Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/cli-diff-insert-seed-note.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@objectstack/cli': patch
---

fix(cli): `os diff` now says what a replay does to a seed dataset in mode `insert`, as it already did for `replace`: a replay inserts its records again, and a row the database refuses is that row's error. The loader's `insert` arm inserts every record without looking for a match, so the plan no longer reads an `insert` dataset as harmless.

Clause-②: no
Metadata-protocol: none
1 change: 1 addition & 0 deletions packages/cli/src/commands/diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ function diffNamedArrays(
function seedModeNote(mode: string): string {
if (seedModeOverwritesMatchedRows(mode)) return '; a replay writes its columns over the rows it matches';
if (mode === 'replace') return '; a replay deletes nothing and inserts these again, so rows already in the table stay';
if (mode === 'insert') return "; a replay inserts these again, and a row the database refuses is that row's error";
return '';
}

Expand Down
24 changes: 24 additions & 0 deletions packages/cli/test/diff-upgrade-plan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,28 @@ describe('os diff — what the upgrade plan adds', () => {
{ type: 'modified', category: 'data', name: 'acme_region', breaking: false, detail: 'seed dataset changed: records; mode ignore' },
]);
});

it('an insert dataset, added or changed, says a replay inserts its records again; ignore stays silent', () => {
const before = lead({}, [
{ object: 'acme_source', mode: 'insert', records: [{ name: 'web' }] },
{ object: 'acme_region', mode: 'ignore', records: [{ name: 'emea' }] },
]);
const after = lead({}, [
{ object: 'acme_source', mode: 'insert', records: [{ name: 'web' }, { name: 'event' }] },
{ object: 'acme_region', mode: 'ignore', records: [{ name: 'apac' }] },
{ object: 'acme_channel', mode: 'insert', records: [{ name: 'email' }] },
]);
const insertNote = "a replay inserts these again, and a row the database refuses is that row's error";
expect(diffStacks(before, after)).toEqual([
{
type: 'added', category: 'data', name: 'acme_channel', breaking: false,
detail: `seed dataset added: 1 record(s); mode insert; ${insertNote}`,
},
{
type: 'modified', category: 'data', name: 'acme_source', breaking: false,
detail: `seed dataset changed: records; mode insert; ${insertNote}`,
},
{ type: 'modified', category: 'data', name: 'acme_region', breaking: false, detail: 'seed dataset changed: records; mode ignore' },
]);
});
});
Loading