mirror of
https://github.com/twentyhq/twenty.git
synced 2024-11-23 22:12:24 +03:00
fix: sync and health (#4095)
* fix: throw error if we try to create a migration without columnName * fix: typeorm save for update breaking everything
This commit is contained in:
parent
8c46e66cf5
commit
3914e8d77c
@ -55,11 +55,22 @@ export class BasicColumnActionFactory extends ColumnActionAbstractFactory<BasicF
|
||||
this.getDefaultValue(alteredFieldMetadata.defaultValue) ??
|
||||
options?.defaultValue;
|
||||
const serializedDefaultValue = serializeDefaultValue(defaultValue);
|
||||
const currentColumnName = currentFieldMetadata.targetColumnMap.value;
|
||||
const alteredColumnName = alteredFieldMetadata.targetColumnMap.value;
|
||||
|
||||
if (!currentColumnName || !alteredColumnName) {
|
||||
this.logger.error(
|
||||
`Column name not found for current or altered field metadata, can be due to a missing or an invalid target column map. Current column name: ${currentColumnName}, Altered column name: ${alteredColumnName}.`,
|
||||
);
|
||||
throw new Error(
|
||||
`Column name not found for current or altered field metadata`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
action: WorkspaceMigrationColumnActionType.ALTER,
|
||||
currentColumnDefinition: {
|
||||
columnName: currentFieldMetadata.targetColumnMap.value,
|
||||
columnName: currentColumnName,
|
||||
columnType: fieldMetadataTypeToColumnType(currentFieldMetadata.type),
|
||||
isNullable: currentFieldMetadata.isNullable,
|
||||
defaultValue: serializeDefaultValue(
|
||||
@ -67,7 +78,7 @@ export class BasicColumnActionFactory extends ColumnActionAbstractFactory<BasicF
|
||||
),
|
||||
},
|
||||
alteredColumnDefinition: {
|
||||
columnName: alteredFieldMetadata.targetColumnMap.value,
|
||||
columnName: alteredColumnName,
|
||||
columnType: fieldMetadataTypeToColumnType(alteredFieldMetadata.type),
|
||||
isNullable: alteredFieldMetadata.isNullable,
|
||||
defaultValue: serializedDefaultValue,
|
||||
|
@ -71,11 +71,22 @@ export class EnumColumnActionFactory extends ColumnActionAbstractFactory<EnumFie
|
||||
}),
|
||||
]
|
||||
: undefined;
|
||||
const currentColumnName = currentFieldMetadata.targetColumnMap.value;
|
||||
const alteredColumnName = alteredFieldMetadata.targetColumnMap.value;
|
||||
|
||||
if (!currentColumnName || !alteredColumnName) {
|
||||
this.logger.error(
|
||||
`Column name not found for current or altered field metadata, can be due to a missing or an invalid target column map. Current column name: ${currentColumnName}, Altered column name: ${alteredColumnName}.`,
|
||||
);
|
||||
throw new Error(
|
||||
`Column name not found for current or altered field metadata`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
action: WorkspaceMigrationColumnActionType.ALTER,
|
||||
currentColumnDefinition: {
|
||||
columnName: currentFieldMetadata.targetColumnMap.value,
|
||||
columnName: currentColumnName,
|
||||
columnType: fieldMetadataTypeToColumnType(currentFieldMetadata.type),
|
||||
enum: currentFieldMetadata.options
|
||||
? [...currentFieldMetadata.options.map((option) => option.value)]
|
||||
@ -87,7 +98,7 @@ export class EnumColumnActionFactory extends ColumnActionAbstractFactory<EnumFie
|
||||
),
|
||||
},
|
||||
alteredColumnDefinition: {
|
||||
columnName: alteredFieldMetadata.targetColumnMap.value,
|
||||
columnName: alteredColumnName,
|
||||
columnType: fieldMetadataTypeToColumnType(alteredFieldMetadata.type),
|
||||
enum: enumOptions,
|
||||
isArray: alteredFieldMetadata.type === FieldMetadataType.MULTI_SELECT,
|
||||
|
@ -127,13 +127,40 @@ export class WorkspaceMetadataUpdaterService {
|
||||
/**
|
||||
* Update field metadata
|
||||
*/
|
||||
const oldFieldMetadataCollection = await fieldMetadataRepository.find({
|
||||
where: {
|
||||
id: In(storage.fieldMetadataUpdateCollection.map((field) => field.id)),
|
||||
},
|
||||
const oldFieldMetadataCollection = await fieldMetadataRepository.findBy({
|
||||
id: In(storage.fieldMetadataUpdateCollection.map((field) => field.id)),
|
||||
});
|
||||
// Pre-process old collection into a mapping for quick access
|
||||
const oldFieldMetadataMap = new Map(
|
||||
oldFieldMetadataCollection.map((field) => [field.id, field]),
|
||||
);
|
||||
// Combine old and new field metadata to get whole updated entities
|
||||
const fieldMetadataUpdateCollection =
|
||||
storage.fieldMetadataUpdateCollection.map((updateFieldMetadata) => {
|
||||
const oldFieldMetadata = oldFieldMetadataMap.get(
|
||||
updateFieldMetadata.id,
|
||||
);
|
||||
|
||||
if (!oldFieldMetadata) {
|
||||
throw new Error(`
|
||||
Field ${updateFieldMetadata.id} not found in oldFieldMetadataCollection`);
|
||||
}
|
||||
|
||||
// TypeORM 😢
|
||||
// If we didn't provide the old value, it will be set to null fields that are not in the updateFieldMetadata
|
||||
// and override the old value with null in the DB.
|
||||
// Also save method doesn't return the whole entity if you give a partial one.
|
||||
// https://github.com/typeorm/typeorm/issues/3490
|
||||
// To avoid calling update in a for loop, we did this hack.
|
||||
return {
|
||||
...oldFieldMetadata,
|
||||
...updateFieldMetadata,
|
||||
options: updateFieldMetadata.options ?? oldFieldMetadata.options,
|
||||
};
|
||||
});
|
||||
|
||||
const updatedFieldMetadataCollection = await fieldMetadataRepository.save(
|
||||
storage.fieldMetadataUpdateCollection as DeepPartial<FieldMetadataEntity>[],
|
||||
fieldMetadataUpdateCollection,
|
||||
);
|
||||
|
||||
/**
|
||||
@ -156,26 +183,21 @@ export class WorkspaceMetadataUpdaterService {
|
||||
return {
|
||||
createdFieldMetadataCollection:
|
||||
createdFieldMetadataCollection as FieldMetadataEntity[],
|
||||
updatedFieldMetadataCollection: oldFieldMetadataCollection.map(
|
||||
(oldFieldMetadata) => {
|
||||
const alteredFieldMetadata = updatedFieldMetadataCollection.find(
|
||||
(field) => field.id === oldFieldMetadata.id,
|
||||
updatedFieldMetadataCollection: updatedFieldMetadataCollection.map(
|
||||
(alteredFieldMetadata) => {
|
||||
const oldFieldMetadata = oldFieldMetadataMap.get(
|
||||
alteredFieldMetadata.id,
|
||||
);
|
||||
|
||||
if (!alteredFieldMetadata) {
|
||||
throw new Error(
|
||||
`Field ${oldFieldMetadata.id} not found in updatedFieldMetadataCollection`,
|
||||
);
|
||||
if (!oldFieldMetadata) {
|
||||
throw new Error(`
|
||||
Field ${alteredFieldMetadata.id} not found in oldFieldMetadataCollection
|
||||
`);
|
||||
}
|
||||
|
||||
return {
|
||||
current: oldFieldMetadata as FieldMetadataEntity,
|
||||
// TypeORM save method doesn't return the whole entity...
|
||||
// https://github.com/typeorm/typeorm/issues/3490
|
||||
altered: {
|
||||
...oldFieldMetadata,
|
||||
...alteredFieldMetadata,
|
||||
} as FieldMetadataEntity,
|
||||
altered: alteredFieldMetadata as FieldMetadataEntity,
|
||||
};
|
||||
},
|
||||
),
|
||||
|
@ -15,9 +15,9 @@ export class WorkspaceSyncStorage {
|
||||
|
||||
// Field metadata
|
||||
private readonly _fieldMetadataCreateCollection: PartialFieldMetadata[] = [];
|
||||
private readonly _fieldMetadataUpdateCollection: Partial<
|
||||
PartialFieldMetadata & { id: string }
|
||||
>[] = [];
|
||||
private readonly _fieldMetadataUpdateCollection: (Partial<PartialFieldMetadata> & {
|
||||
id: string;
|
||||
})[] = [];
|
||||
private readonly _fieldMetadataDeleteCollection: FieldMetadataEntity[] = [];
|
||||
|
||||
// Relation metadata
|
||||
@ -76,7 +76,9 @@ export class WorkspaceSyncStorage {
|
||||
this._fieldMetadataCreateCollection.push(field);
|
||||
}
|
||||
|
||||
addUpdateFieldMetadata(field: Partial<PartialFieldMetadata>) {
|
||||
addUpdateFieldMetadata(
|
||||
field: Partial<PartialFieldMetadata> & { id: string },
|
||||
) {
|
||||
this._fieldMetadataUpdateCollection.push(field);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user