Move migration logic to backend

This commit is contained in:
Adria Navarro 2024-05-02 11:50:11 +01:00
parent d39c9bd3dd
commit 569488deee
4 changed files with 89 additions and 67 deletions

View File

@ -180,5 +180,5 @@ export async function migrate(ctx: UserCtx<MigrateRequest, MigrateResponse>) {
} }
ctx.status = 200 ctx.status = 200
ctx.body = { message: `Column ${oldColumn.name} migrated.` } ctx.body = { message: `Column ${oldColumn} migrated.` }
} }

View File

@ -493,16 +493,16 @@ describe.each([
) )
await config.api.table.migrate(table._id!, { await config.api.table.migrate(table._id!, {
oldColumn: table.schema["user relationship"], oldColumn: "user relationship",
newColumn: { newColumn: "user column",
name: "user column",
type: FieldType.BB_REFERENCE_SINGLE,
subtype: BBReferenceFieldSubType.USER,
},
}) })
const migratedTable = await config.api.table.get(table._id!) 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() expect(migratedTable.schema["user relationship"]).not.toBeDefined()
const migratedRows = await config.api.row.fetch(table._id!) const migratedRows = await config.api.row.fetch(table._id!)
@ -558,16 +558,19 @@ describe.each([
) )
await config.api.table.migrate(table._id!, { await config.api.table.migrate(table._id!, {
oldColumn: table.schema["user relationship"], oldColumn: "user relationship",
newColumn: { newColumn: "user column",
name: "user column",
type: FieldType.BB_REFERENCE,
subtype: BBReferenceFieldSubType.USER,
},
}) })
const migratedTable = await config.api.table.get(table._id!) 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() expect(migratedTable.schema["user relationship"]).not.toBeDefined()
const migratedRow = await config.api.row.get(table._id!, testRow._id!) const migratedRow = await config.api.row.get(table._id!, testRow._id!)
@ -610,16 +613,19 @@ describe.each([
}) })
await config.api.table.migrate(table._id!, { await config.api.table.migrate(table._id!, {
oldColumn: table.schema["user relationship"], oldColumn: "user relationship",
newColumn: { newColumn: "user column",
name: "user column",
type: FieldType.BB_REFERENCE,
subtype: BBReferenceFieldSubType.USER,
},
}) })
const migratedTable = await config.api.table.get(table._id!) 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() expect(migratedTable.schema["user relationship"]).not.toBeDefined()
const row1Migrated = await config.api.row.get(table._id!, row1._id!) const row1Migrated = await config.api.row.get(table._id!, row1._id!)
@ -665,16 +671,19 @@ describe.each([
}) })
await config.api.table.migrate(table._id!, { await config.api.table.migrate(table._id!, {
oldColumn: table.schema["user relationship"], oldColumn: "user relationship",
newColumn: { newColumn: "user column",
name: "user column",
type: FieldType.BB_REFERENCE,
subtype: BBReferenceFieldSubType.USER,
},
}) })
const migratedTable = await config.api.table.get(table._id!) 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() expect(migratedTable.schema["user relationship"]).not.toBeDefined()
const row1Migrated = await config.api.row.get(table._id!, row1._id!) 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 let table: Table
beforeAll(async () => { beforeAll(async () => {
table = await config.api.table.save( table = await config.api.table.save(
@ -724,12 +733,8 @@ describe.each([
await config.api.table.migrate( await config.api.table.migrate(
table._id!, table._id!,
{ {
oldColumn: table.schema["user relationship"], oldColumn: "user relationship",
newColumn: { newColumn: "",
name: "",
type: FieldType.BB_REFERENCE,
subtype: BBReferenceFieldSubType.USER,
},
}, },
{ status: 400 } { status: 400 }
) )
@ -739,12 +744,8 @@ describe.each([
await config.api.table.migrate( await config.api.table.migrate(
table._id!, table._id!,
{ {
oldColumn: table.schema["user relationship"], oldColumn: "user relationship",
newColumn: { newColumn: "_id",
name: "_id",
type: FieldType.BB_REFERENCE,
subtype: BBReferenceFieldSubType.USER,
},
}, },
{ status: 400 } { status: 400 }
) )
@ -754,12 +755,8 @@ describe.each([
await config.api.table.migrate( await config.api.table.migrate(
table._id!, table._id!,
{ {
oldColumn: table.schema["user relationship"], oldColumn: "user relationship",
newColumn: { newColumn: "num",
name: "num",
type: FieldType.BB_REFERENCE,
subtype: BBReferenceFieldSubType.USER,
},
}, },
{ status: 400 } { status: 400 }
) )
@ -769,16 +766,8 @@ describe.each([
await config.api.table.migrate( await config.api.table.migrate(
table._id!, table._id!,
{ {
oldColumn: { oldColumn: "not a column",
name: "not a column", newColumn: "new column",
type: FieldType.BB_REFERENCE,
subtype: BBReferenceFieldSubType.USER,
},
newColumn: {
name: "new column",
type: FieldType.BB_REFERENCE,
subtype: BBReferenceFieldSubType.USER,
},
}, },
{ status: 400 } { status: 400 }
) )

View File

@ -25,25 +25,58 @@ export interface MigrationResult {
export async function migrate( export async function migrate(
table: Table, table: Table,
oldColumn: FieldSchema, oldColumnName: string,
newColumn: FieldSchema newColumnName: string
): Promise<MigrationResult> { ): Promise<MigrationResult> {
if (newColumn.name in table.schema) { if (newColumnName in table.schema) {
throw new BadRequestError(`Column "${newColumn.name}" already exists`) throw new BadRequestError(`Column "${newColumnName}" already exists`)
} }
if (newColumn.name === "") { if (newColumnName === "") {
throw new BadRequestError(`Column name cannot be empty`) 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`) 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.schema[newColumn.name] = newColumn
table = await sdk.tables.saveTable(table) table = await sdk.tables.saveTable(table)
let migrator = getColumnMigrator(table, oldColumn, newColumn) const migrator = getColumnMigrator(table, oldColumn, newColumn)
try { try {
return await migrator.doMigration() return await migrator.doMigration()
} catch (e) { } catch (e) {

View File

@ -31,8 +31,8 @@ export interface BulkImportResponse {
} }
export interface MigrateRequest { export interface MigrateRequest {
oldColumn: FieldSchema oldColumn: string
newColumn: FieldSchema newColumn: string
} }
export interface MigrateResponse { export interface MigrateResponse {