Add field create and delete migration to metadata sync (#2942)

add field create and delete migration to metadata sync
This commit is contained in:
Weiko
2023-12-11 17:42:09 +01:00
committed by GitHub
parent b9de9f1a08
commit d2a42c14d2
4 changed files with 83 additions and 4 deletions

View File

@ -9,6 +9,7 @@ export enum WorkspaceMigrationColumnActionType {
CREATE = 'CREATE',
ALTER = 'ALTER',
RELATION = 'RELATION',
DROP = 'DROP',
}
export type WorkspaceMigrationEnum = string | { from: string; to: string };
@ -41,12 +42,18 @@ export type WorkspaceMigrationColumnRelation = {
isUnique?: boolean;
};
export type WorkspaceMigrationColumnDrop = {
action: WorkspaceMigrationColumnActionType.DROP;
columnName: string;
};
export type WorkspaceMigrationColumnAction = {
action: WorkspaceMigrationColumnActionType;
} & (
| WorkspaceMigrationColumnCreate
| WorkspaceMigrationColumnAlter
| WorkspaceMigrationColumnRelation
| WorkspaceMigrationColumnDrop
);
export type WorkspaceMigrationTableAction = {

View File

@ -187,6 +187,12 @@ export class WorkspaceMigrationRunnerService {
columnMigration,
);
break;
case WorkspaceMigrationColumnActionType.DROP:
await queryRunner.dropColumn(
`${schemaName}.${tableName}`,
columnMigration.columnName,
);
break;
default:
throw new Error(`Migration column action not supported`);
}

View File

@ -144,7 +144,8 @@ function generateFieldMetadata<T extends FieldMetadataType>(
name: fieldKey,
...metadata,
targetColumnMap: targetColumnMap,
isNullable: metadata.type === FieldMetadataType.RELATION ? true : isNullable,
isNullable:
metadata.type === FieldMetadataType.RELATION ? true : isNullable,
isSystem,
isCustom: false,
options: null, // TODO: handle options + stringify for the diff.

View File

@ -125,6 +125,7 @@ export class WorkspaceSyncMetadataService {
if (value === null || typeof value !== 'object') {
return [key, value];
}
return [
key,
filterIgnoredProperties(
@ -134,6 +135,7 @@ export class WorkspaceSyncMetadataService {
if (property !== null && typeof property === 'object') {
return JSON.stringify(property);
}
return property;
},
),
@ -157,6 +159,7 @@ export class WorkspaceSyncMetadataService {
// We only handle CHANGE here as REMOVE and CREATE are handled earlier.
if (diff.type === 'CHANGE') {
const property = diff.path[0];
objectsToUpdate[objectInDB.id] = {
...objectsToUpdate[objectInDB.id],
[property]: diff.value,
@ -166,6 +169,7 @@ export class WorkspaceSyncMetadataService {
for (const diff of fieldsDiff) {
const fieldName = diff.path[0];
if (diff.type === 'CREATE')
fieldsToCreate.push({
...standardObjectFields[fieldName],
@ -175,6 +179,7 @@ export class WorkspaceSyncMetadataService {
fieldsToDelete.push(objectInDBFields[fieldName]);
if (diff.type === 'CHANGE') {
const property = diff.path[diff.path.length - 1];
fieldsToUpdate[objectInDBFields[fieldName].id] = {
...fieldsToUpdate[objectInDBFields[fieldName].id],
[property]: diff.value,
@ -221,6 +226,7 @@ export class WorkspaceSyncMetadataService {
const fieldsToDeleteWithoutRelationType = fieldsToDelete.filter(
(field) => field.type !== FieldMetadataType.RELATION,
);
if (fieldsToDeleteWithoutRelationType.length > 0) {
await this.fieldMetadataRepository.delete(
fieldsToDeleteWithoutRelationType.map((field) => field.id),
@ -233,6 +239,7 @@ export class WorkspaceSyncMetadataService {
objectsToDelete,
fieldsToCreate,
fieldsToDelete,
objectsInDB,
);
// We run syncRelationMetadata after everything to ensure that all objects and fields are
@ -263,7 +270,9 @@ export class WorkspaceSyncMetadataService {
objectsInDBByName,
).reduce((result, currentObject) => {
const key = `${currentObject.fromObjectMetadataId}->${currentObject.fromFieldMetadataId}`;
result[key] = currentObject;
return result;
}, {});
@ -279,7 +288,9 @@ export class WorkspaceSyncMetadataService {
)
.reduce((result, currentObject) => {
const key = `${currentObject.fromObjectMetadataId}->${currentObject.fromFieldMetadataId}`;
result[key] = currentObject;
return result;
}, {});
@ -324,11 +335,12 @@ export class WorkspaceSyncMetadataService {
private async generateMigrationsFromSync(
objectsToCreate: ObjectMetadataEntity[],
_objectsToDelete: ObjectMetadataEntity[],
_fieldsToCreate: FieldMetadataEntity[],
_fieldsToDelete: FieldMetadataEntity[],
fieldsToCreate: FieldMetadataEntity[],
fieldsToDelete: FieldMetadataEntity[],
objectsInDB: ObjectMetadataEntity[],
) {
const migrationsToSave: Partial<WorkspaceMigrationEntity>[] = [];
if (objectsToCreate.length > 0) {
objectsToCreate.map((object) => {
const migrations = [
@ -359,6 +371,59 @@ export class WorkspaceSyncMetadataService {
});
}
// TODO: handle object delete migrations.
// Note: we need to delete the relation first due to the DB constraint.
const objectsInDbById = objectsInDB.reduce((result, currentObject) => {
result[currentObject.id] = currentObject;
return result;
}, {});
if (fieldsToCreate.length > 0) {
fieldsToCreate.map((field) => {
const migrations = [
{
name: objectsInDbById[field.objectMetadataId].targetTableName,
action: 'alter',
columns: this.workspaceMigrationFactory.createColumnActions(
WorkspaceMigrationColumnActionType.CREATE,
field,
),
} satisfies WorkspaceMigrationTableAction,
];
migrationsToSave.push({
workspaceId: field.workspaceId,
isCustom: false,
migrations,
});
});
}
if (fieldsToDelete.length > 0) {
fieldsToDelete.map((field) => {
const migrations = [
{
name: objectsInDbById[field.objectMetadataId].targetTableName,
action: 'alter',
columns: [
{
action: WorkspaceMigrationColumnActionType.DROP,
columnName: field.name,
},
],
} satisfies WorkspaceMigrationTableAction,
];
migrationsToSave.push({
workspaceId: field.workspaceId,
isCustom: false,
migrations,
});
});
}
await this.workspaceMigrationRepository.save(migrationsToSave);
// TODO: handle delete migrations