diff --git a/.changeset/slimy-cougars-rush.md b/.changeset/slimy-cougars-rush.md new file mode 100644 index 000000000..7f05afa3e --- /dev/null +++ b/.changeset/slimy-cougars-rush.md @@ -0,0 +1,5 @@ +--- +'@powersync/common': patch +--- + +Include metadata and previous values when serializing CRUD entries to JSON. diff --git a/packages/common/src/client/sync/bucket/CrudEntry.ts b/packages/common/src/client/sync/bucket/CrudEntry.ts index 1d0133486..54af6e6b7 100644 --- a/packages/common/src/client/sync/bucket/CrudEntry.ts +++ b/packages/common/src/client/sync/bucket/CrudEntry.ts @@ -42,6 +42,8 @@ type CrudEntryOutputJSON = { id: string; tx_id?: number; data?: Record; + old?: Record; + metadata?: string; }; /** @@ -132,7 +134,9 @@ export class CrudEntry { type: this.table, id: this.id, tx_id: this.transactionId, - data: this.opData + data: this.opData, + old: this.previousValues, + metadata: this.metadata }; } @@ -154,6 +158,15 @@ export class CrudEntry { * Generates an array for use in deep comparison operations */ toComparisonArray() { - return [this.transactionId, this.clientId, this.op, this.table, this.id, this.opData]; + return [ + this.transactionId, + this.clientId, + this.op, + this.table, + this.id, + this.opData, + this.previousValues, + this.metadata + ]; } } diff --git a/packages/node/tests/crud.test.ts b/packages/node/tests/crud.test.ts index d9f35c57d..5ab66196c 100644 --- a/packages/node/tests/crud.test.ts +++ b/packages/node/tests/crud.test.ts @@ -14,9 +14,10 @@ databaseTest('include metadata', async ({ database }) => { }); await database.updateSchema(schema); await database.execute('INSERT INTO lists (id, name, _metadata) VALUES (uuid(), ?, ?);', ['entry', 'so meta']); - + const batch = await database.getNextCrudTransaction(); expect(batch?.crud[0].metadata).toBe('so meta'); + expect(JSON.stringify(batch?.crud[0])).toContain('"metadata":"so meta"'); }); databaseTest('include old values', async ({ database }) => { @@ -30,12 +31,18 @@ databaseTest('include old values', async ({ database }) => { ) }); await database.updateSchema(schema); - await database.execute('INSERT INTO lists (id, name) VALUES (uuid(), ?);', ['entry']); + await database.execute('INSERT INTO lists (id, name) VALUES (?, ?);', [ + 'a185b7e1-dffa-4a9a-888c-15c0f0cac4b3', + 'entry' + ]); await database.execute('DELETE FROM ps_crud;'); await database.execute('UPDATE lists SET name = ?', ['new name']); - + const batch = await database.getNextCrudTransaction(); - expect(batch?.crud[0].previousValues).toStrictEqual({name: 'entry'}); + expect(batch?.crud[0].previousValues).toStrictEqual({ name: 'entry' }); + expect(JSON.stringify(batch?.crud[0])).toBe( + '{"op_id":2,"op":"PATCH","type":"lists","id":"a185b7e1-dffa-4a9a-888c-15c0f0cac4b3","tx_id":2,"data":{"name":"new name"},"old":{"name":"entry"}}' + ); }); databaseTest('include old values with column filter', async ({ database }) => { @@ -53,9 +60,9 @@ databaseTest('include old values with column filter', async ({ database }) => { await database.execute('INSERT INTO lists (id, name, content) VALUES (uuid(), ?, ?);', ['name', 'content']); await database.execute('DELETE FROM ps_crud;'); await database.execute('UPDATE lists SET name = ?, content = ?', ['new name', 'new content']); - + const batch = await database.getNextCrudTransaction(); - expect(batch?.crud[0].previousValues).toStrictEqual({name: 'name'}); + expect(batch?.crud[0].previousValues).toStrictEqual({ name: 'name' }); }); databaseTest('include old values when changed', async ({ database }) => { @@ -73,9 +80,9 @@ databaseTest('include old values when changed', async ({ database }) => { await database.execute('INSERT INTO lists (id, name, content) VALUES (uuid(), ?, ?);', ['name', 'content']); await database.execute('DELETE FROM ps_crud;'); await database.execute('UPDATE lists SET name = ?', ['new name']); - + const batch = await database.getNextCrudTransaction(); - expect(batch?.crud[0].previousValues).toStrictEqual({name: 'name'}); + expect(batch?.crud[0].previousValues).toStrictEqual({ name: 'name' }); }); databaseTest('ignore empty update', async ({ database }) => { @@ -92,7 +99,7 @@ databaseTest('ignore empty update', async ({ database }) => { await database.execute('INSERT INTO lists (id, name) VALUES (uuid(), ?);', ['name']); await database.execute('DELETE FROM ps_crud;'); await database.execute('UPDATE lists SET name = ?', ['name']); - + const batch = await database.getNextCrudTransaction(); expect(batch).toBeNull(); });