feat: refactor workspace sync fields (#6069)
This PR was first here to fix the issue related to ticket #5004, after some testing it seems that changing the name of a relation is actually properly working, if we rename `ONE-TO-MANY` side, the only things that is going to be updated is the FieldMetadata as the `joinColumn` is stored on the opposite object. For `MANY-TO-ONE` relations, the `joinColumn` migration is properly generated. We need to take care that if we rename a side of a relation, sometimes the opposite side doesn't have `inverseSideFieldKey` implemented and used by default the name of the opposite object, so this is going to throw an error as the field can't be found in the object. --------- Co-authored-by: Marie <51697796+ijreilly@users.noreply.github.com>
This commit is contained in:
@ -47,9 +47,6 @@ export class WorkspaceMetadataUpdaterService {
|
||||
storage.objectMetadataCreateCollection.map((objectMetadata) => ({
|
||||
...objectMetadata,
|
||||
isActive: true,
|
||||
fields: objectMetadata.fields.map((field) =>
|
||||
this.prepareFieldMetadataForCreation(field),
|
||||
),
|
||||
})) as DeepPartial<ObjectMetadataEntity>[],
|
||||
);
|
||||
const identifiers = createdPartialObjectMetadataCollection.map(
|
||||
|
||||
@ -15,7 +15,9 @@ import { WorkspaceSyncStorage } from 'src/engine/workspace-manager/workspace-syn
|
||||
import { WorkspaceMigrationFieldFactory } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-field.factory';
|
||||
import { StandardFieldFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory';
|
||||
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
|
||||
import { computeStandardObject } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util';
|
||||
import { computeStandardFields } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-fields.util';
|
||||
import { standardObjectMetadataDefinitions } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects';
|
||||
import { mapObjectMetadataByUniqueIdentifier } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/sync-metadata.util';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceSyncFieldMetadataService {
|
||||
@ -47,56 +49,25 @@ export class WorkspaceSyncFieldMetadataService {
|
||||
},
|
||||
relations: ['dataSource', 'fields'],
|
||||
});
|
||||
|
||||
// Filter out non-custom objects
|
||||
const customObjectMetadataCollection =
|
||||
originalObjectMetadataCollection.filter(
|
||||
(objectMetadata) => objectMetadata.isCustom,
|
||||
);
|
||||
|
||||
// Create standard field metadata collection
|
||||
const standardFieldMetadataCollection = this.standardFieldFactory.create(
|
||||
CustomWorkspaceEntity,
|
||||
await this.synchronizeStandardObjectFields(
|
||||
context,
|
||||
originalObjectMetadataCollection,
|
||||
customObjectMetadataCollection,
|
||||
storage,
|
||||
workspaceFeatureFlagsMap,
|
||||
);
|
||||
|
||||
// Loop over all custom objects from the DB and compare their fields with standard fields
|
||||
for (const customObjectMetadata of customObjectMetadataCollection) {
|
||||
// Also, maybe it's better to refactor a bit and move generation part into a separate module ?
|
||||
const standardObjectMetadata = computeStandardObject(
|
||||
{
|
||||
...customObjectMetadata,
|
||||
fields: standardFieldMetadataCollection,
|
||||
},
|
||||
customObjectMetadata,
|
||||
);
|
||||
|
||||
/**
|
||||
* COMPARE FIELD METADATA
|
||||
*/
|
||||
const fieldComparatorResults = this.workspaceFieldComparator.compare(
|
||||
customObjectMetadata,
|
||||
standardObjectMetadata,
|
||||
);
|
||||
|
||||
for (const fieldComparatorResult of fieldComparatorResults) {
|
||||
switch (fieldComparatorResult.action) {
|
||||
case ComparatorAction.CREATE: {
|
||||
storage.addCreateFieldMetadata(fieldComparatorResult.object);
|
||||
break;
|
||||
}
|
||||
case ComparatorAction.UPDATE: {
|
||||
storage.addUpdateFieldMetadata(fieldComparatorResult.object);
|
||||
break;
|
||||
}
|
||||
case ComparatorAction.DELETE: {
|
||||
storage.addDeleteFieldMetadata(fieldComparatorResult.object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
await this.synchronizeCustomObjectFields(
|
||||
context,
|
||||
customObjectMetadataCollection,
|
||||
storage,
|
||||
workspaceFeatureFlagsMap,
|
||||
);
|
||||
|
||||
this.logger.log('Updating workspace metadata');
|
||||
|
||||
@ -137,4 +108,120 @@ export class WorkspaceSyncFieldMetadataService {
|
||||
...deleteFieldWorkspaceMigrations,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* This can be optimized to avoid import of standardObjectFactory here.
|
||||
* We should refactor the logic of the factory, so this one only create the objects and not the fields.
|
||||
* Then standardFieldFactory should be used to create the fields of standard objects.
|
||||
*/
|
||||
private async synchronizeStandardObjectFields(
|
||||
context: WorkspaceSyncContext,
|
||||
originalObjectMetadataCollection: ObjectMetadataEntity[],
|
||||
customObjectMetadataCollection: ObjectMetadataEntity[],
|
||||
storage: WorkspaceSyncStorage,
|
||||
workspaceFeatureFlagsMap: FeatureFlagMap,
|
||||
): Promise<void> {
|
||||
// Create standard field metadata map
|
||||
const standardObjectStandardFieldMetadataMap =
|
||||
this.standardFieldFactory.create(
|
||||
standardObjectMetadataDefinitions,
|
||||
context,
|
||||
workspaceFeatureFlagsMap,
|
||||
);
|
||||
|
||||
// Create map of original and standard object metadata by standard ids
|
||||
const originalObjectMetadataMap = mapObjectMetadataByUniqueIdentifier(
|
||||
originalObjectMetadataCollection,
|
||||
);
|
||||
|
||||
this.logger.log('Comparing standard objects and fields metadata');
|
||||
|
||||
// Loop over all standard objects and compare them with the objects in DB
|
||||
for (const [
|
||||
standardObjectId,
|
||||
standardFieldMetadataCollection,
|
||||
] of standardObjectStandardFieldMetadataMap) {
|
||||
const originalObjectMetadata =
|
||||
originalObjectMetadataMap[standardObjectId];
|
||||
const computedStandardFieldMetadataCollection = computeStandardFields(
|
||||
standardFieldMetadataCollection,
|
||||
originalObjectMetadata,
|
||||
// We need to provide this for generated relations with custom objects
|
||||
customObjectMetadataCollection,
|
||||
);
|
||||
|
||||
const fieldComparatorResults = this.workspaceFieldComparator.compare(
|
||||
originalObjectMetadata.id,
|
||||
originalObjectMetadata.fields,
|
||||
computedStandardFieldMetadataCollection,
|
||||
);
|
||||
|
||||
for (const fieldComparatorResult of fieldComparatorResults) {
|
||||
switch (fieldComparatorResult.action) {
|
||||
case ComparatorAction.CREATE: {
|
||||
storage.addCreateFieldMetadata(fieldComparatorResult.object);
|
||||
break;
|
||||
}
|
||||
case ComparatorAction.UPDATE: {
|
||||
storage.addUpdateFieldMetadata(fieldComparatorResult.object);
|
||||
break;
|
||||
}
|
||||
case ComparatorAction.DELETE: {
|
||||
storage.addDeleteFieldMetadata(fieldComparatorResult.object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async synchronizeCustomObjectFields(
|
||||
context: WorkspaceSyncContext,
|
||||
customObjectMetadataCollection: ObjectMetadataEntity[],
|
||||
storage: WorkspaceSyncStorage,
|
||||
workspaceFeatureFlagsMap: FeatureFlagMap,
|
||||
): Promise<void> {
|
||||
// Create standard field metadata collection
|
||||
const customObjectStandardFieldMetadataCollection =
|
||||
this.standardFieldFactory.create(
|
||||
CustomWorkspaceEntity,
|
||||
context,
|
||||
workspaceFeatureFlagsMap,
|
||||
);
|
||||
|
||||
// Loop over all custom objects from the DB and compare their fields with standard fields
|
||||
for (const customObjectMetadata of customObjectMetadataCollection) {
|
||||
// Also, maybe it's better to refactor a bit and move generation part into a separate module ?
|
||||
const standardFieldMetadataCollection = computeStandardFields(
|
||||
customObjectStandardFieldMetadataCollection,
|
||||
customObjectMetadata,
|
||||
);
|
||||
|
||||
/**
|
||||
* COMPARE FIELD METADATA
|
||||
*/
|
||||
const fieldComparatorResults = this.workspaceFieldComparator.compare(
|
||||
customObjectMetadata.id,
|
||||
customObjectMetadata.fields,
|
||||
standardFieldMetadataCollection,
|
||||
);
|
||||
|
||||
for (const fieldComparatorResult of fieldComparatorResults) {
|
||||
switch (fieldComparatorResult.action) {
|
||||
case ComparatorAction.CREATE: {
|
||||
storage.addCreateFieldMetadata(fieldComparatorResult.object);
|
||||
break;
|
||||
}
|
||||
case ComparatorAction.UPDATE: {
|
||||
storage.addUpdateFieldMetadata(fieldComparatorResult.object);
|
||||
break;
|
||||
}
|
||||
case ComparatorAction.DELETE: {
|
||||
storage.addDeleteFieldMetadata(fieldComparatorResult.object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,11 +12,9 @@ import { mapObjectMetadataByUniqueIdentifier } from 'src/engine/workspace-manage
|
||||
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { StandardObjectFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory';
|
||||
import { WorkspaceObjectComparator } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-object.comparator';
|
||||
import { WorkspaceFieldComparator } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-field.comparator';
|
||||
import { WorkspaceMetadataUpdaterService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-metadata-updater.service';
|
||||
import { WorkspaceSyncStorage } from 'src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage';
|
||||
import { WorkspaceMigrationObjectFactory } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-object.factory';
|
||||
import { computeStandardObject } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util';
|
||||
import { standardObjectMetadataDefinitions } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects';
|
||||
|
||||
@Injectable()
|
||||
@ -26,7 +24,6 @@ export class WorkspaceSyncObjectMetadataService {
|
||||
constructor(
|
||||
private readonly standardObjectFactory: StandardObjectFactory,
|
||||
private readonly workspaceObjectComparator: WorkspaceObjectComparator,
|
||||
private readonly workspaceFieldComparator: WorkspaceFieldComparator,
|
||||
private readonly workspaceMetadataUpdaterService: WorkspaceMetadataUpdaterService,
|
||||
private readonly workspaceMigrationObjectFactory: WorkspaceMigrationObjectFactory,
|
||||
) {}
|
||||
@ -49,10 +46,6 @@ export class WorkspaceSyncObjectMetadataService {
|
||||
},
|
||||
relations: ['dataSource', 'fields'],
|
||||
});
|
||||
const customObjectMetadataCollection =
|
||||
originalObjectMetadataCollection.filter(
|
||||
(objectMetadata) => objectMetadata.isCustom,
|
||||
);
|
||||
|
||||
// Create standard object metadata collection
|
||||
const standardObjectMetadataCollection = this.standardObjectFactory.create(
|
||||
@ -87,11 +80,8 @@ export class WorkspaceSyncObjectMetadataService {
|
||||
for (const standardObjectId in standardObjectMetadataMap) {
|
||||
const originalObjectMetadata =
|
||||
originalObjectMetadataMap[standardObjectId];
|
||||
const standardObjectMetadata = computeStandardObject(
|
||||
standardObjectMetadataMap[standardObjectId],
|
||||
originalObjectMetadata,
|
||||
customObjectMetadataCollection,
|
||||
);
|
||||
const standardObjectMetadata =
|
||||
standardObjectMetadataMap[standardObjectId];
|
||||
|
||||
/**
|
||||
* COMPARE OBJECT METADATA
|
||||
@ -109,35 +99,6 @@ export class WorkspaceSyncObjectMetadataService {
|
||||
if (objectComparatorResult.action === ComparatorAction.UPDATE) {
|
||||
storage.addUpdateObjectMetadata(objectComparatorResult.object);
|
||||
}
|
||||
|
||||
/**
|
||||
* COMPARE FIELD METADATA
|
||||
* NOTE: This should be moved to WorkspaceSyncFieldMetadataService for more clarity since
|
||||
* this code only adds field metadata to the storage but it's actually used in the other service.
|
||||
* NOTE2: WorkspaceSyncFieldMetadataService has been added for custom fields sync, it should be refactored to handle
|
||||
* both custom and non-custom fields.
|
||||
*/
|
||||
const fieldComparatorResults = this.workspaceFieldComparator.compare(
|
||||
originalObjectMetadata,
|
||||
standardObjectMetadata,
|
||||
);
|
||||
|
||||
for (const fieldComparatorResult of fieldComparatorResults) {
|
||||
switch (fieldComparatorResult.action) {
|
||||
case ComparatorAction.CREATE: {
|
||||
storage.addCreateFieldMetadata(fieldComparatorResult.object);
|
||||
break;
|
||||
}
|
||||
case ComparatorAction.UPDATE: {
|
||||
storage.addUpdateFieldMetadata(fieldComparatorResult.object);
|
||||
break;
|
||||
}
|
||||
case ComparatorAction.DELETE: {
|
||||
storage.addDeleteFieldMetadata(fieldComparatorResult.object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.log('Updating workspace metadata');
|
||||
|
||||
Reference in New Issue
Block a user