From daee212c419179730ebee273b2373ef25f1db1b1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 19 May 2026 10:18:58 +0000 Subject: [PATCH 1/2] Add reproduction test for composite primary key preInsert hook Agent-Logs-Url: https://github.com/pubkey/rxdb/sessions/08237573-b364-44bc-847f-90e402f47a85 Co-authored-by: pubkey <8926560+pubkey@users.noreply.github.com> --- ...d-test-composite-primary-preinsert-hook.md | 1 + test/unit/hooks.test.ts | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 orga/changelog/add-test-composite-primary-preinsert-hook.md diff --git a/orga/changelog/add-test-composite-primary-preinsert-hook.md b/orga/changelog/add-test-composite-primary-preinsert-hook.md new file mode 100644 index 00000000000..518fbc35f37 --- /dev/null +++ b/orga/changelog/add-test-composite-primary-preinsert-hook.md @@ -0,0 +1 @@ +- TEST add reproduction for composite primary key auto-fill when only `name` and `number` are set in a `preInsert` hook without `id` (https://github.com/pubkey/rxdb/pull/8527) diff --git a/test/unit/hooks.test.ts b/test/unit/hooks.test.ts index b5095bc0357..2ff46328c26 100644 --- a/test/unit/hooks.test.ts +++ b/test/unit/hooks.test.ts @@ -559,5 +559,58 @@ describe('hooks.test.js', () => { assert.strictEqual(allDocs.length, 0); c.database.close(); }); + it('should auto-generate composite primary key when set in preInsert hook', async () => { + const db = await createRxDatabase({ + name: randomToken(10), + storage: config.storage.getStorage(), + multiInstance: true + }); + const collections = await db.addCollections({ + humans: { + schema: { + version: 0, + primaryKey: { + key: 'id', + fields: ['name', 'number'], + separator: '|' + }, + type: 'object', + properties: { + id: { + type: 'string', + maxLength: 100 + }, + name: { + type: 'string', + maxLength: 100 + }, + number: { + type: 'integer', + minimum: 0, + maximum: 9999 + } + }, + required: [ + 'id', + 'name', + 'number' + ] + } + } + }); + const collection = collections.humans; + + collection.preInsert((docData) => { + docData.name = 'alice'; + docData.number = 5; + }, false); + + const doc = await collection.insert({} as any); + assert.strictEqual(doc.id, 'alice|5'); + assert.strictEqual(doc.name, 'alice'); + assert.strictEqual(doc.number, 5); + + db.close(); + }); }); }); From 541bc57d09beb11026a028d04d21e8b29acf9473 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 19 May 2026 10:41:59 +0000 Subject: [PATCH 2/2] Fix composite primary fill after preInsert hooks Agent-Logs-Url: https://github.com/pubkey/rxdb/sessions/8d80a707-d21c-45b6-95ed-f0d03a6e3bfb Co-authored-by: pubkey <8926560+pubkey@users.noreply.github.com> --- orga/changelog/fix-composite-primary-preinsert-hook.md | 1 + src/rx-collection-helper.ts | 5 +++-- src/rx-collection.ts | 10 +++++++++- 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 orga/changelog/fix-composite-primary-preinsert-hook.md diff --git a/orga/changelog/fix-composite-primary-preinsert-hook.md b/orga/changelog/fix-composite-primary-preinsert-hook.md new file mode 100644 index 00000000000..08310b1e34b --- /dev/null +++ b/orga/changelog/fix-composite-primary-preinsert-hook.md @@ -0,0 +1 @@ +- FIX allow `preInsert` hooks to set composite primary key fields (for example `name` and `number`) without manually setting `id`, so RxDB computes the composite primary key afterwards (https://github.com/pubkey/rxdb/pull/8527) diff --git a/src/rx-collection-helper.ts b/src/rx-collection-helper.ts index 273d140989d..e48d7d38c1e 100644 --- a/src/rx-collection-helper.ts +++ b/src/rx-collection-helper.ts @@ -33,11 +33,12 @@ import { newRxError } from './rx-error.ts'; */ export function fillObjectDataBeforeInsert( schema: RxSchema, - data: Partial> | any + data: Partial> | any, + skipPrimaryKeyFill: boolean = false ): RxDocumentData { data = flatClone(data); data = fillObjectWithDefaults(schema, data); - if (typeof schema.jsonSchema.primaryKey !== 'string') { + if (!skipPrimaryKeyFill && typeof schema.jsonSchema.primaryKey !== 'string') { data = fillPrimaryKey( schema.primaryPath, schema.jsonSchema, diff --git a/src/rx-collection.ts b/src/rx-collection.ts index d8fb5bf90dd..bde6a05001c 100644 --- a/src/rx-collection.ts +++ b/src/rx-collection.ts @@ -52,6 +52,7 @@ import { runAsyncPluginHooks, runPluginHooks } from './hooks.ts'; +import { fillPrimaryKey } from './rx-schema-helper.ts'; import { Subscription, @@ -443,9 +444,16 @@ export class RxCollectionBase< if (this.hasHooks('pre', 'insert')) { insertRows = await Promise.all( docsData.map(docData => { - const useDocData = fillObjectDataBeforeInsert(this.schema, docData); + const useDocData = fillObjectDataBeforeInsert(this.schema, docData, true); return this._runHooks('pre', 'insert', useDocData) .then(() => { + if (typeof this.schema.jsonSchema.primaryKey !== 'string') { + fillPrimaryKey( + this.schema.primaryPath as any, + this.schema.jsonSchema as any, + useDocData as any + ); + } ids.add((useDocData as any)[primaryPath]); return { document: useDocData }; });