From 684a79abef5b25ff5b8e37527de6f0f0d262ae72 Mon Sep 17 00:00:00 2001 From: Ido Kahlon Date: Wed, 11 Jan 2023 16:45:22 +0200 Subject: [PATCH 1/3] update - from patch to fully replace --- .../test/e2e/app_data.e2e.spec.ts | 26 ++++++++++++++++++- .../src/converters/item_transformer.js | 7 ----- .../src/converters/item_transformer.spec.ts | 9 ------- .../src/service/schema_aware_data.ts | 12 +++------ .../test/drivers/item_patcher_test_support.ts | 5 ---- 5 files changed, 29 insertions(+), 30 deletions(-) diff --git a/apps/velo-external-db/test/e2e/app_data.e2e.spec.ts b/apps/velo-external-db/test/e2e/app_data.e2e.spec.ts index 19d359adf..b4f9ee92e 100644 --- a/apps/velo-external-db/test/e2e/app_data.e2e.spec.ts +++ b/apps/velo-external-db/test/e2e/app_data.e2e.spec.ts @@ -206,7 +206,7 @@ describe(`Velo External DB Data REST API: ${currentDbImplementationName()}`, () }) - test('update undefined to number columns should insert nulls', async() => { + test('update explicit null to number columns should insert nulls', async() => { await schema.givenCollection(ctx.collectionName, ctx.numberColumns, authOwner) await data.givenItems([ctx.numberItem], ctx.collectionName, authAdmin) ctx.numberItem[ctx.numberColumns[0].name] = null @@ -226,6 +226,28 @@ describe(`Velo External DB Data REST API: ${currentDbImplementationName()}`, () }) + test('update partial item should insert null for all the non-system fields', async() => { + await schema.givenCollection(ctx.collectionName, ctx.numberColumns, authOwner) + await data.givenItems([ctx.numberItem], ctx.collectionName, authOwner) + + const itemToUpdate = { + _id: ctx.numberItem._id, + [ctx.numberColumns[0].name]: ctx.randomNumberColumnValue + } + + await axios.post('/data/update', { collectionName: ctx.collectionName, item: itemToUpdate }, authAdmin) + + await expect(data.expectAllDataIn(ctx.collectionName, authAdmin)).resolves.toEqual({ + items: [ + expect.objectContaining({ + _id: ctx.numberItem._id, + [ctx.numberColumns[0].name]: ctx.randomNumberColumnValue, + [ctx.numberColumns[1].name]: null, + }) + ], totalCount: 1 + }) + }) + const ctx = { collectionName: Uninitialized, column: Uninitialized, @@ -238,6 +260,7 @@ describe(`Velo External DB Data REST API: ${currentDbImplementationName()}`, () numberItem: Uninitialized, anotherNumberItem: Uninitialized, pastVeloDate: Uninitialized, + randomNumberColumnValue: Uninitialized, } afterAll(async() => await teardownApp()) @@ -254,5 +277,6 @@ describe(`Velo External DB Data REST API: ${currentDbImplementationName()}`, () ctx.numberItem = genCommon.randomNumberEntity(ctx.numberColumns) ctx.anotherNumberItem = genCommon.randomNumberEntity(ctx.numberColumns) ctx.pastVeloDate = genCommon.pastVeloDate() + ctx.randomNumberColumnValue = chance.integer({ min: 0, max: 100 }) }) }) diff --git a/libs/velo-external-db-core/src/converters/item_transformer.js b/libs/velo-external-db-core/src/converters/item_transformer.js index a469a516e..05c29e4f7 100644 --- a/libs/velo-external-db-core/src/converters/item_transformer.js +++ b/libs/velo-external-db-core/src/converters/item_transformer.js @@ -11,17 +11,10 @@ class ItemTransformer { return items.map(i => this.prepareForInsert(i, fields)) } - prepareItemsForUpdate(items, fields) { - return items.map(i => this.prepareForUpdate(i, fields)) - } - prepareForInsert(item, fields) { return this.unpackDates(fields.reduce((pv, f) => ({ ...pv, [f.field]: item[f.field] || this.defaultValueFor(f) }), {})) } - prepareForUpdate(item, fields) { - return this.unpackDates(fields.reduce((pv, f) => f.field in item ? ({ ...pv, [f.field]: item[f.field] }) : pv, {})) - } patchItemsBooleanFields(items, fields) { return items.map(i => this.patchBoolean(i, fields.filter(f => f.type === 'boolean'))) diff --git a/libs/velo-external-db-core/src/converters/item_transformer.spec.ts b/libs/velo-external-db-core/src/converters/item_transformer.spec.ts index 1887aecda..dff8e5872 100644 --- a/libs/velo-external-db-core/src/converters/item_transformer.spec.ts +++ b/libs/velo-external-db-core/src/converters/item_transformer.spec.ts @@ -69,16 +69,7 @@ describe('Item Transformer', () => { }) }) - describe('prepare for update', () => { - test('prepare for update will remove non existing fields', async() => { - expect(env.itemTransformer.prepareForUpdate({ ...ctx.obj, someProp: 'whatever' }, ctx.objSchemaFields)).toEqual( ctx.obj ) - }) - test('prepare for insert will unpack velo date', () => { - const objWithVeloDate = { ...ctx.obj, [ctx.property]: ctx.veloDate } - expect(env.itemTransformer.prepareForUpdate(objWithVeloDate, [...ctx.objSchemaFields, { field: ctx.property, type: 'date' }])).toEqual( { ...ctx.obj, [ctx.property]: new Date(ctx.veloDate.$date) } ) - }) - }) describe('unpack dates', () => { test('unpack dates will duplicate object and do nothing is date is not there', async() => { diff --git a/libs/velo-external-db-core/src/service/schema_aware_data.ts b/libs/velo-external-db-core/src/service/schema_aware_data.ts index 4479de8d1..c72df4eae 100644 --- a/libs/velo-external-db-core/src/service/schema_aware_data.ts +++ b/libs/velo-external-db-core/src/service/schema_aware_data.ts @@ -51,12 +51,14 @@ export default class SchemaAwareDataService { } async update(collectionName: string, item: Item) { - const prepared = await this.prepareItemsForUpdate(collectionName, [item]) + const fields = await this.schemaInformation.schemaFieldsFor(collectionName) + const prepared = await this.prepareItemsForInsert(fields, [item]) return await this.dataService.update(collectionName, prepared[0]) } async bulkUpdate(collectionName: string, items: Item[]) { - const prepared = await this.prepareItemsForUpdate(collectionName, items) + const fields = await this.schemaInformation.schemaFieldsFor(collectionName) + const prepared = await this.prepareItemsForInsert(fields, items) return await this.dataService.bulkUpdate(collectionName, prepared) } @@ -98,12 +100,6 @@ export default class SchemaAwareDataService { this.queryValidator.validateProjection(schemaFields, projection) } - async prepareItemsForUpdate(collectionName: string, items: Item[]): Promise { - const fields = await this.schemaInformation.schemaFieldsFor(collectionName) - - return this.itemTransformer.prepareItemsForUpdate(items, fields) - } - async prepareItemsForInsert(fields: any, items: any[]): Promise { return this.itemTransformer.prepareItemsForInsert(items, fields) } diff --git a/libs/velo-external-db-core/test/drivers/item_patcher_test_support.ts b/libs/velo-external-db-core/test/drivers/item_patcher_test_support.ts index 0025ca183..324abad99 100644 --- a/libs/velo-external-db-core/test/drivers/item_patcher_test_support.ts +++ b/libs/velo-external-db-core/test/drivers/item_patcher_test_support.ts @@ -3,7 +3,6 @@ import { SystemFields } from '@wix-velo/velo-external-db-commons' export const itemTransformer = { prepareItemsForInsert: jest.fn(), - prepareItemsForUpdate: jest.fn(), patchItems: jest.fn() } @@ -13,9 +12,6 @@ export const givenPreparedItemsForInsertWith = (prepared: any, items: any) => when(itemTransformer.prepareItemsForInsert).calledWith(items, systemFields) .mockReturnValue(prepared) -export const givenPreparedItemsForUpdateWith = (prepared: any, items: any) => - when(itemTransformer.prepareItemsForUpdate).calledWith(items, systemFields) - .mockReturnValue(prepared) export const givenPatchedBooleanFieldsWith = (patched: any, items: any, fields?: { field: string, type: string, subtype?: string }[]) => when(itemTransformer.patchItems).calledWith(items, fields || systemFields) @@ -23,7 +19,6 @@ export const givenPatchedBooleanFieldsWith = (patched: any, items: any, fields?: export const reset = () => { itemTransformer.prepareItemsForInsert.mockClear() - itemTransformer.prepareItemsForUpdate.mockClear() itemTransformer.patchItems.mockClear() } From 0d07c8b6c358c0f1f3f70ee3d466d54cd69ddf0b Mon Sep 17 00:00:00 2001 From: Ido Kahlon Date: Wed, 11 Jan 2023 16:50:40 +0200 Subject: [PATCH 2/3] fix schema_aware test --- .../src/service/schema_aware_data.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/velo-external-db-core/src/service/schema_aware_data.spec.ts b/libs/velo-external-db-core/src/service/schema_aware_data.spec.ts index c1615d19b..8a626c434 100644 --- a/libs/velo-external-db-core/src/service/schema_aware_data.spec.ts +++ b/libs/velo-external-db-core/src/service/schema_aware_data.spec.ts @@ -58,7 +58,7 @@ describe ('Schema Aware Data Service', () => { test('update will prepare item for update and call data service with the prepared item', async() => { schema.givenDefaultSchemaFor(ctx.collectionName) - patcher.givenPreparedItemsForUpdateWith([ctx.preparedEntity], [ctx.entityWithExtraProps]) + patcher.givenPreparedItemsForInsertWith([ctx.preparedEntity], [ctx.entityWithExtraProps]) data.givenUpdateResult(ctx.preparedEntity, ctx.collectionName) return expect(env.schemaAwareDataService.update(ctx.collectionName, ctx.entityWithExtraProps)).resolves.toEqual({ item: ctx.preparedEntity }) @@ -66,7 +66,7 @@ describe ('Schema Aware Data Service', () => { test('bulk update will prepare items for update and call data service with the prepared items', async() => { schema.givenDefaultSchemaFor(ctx.collectionName) - patcher.givenPreparedItemsForUpdateWith(ctx.preparedEntities, ctx.entitiesWithExtraProps) + patcher.givenPreparedItemsForInsertWith(ctx.preparedEntities, ctx.entitiesWithExtraProps) data.givenBulkUpdateResult(ctx.preparedEntities, ctx.collectionName) return expect(env.schemaAwareDataService.bulkUpdate(ctx.collectionName, ctx.entitiesWithExtraProps)).resolves.toEqual({ items: ctx.preparedEntities }) From ad65fd3fefd2b5bc25499e13a4a1ef1ac8defe4b Mon Sep 17 00:00:00 2001 From: Ido Kahlon Date: Wed, 22 Feb 2023 11:46:20 +0200 Subject: [PATCH 3/3] update core package --- libs/velo-external-db-core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/velo-external-db-core/package.json b/libs/velo-external-db-core/package.json index d144d3bcd..87af1f2eb 100644 --- a/libs/velo-external-db-core/package.json +++ b/libs/velo-external-db-core/package.json @@ -1,5 +1,5 @@ { "name": "@wix-velo/velo-external-db-core", - "version": "1.2.4", + "version": "2.0.0", "type": "commonjs" }