Add field create and delete migration to metadata sync (#2942)
add field create and delete migration to metadata sync
This commit is contained in:
@ -9,6 +9,7 @@ export enum WorkspaceMigrationColumnActionType {
|
|||||||
CREATE = 'CREATE',
|
CREATE = 'CREATE',
|
||||||
ALTER = 'ALTER',
|
ALTER = 'ALTER',
|
||||||
RELATION = 'RELATION',
|
RELATION = 'RELATION',
|
||||||
|
DROP = 'DROP',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type WorkspaceMigrationEnum = string | { from: string; to: string };
|
export type WorkspaceMigrationEnum = string | { from: string; to: string };
|
||||||
@ -41,12 +42,18 @@ export type WorkspaceMigrationColumnRelation = {
|
|||||||
isUnique?: boolean;
|
isUnique?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type WorkspaceMigrationColumnDrop = {
|
||||||
|
action: WorkspaceMigrationColumnActionType.DROP;
|
||||||
|
columnName: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type WorkspaceMigrationColumnAction = {
|
export type WorkspaceMigrationColumnAction = {
|
||||||
action: WorkspaceMigrationColumnActionType;
|
action: WorkspaceMigrationColumnActionType;
|
||||||
} & (
|
} & (
|
||||||
| WorkspaceMigrationColumnCreate
|
| WorkspaceMigrationColumnCreate
|
||||||
| WorkspaceMigrationColumnAlter
|
| WorkspaceMigrationColumnAlter
|
||||||
| WorkspaceMigrationColumnRelation
|
| WorkspaceMigrationColumnRelation
|
||||||
|
| WorkspaceMigrationColumnDrop
|
||||||
);
|
);
|
||||||
|
|
||||||
export type WorkspaceMigrationTableAction = {
|
export type WorkspaceMigrationTableAction = {
|
||||||
|
|||||||
@ -187,6 +187,12 @@ export class WorkspaceMigrationRunnerService {
|
|||||||
columnMigration,
|
columnMigration,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case WorkspaceMigrationColumnActionType.DROP:
|
||||||
|
await queryRunner.dropColumn(
|
||||||
|
`${schemaName}.${tableName}`,
|
||||||
|
columnMigration.columnName,
|
||||||
|
);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Migration column action not supported`);
|
throw new Error(`Migration column action not supported`);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,7 +144,8 @@ function generateFieldMetadata<T extends FieldMetadataType>(
|
|||||||
name: fieldKey,
|
name: fieldKey,
|
||||||
...metadata,
|
...metadata,
|
||||||
targetColumnMap: targetColumnMap,
|
targetColumnMap: targetColumnMap,
|
||||||
isNullable: metadata.type === FieldMetadataType.RELATION ? true : isNullable,
|
isNullable:
|
||||||
|
metadata.type === FieldMetadataType.RELATION ? true : isNullable,
|
||||||
isSystem,
|
isSystem,
|
||||||
isCustom: false,
|
isCustom: false,
|
||||||
options: null, // TODO: handle options + stringify for the diff.
|
options: null, // TODO: handle options + stringify for the diff.
|
||||||
|
|||||||
@ -125,6 +125,7 @@ export class WorkspaceSyncMetadataService {
|
|||||||
if (value === null || typeof value !== 'object') {
|
if (value === null || typeof value !== 'object') {
|
||||||
return [key, value];
|
return [key, value];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
key,
|
key,
|
||||||
filterIgnoredProperties(
|
filterIgnoredProperties(
|
||||||
@ -134,6 +135,7 @@ export class WorkspaceSyncMetadataService {
|
|||||||
if (property !== null && typeof property === 'object') {
|
if (property !== null && typeof property === 'object') {
|
||||||
return JSON.stringify(property);
|
return JSON.stringify(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
return property;
|
return property;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -157,6 +159,7 @@ export class WorkspaceSyncMetadataService {
|
|||||||
// We only handle CHANGE here as REMOVE and CREATE are handled earlier.
|
// We only handle CHANGE here as REMOVE and CREATE are handled earlier.
|
||||||
if (diff.type === 'CHANGE') {
|
if (diff.type === 'CHANGE') {
|
||||||
const property = diff.path[0];
|
const property = diff.path[0];
|
||||||
|
|
||||||
objectsToUpdate[objectInDB.id] = {
|
objectsToUpdate[objectInDB.id] = {
|
||||||
...objectsToUpdate[objectInDB.id],
|
...objectsToUpdate[objectInDB.id],
|
||||||
[property]: diff.value,
|
[property]: diff.value,
|
||||||
@ -166,6 +169,7 @@ export class WorkspaceSyncMetadataService {
|
|||||||
|
|
||||||
for (const diff of fieldsDiff) {
|
for (const diff of fieldsDiff) {
|
||||||
const fieldName = diff.path[0];
|
const fieldName = diff.path[0];
|
||||||
|
|
||||||
if (diff.type === 'CREATE')
|
if (diff.type === 'CREATE')
|
||||||
fieldsToCreate.push({
|
fieldsToCreate.push({
|
||||||
...standardObjectFields[fieldName],
|
...standardObjectFields[fieldName],
|
||||||
@ -175,6 +179,7 @@ export class WorkspaceSyncMetadataService {
|
|||||||
fieldsToDelete.push(objectInDBFields[fieldName]);
|
fieldsToDelete.push(objectInDBFields[fieldName]);
|
||||||
if (diff.type === 'CHANGE') {
|
if (diff.type === 'CHANGE') {
|
||||||
const property = diff.path[diff.path.length - 1];
|
const property = diff.path[diff.path.length - 1];
|
||||||
|
|
||||||
fieldsToUpdate[objectInDBFields[fieldName].id] = {
|
fieldsToUpdate[objectInDBFields[fieldName].id] = {
|
||||||
...fieldsToUpdate[objectInDBFields[fieldName].id],
|
...fieldsToUpdate[objectInDBFields[fieldName].id],
|
||||||
[property]: diff.value,
|
[property]: diff.value,
|
||||||
@ -221,6 +226,7 @@ export class WorkspaceSyncMetadataService {
|
|||||||
const fieldsToDeleteWithoutRelationType = fieldsToDelete.filter(
|
const fieldsToDeleteWithoutRelationType = fieldsToDelete.filter(
|
||||||
(field) => field.type !== FieldMetadataType.RELATION,
|
(field) => field.type !== FieldMetadataType.RELATION,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (fieldsToDeleteWithoutRelationType.length > 0) {
|
if (fieldsToDeleteWithoutRelationType.length > 0) {
|
||||||
await this.fieldMetadataRepository.delete(
|
await this.fieldMetadataRepository.delete(
|
||||||
fieldsToDeleteWithoutRelationType.map((field) => field.id),
|
fieldsToDeleteWithoutRelationType.map((field) => field.id),
|
||||||
@ -233,6 +239,7 @@ export class WorkspaceSyncMetadataService {
|
|||||||
objectsToDelete,
|
objectsToDelete,
|
||||||
fieldsToCreate,
|
fieldsToCreate,
|
||||||
fieldsToDelete,
|
fieldsToDelete,
|
||||||
|
objectsInDB,
|
||||||
);
|
);
|
||||||
|
|
||||||
// We run syncRelationMetadata after everything to ensure that all objects and fields are
|
// We run syncRelationMetadata after everything to ensure that all objects and fields are
|
||||||
@ -263,7 +270,9 @@ export class WorkspaceSyncMetadataService {
|
|||||||
objectsInDBByName,
|
objectsInDBByName,
|
||||||
).reduce((result, currentObject) => {
|
).reduce((result, currentObject) => {
|
||||||
const key = `${currentObject.fromObjectMetadataId}->${currentObject.fromFieldMetadataId}`;
|
const key = `${currentObject.fromObjectMetadataId}->${currentObject.fromFieldMetadataId}`;
|
||||||
|
|
||||||
result[key] = currentObject;
|
result[key] = currentObject;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
@ -279,7 +288,9 @@ export class WorkspaceSyncMetadataService {
|
|||||||
)
|
)
|
||||||
.reduce((result, currentObject) => {
|
.reduce((result, currentObject) => {
|
||||||
const key = `${currentObject.fromObjectMetadataId}->${currentObject.fromFieldMetadataId}`;
|
const key = `${currentObject.fromObjectMetadataId}->${currentObject.fromFieldMetadataId}`;
|
||||||
|
|
||||||
result[key] = currentObject;
|
result[key] = currentObject;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
@ -324,11 +335,12 @@ export class WorkspaceSyncMetadataService {
|
|||||||
private async generateMigrationsFromSync(
|
private async generateMigrationsFromSync(
|
||||||
objectsToCreate: ObjectMetadataEntity[],
|
objectsToCreate: ObjectMetadataEntity[],
|
||||||
_objectsToDelete: ObjectMetadataEntity[],
|
_objectsToDelete: ObjectMetadataEntity[],
|
||||||
_fieldsToCreate: FieldMetadataEntity[],
|
fieldsToCreate: FieldMetadataEntity[],
|
||||||
_fieldsToDelete: FieldMetadataEntity[],
|
fieldsToDelete: FieldMetadataEntity[],
|
||||||
|
objectsInDB: ObjectMetadataEntity[],
|
||||||
) {
|
) {
|
||||||
const migrationsToSave: Partial<WorkspaceMigrationEntity>[] = [];
|
const migrationsToSave: Partial<WorkspaceMigrationEntity>[] = [];
|
||||||
|
|
||||||
if (objectsToCreate.length > 0) {
|
if (objectsToCreate.length > 0) {
|
||||||
objectsToCreate.map((object) => {
|
objectsToCreate.map((object) => {
|
||||||
const migrations = [
|
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);
|
await this.workspaceMigrationRepository.save(migrationsToSave);
|
||||||
|
|
||||||
// TODO: handle delete migrations
|
// TODO: handle delete migrations
|
||||||
|
|||||||
Reference in New Issue
Block a user