From 569488deeea8cfa59f561e29d45579f21ff39bef Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Thu, 2 May 2024 11:50:11 +0100 Subject: [PATCH] Move migration logic to backend --- .../server/src/api/controllers/table/index.ts | 2 +- .../server/src/api/routes/tests/table.spec.ts | 103 ++++++++---------- .../server/src/sdk/app/tables/migration.ts | 47 ++++++-- packages/types/src/api/web/app/table.ts | 4 +- 4 files changed, 89 insertions(+), 67 deletions(-) diff --git a/packages/server/src/api/controllers/table/index.ts b/packages/server/src/api/controllers/table/index.ts index 63ce00c5ef..eae5204c7e 100644 --- a/packages/server/src/api/controllers/table/index.ts +++ b/packages/server/src/api/controllers/table/index.ts @@ -180,5 +180,5 @@ export async function migrate(ctx: UserCtx) { } ctx.status = 200 - ctx.body = { message: `Column ${oldColumn.name} migrated.` } + ctx.body = { message: `Column ${oldColumn} migrated.` } } diff --git a/packages/server/src/api/routes/tests/table.spec.ts b/packages/server/src/api/routes/tests/table.spec.ts index 2aa44ce64f..33bd3dba5c 100644 --- a/packages/server/src/api/routes/tests/table.spec.ts +++ b/packages/server/src/api/routes/tests/table.spec.ts @@ -493,16 +493,16 @@ describe.each([ ) await config.api.table.migrate(table._id!, { - oldColumn: table.schema["user relationship"], - newColumn: { - name: "user column", - type: FieldType.BB_REFERENCE_SINGLE, - subtype: BBReferenceFieldSubType.USER, - }, + oldColumn: "user relationship", + newColumn: "user column", }) const migratedTable = await config.api.table.get(table._id!) - expect(migratedTable.schema["user column"]).toBeDefined() + expect(migratedTable.schema["user column"]).toEqual({ + name: "user column", + type: FieldType.BB_REFERENCE_SINGLE, + subtype: BBReferenceFieldSubType.USER, + }) expect(migratedTable.schema["user relationship"]).not.toBeDefined() const migratedRows = await config.api.row.fetch(table._id!) @@ -558,16 +558,19 @@ describe.each([ ) await config.api.table.migrate(table._id!, { - oldColumn: table.schema["user relationship"], - newColumn: { - name: "user column", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - }, + oldColumn: "user relationship", + newColumn: "user column", }) const migratedTable = await config.api.table.get(table._id!) - expect(migratedTable.schema["user column"]).toBeDefined() + expect(migratedTable.schema["user column"]).toEqual({ + name: "user column", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + constraints: { + type: "array", + }, + }) expect(migratedTable.schema["user relationship"]).not.toBeDefined() const migratedRow = await config.api.row.get(table._id!, testRow._id!) @@ -610,16 +613,19 @@ describe.each([ }) await config.api.table.migrate(table._id!, { - oldColumn: table.schema["user relationship"], - newColumn: { - name: "user column", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - }, + oldColumn: "user relationship", + newColumn: "user column", }) const migratedTable = await config.api.table.get(table._id!) - expect(migratedTable.schema["user column"]).toBeDefined() + expect(migratedTable.schema["user column"]).toEqual({ + name: "user column", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + constraints: { + type: "array", + }, + }) expect(migratedTable.schema["user relationship"]).not.toBeDefined() const row1Migrated = await config.api.row.get(table._id!, row1._id!) @@ -665,16 +671,19 @@ describe.each([ }) await config.api.table.migrate(table._id!, { - oldColumn: table.schema["user relationship"], - newColumn: { - name: "user column", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - }, + oldColumn: "user relationship", + newColumn: "user column", }) const migratedTable = await config.api.table.get(table._id!) - expect(migratedTable.schema["user column"]).toBeDefined() + expect(migratedTable.schema["user column"]).toEqual({ + name: "user column", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + constraints: { + type: "array", + }, + }) expect(migratedTable.schema["user relationship"]).not.toBeDefined() const row1Migrated = await config.api.row.get(table._id!, row1._id!) @@ -690,7 +699,7 @@ describe.each([ ]) }) - describe("unhappy paths", () => { + describe.only("unhappy paths", () => { let table: Table beforeAll(async () => { table = await config.api.table.save( @@ -724,12 +733,8 @@ describe.each([ await config.api.table.migrate( table._id!, { - oldColumn: table.schema["user relationship"], - newColumn: { - name: "", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - }, + oldColumn: "user relationship", + newColumn: "", }, { status: 400 } ) @@ -739,12 +744,8 @@ describe.each([ await config.api.table.migrate( table._id!, { - oldColumn: table.schema["user relationship"], - newColumn: { - name: "_id", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - }, + oldColumn: "user relationship", + newColumn: "_id", }, { status: 400 } ) @@ -754,12 +755,8 @@ describe.each([ await config.api.table.migrate( table._id!, { - oldColumn: table.schema["user relationship"], - newColumn: { - name: "num", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - }, + oldColumn: "user relationship", + newColumn: "num", }, { status: 400 } ) @@ -769,16 +766,8 @@ describe.each([ await config.api.table.migrate( table._id!, { - oldColumn: { - name: "not a column", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - }, - newColumn: { - name: "new column", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - }, + oldColumn: "not a column", + newColumn: "new column", }, { status: 400 } ) diff --git a/packages/server/src/sdk/app/tables/migration.ts b/packages/server/src/sdk/app/tables/migration.ts index 732773f164..d0decf01f6 100644 --- a/packages/server/src/sdk/app/tables/migration.ts +++ b/packages/server/src/sdk/app/tables/migration.ts @@ -25,25 +25,58 @@ export interface MigrationResult { export async function migrate( table: Table, - oldColumn: FieldSchema, - newColumn: FieldSchema + oldColumnName: string, + newColumnName: string ): Promise { - if (newColumn.name in table.schema) { - throw new BadRequestError(`Column "${newColumn.name}" already exists`) + if (newColumnName in table.schema) { + throw new BadRequestError(`Column "${newColumnName}" already exists`) } - if (newColumn.name === "") { + if (newColumnName === "") { throw new BadRequestError(`Column name cannot be empty`) } - if (dbCore.isInternalColumnName(newColumn.name)) { + if (dbCore.isInternalColumnName(newColumnName)) { throw new BadRequestError(`Column name cannot be a reserved column name`) } + const oldColumn = table.schema[oldColumnName] + + if (!oldColumn) { + throw new BadRequestError( + `Column "${oldColumnName}" does not exist on table "${table.name}"` + ) + } + + if ( + oldColumn.type !== FieldType.LINK || + oldColumn.tableId !== InternalTable.USER_METADATA + ) { + throw new BadRequestError( + `Only user relationship migration columns is currently supported` + ) + } + + const type = + oldColumn.relationshipType === RelationshipType.ONE_TO_MANY + ? FieldType.BB_REFERENCE_SINGLE + : FieldType.BB_REFERENCE + const newColumn: FieldSchema = { + name: newColumnName, + type, + subtype: BBReferenceFieldSubType.USER, + } + + if (newColumn.type === FieldType.BB_REFERENCE) { + newColumn.constraints = { + type: "array", + } + } + table.schema[newColumn.name] = newColumn table = await sdk.tables.saveTable(table) - let migrator = getColumnMigrator(table, oldColumn, newColumn) + const migrator = getColumnMigrator(table, oldColumn, newColumn) try { return await migrator.doMigration() } catch (e) { diff --git a/packages/types/src/api/web/app/table.ts b/packages/types/src/api/web/app/table.ts index ffe59ae395..4e2e84baa0 100644 --- a/packages/types/src/api/web/app/table.ts +++ b/packages/types/src/api/web/app/table.ts @@ -31,8 +31,8 @@ export interface BulkImportResponse { } export interface MigrateRequest { - oldColumn: FieldSchema - newColumn: FieldSchema + oldColumn: string + newColumn: string } export interface MigrateResponse {