diff --git a/.changeset/cli-diff-insert-seed-note.md b/.changeset/cli-diff-insert-seed-note.md new file mode 100644 index 00000000000..bd96436585f --- /dev/null +++ b/.changeset/cli-diff-insert-seed-note.md @@ -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 diff --git a/packages/cli/src/commands/diff.ts b/packages/cli/src/commands/diff.ts index 5a8ab9b986c..b02482c057c 100644 --- a/packages/cli/src/commands/diff.ts +++ b/packages/cli/src/commands/diff.ts @@ -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 ''; } diff --git a/packages/cli/test/diff-upgrade-plan.test.ts b/packages/cli/test/diff-upgrade-plan.test.ts index 8bf07d95b24..6ef764a7dbb 100644 --- a/packages/cli/test/diff-upgrade-plan.test.ts +++ b/packages/cli/test/diff-upgrade-plan.test.ts @@ -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' }, + ]); + }); });