From 5b2645264966c2dafe2634507f8789acbb2fd600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20M?= Date: Tue, 2 Jul 2024 17:21:13 +0200 Subject: [PATCH] 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> --- .vscode/twenty.code-workspace | 6 +- .../timeline-calendar-event.service.ts | 2 +- .../commands/add-standard-id.command.ts | 13 +- .../workspace-field.comparator.spec.ts | 8 +- .../comparators/workspace-field.comparator.ts | 17 +- .../workspace-object.comparator.ts | 4 +- .../factories/standard-field.factory.ts | 49 ++++- .../factories/standard-object.factory.ts | 15 +- .../interfaces/comparator.interface.ts | 4 +- .../workspace-metadata-updater.service.ts | 3 - .../workspace-sync-field-metadata.service.ts | 171 +++++++++++++----- .../workspace-sync-object-metadata.service.ts | 43 +---- .../standard-objects/index.ts | 1 + .../storage/workspace-sync.storage.ts | 14 +- ...til.ts => compute-standard-fields.util.ts} | 28 +-- 15 files changed, 229 insertions(+), 149 deletions(-) rename packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/{compute-standard-object.util.ts => compute-standard-fields.util.ts} (81%) diff --git a/.vscode/twenty.code-workspace b/.vscode/twenty.code-workspace index 49c9ebed09..c791ac11a0 100644 --- a/.vscode/twenty.code-workspace +++ b/.vscode/twenty.code-workspace @@ -43,21 +43,21 @@ "[typescript]": { "editor.formatOnSave": false, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true, + "source.fixAll.eslint": "explicit", "source.addMissingImports": "always" } }, "[javascript]": { "editor.formatOnSave": false, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true, + "source.fixAll.eslint": "explicit", "source.addMissingImports": "always" } }, "[typescriptreact]": { "editor.formatOnSave": false, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true, + "source.fixAll.eslint": "explicit", "source.addMissingImports": "always" } }, diff --git a/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.service.ts b/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.service.ts index 1ef6370abc..cdca7e31ac 100644 --- a/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.service.ts +++ b/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.service.ts @@ -122,7 +122,7 @@ export class TimelineCalendarEventService { return { totalNumberOfCalendarEvents: total, - timelineCalendarEvents, + timelineCalendarEvents: timelineCalendarEvents, }; } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts index 4908a02814..e4b5405a00 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts @@ -8,9 +8,9 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { standardObjectMetadataDefinitions } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects'; import { StandardObjectFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory'; -import { computeStandardObject } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util'; 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 { computeStandardFields } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-fields.util'; interface RunCommandOptions { workspaceId?: string; @@ -123,11 +123,8 @@ export class AddStandardIdCommand extends CommandRunner { continue; } - const computedStandardObjectMetadata = computeStandardObject( - standardObjectMetadata ?? { - ...originalObjectMetadata, - fields: standardFieldMetadataCollection, - }, + const computedStandardFieldMetadataCollection = computeStandardFields( + standardFieldMetadataCollection, originalObjectMetadata, customObjectMetadataCollection, ); @@ -135,13 +132,13 @@ export class AddStandardIdCommand extends CommandRunner { if (!originalObjectMetadata.isCustom) { updateObjectMetadataCollection.push({ id: originalObjectMetadata.id, - standardId: computedStandardObjectMetadata.standardId, + standardId: originalObjectMetadata.standardId, }); } for (const fieldMetadata of originalObjectMetadata.fields) { const standardFieldMetadata = - computedStandardObjectMetadata.fields.find( + computedStandardFieldMetadataCollection.find( (field) => field.name === fieldMetadata.name && !field.isCustom, ); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/__tests__/workspace-field.comparator.spec.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/__tests__/workspace-field.comparator.spec.ts index e4deb708c3..3df3f57398 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/__tests__/workspace-field.comparator.spec.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/__tests__/workspace-field.comparator.spec.ts @@ -36,7 +36,7 @@ describe('WorkspaceFieldComparator', () => { ], } as any; - const result = comparator.compare(original, standard); + const result = comparator.compare('', original.fields, standard.fields); expect(result).toEqual([ { @@ -65,7 +65,7 @@ describe('WorkspaceFieldComparator', () => { ], } as any; - const result = comparator.compare(original, standard); + const result = comparator.compare('', original.fields, standard.fields); expect(result).toEqual([ { @@ -88,7 +88,7 @@ describe('WorkspaceFieldComparator', () => { } as any; const standard = { fields: [] } as any; - const result = comparator.compare(original, standard); + const result = comparator.compare('', original.fields, standard.fields); expect(result).toEqual([ { @@ -108,7 +108,7 @@ describe('WorkspaceFieldComparator', () => { fields: [createMockFieldMetadata({ standardId: '1' })], } as any; - const result = comparator.compare(original, standard); + const result = comparator.compare('', original.fields, standard.fields); expect(result).toHaveLength(0); }); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-field.comparator.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-field.comparator.ts index eaf55f33a4..f1659ea6be 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-field.comparator.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-field.comparator.ts @@ -7,9 +7,7 @@ import { FieldComparatorResult, } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface'; import { ComputedPartialFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface'; -import { ComputedPartialWorkspaceEntity } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util'; import { FieldMetadataEntity, @@ -35,8 +33,9 @@ export class WorkspaceFieldComparator { constructor() {} public compare( - originalObjectMetadata: ObjectMetadataEntity, - standardObjectMetadata: ComputedPartialWorkspaceEntity, + originalObjectMetadataId: string, + originalFieldMetadataCollection: FieldMetadataEntity[], + standardFieldMetadataCollection: ComputedPartialFieldMetadata[], ): FieldComparatorResult[] { const result: FieldComparatorResult[] = []; const fieldPropertiesToUpdateMap: Record< @@ -46,7 +45,7 @@ export class WorkspaceFieldComparator { // Double security to only compare non-custom fields const filteredOriginalFieldCollection = - originalObjectMetadata.fields.filter((field) => !field.isCustom); + originalFieldMetadataCollection.filter((field) => !field.isCustom); const originalFieldMetadataMap = transformMetadataForComparison( filteredOriginalFieldCollection, { @@ -73,7 +72,7 @@ export class WorkspaceFieldComparator { }, ); const standardFieldMetadataMap = transformMetadataForComparison( - standardObjectMetadata.fields, + standardFieldMetadataCollection, { shouldIgnoreProperty: (property, originalMetadata) => { if (commonFieldPropertiesToIgnore.includes(property)) { @@ -117,9 +116,9 @@ export class WorkspaceFieldComparator { }; // Object shouldn't have thousands of fields, so we can use find here const standardFieldMetadata = - standardObjectMetadata.fields.find(findField); + standardFieldMetadataCollection.find(findField); const originalFieldMetadata = - originalObjectMetadata.fields.find(findField); + originalFieldMetadataCollection.find(findField); switch (difference.type) { case 'CREATE': { @@ -133,7 +132,7 @@ export class WorkspaceFieldComparator { action: ComparatorAction.CREATE, object: { ...standardFieldMetadata, - objectMetadataId: originalObjectMetadata.id, + objectMetadataId: originalObjectMetadataId, }, }); break; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-object.comparator.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-object.comparator.ts index 9ab7f2f27f..eaa37da7cf 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-object.comparator.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-object.comparator.ts @@ -27,8 +27,8 @@ export class WorkspaceObjectComparator { constructor() {} public compare( - originalObjectMetadata: ObjectMetadataEntity | undefined, - standardObjectMetadata: ComputedPartialWorkspaceEntity, + originalObjectMetadata: Omit | undefined, + standardObjectMetadata: Omit, ): ObjectComparatorResult { // If the object doesn't exist in the original metadata, we need to create it if (!originalObjectMetadata) { diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts index 8d714e19b2..20c720e1ed 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts @@ -24,10 +24,53 @@ export class StandardFieldFactory { target: typeof BaseWorkspaceEntity, context: WorkspaceSyncContext, workspaceFeatureFlagsMap: FeatureFlagMap, - ): Array { + ): (PartialFieldMetadata | PartialComputedFieldMetadata)[]; + + create( + targets: (typeof BaseWorkspaceEntity)[], + context: WorkspaceSyncContext, + workspaceFeatureFlagsMap: FeatureFlagMap, // Map of standardId to field metadata + ): Map; + + create( + targetOrTargets: + | typeof BaseWorkspaceEntity + | (typeof BaseWorkspaceEntity)[], + context: WorkspaceSyncContext, + workspaceFeatureFlagsMap: FeatureFlagMap, + ): + | (PartialFieldMetadata | PartialComputedFieldMetadata)[] + | Map { + if (Array.isArray(targetOrTargets)) { + return targetOrTargets.reduce((acc, target) => { + const workspaceEntityMetadataArgs = + metadataArgsStorage.filterEntities(target); + + if (!workspaceEntityMetadataArgs) { + return acc; + } + + if ( + isGatedAndNotEnabled( + workspaceEntityMetadataArgs.gate, + workspaceFeatureFlagsMap, + ) + ) { + return acc; + } + + acc.set( + workspaceEntityMetadataArgs.standardId, + this.create(target, context, workspaceFeatureFlagsMap), + ); + + return acc; + }, new Map()); + } + const workspaceEntityMetadataArgs = - metadataArgsStorage.filterEntities(target); - const metadataCollections = this.collectMetadata(target); + metadataArgsStorage.filterEntities(targetOrTargets); + const metadataCollections = this.collectMetadata(targetOrTargets); return [ ...this.processMetadata( diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts index 9a907f3c3d..72e29753e9 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts @@ -8,17 +8,13 @@ import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-syn import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; -import { StandardFieldFactory } from './standard-field.factory'; - @Injectable() export class StandardObjectFactory { - constructor(private readonly standardFieldFactory: StandardFieldFactory) {} - create( standardObjectMetadataDefinitions: (typeof BaseWorkspaceEntity)[], context: WorkspaceSyncContext, workspaceFeatureFlagsMap: FeatureFlagMap, - ): PartialWorkspaceEntity[] { + ): Omit[] { return standardObjectMetadataDefinitions .map((metadata) => this.createObjectMetadata(metadata, context, workspaceFeatureFlagsMap), @@ -30,7 +26,7 @@ export class StandardObjectFactory { target: typeof BaseWorkspaceEntity, context: WorkspaceSyncContext, workspaceFeatureFlagsMap: FeatureFlagMap, - ): PartialWorkspaceEntity | undefined { + ): Omit | undefined { const workspaceEntityMetadataArgs = metadataArgsStorage.filterEntities(target); @@ -49,12 +45,6 @@ export class StandardObjectFactory { return undefined; } - const fields = this.standardFieldFactory.create( - target, - context, - workspaceFeatureFlagsMap, - ); - return { ...workspaceEntityMetadataArgs, // TODO: Remove targetTableName when we remove the old metadata @@ -64,7 +54,6 @@ export class StandardObjectFactory { isCustom: false, isRemote: false, isSystem: workspaceEntityMetadataArgs.isSystem ?? false, - fields, }; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface.ts index ab40fdfa79..b4279b5d23 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface.ts @@ -33,9 +33,9 @@ export interface ComparatorDeleteResult { export type ObjectComparatorResult = | ComparatorSkipResult - | ComparatorCreateResult + | ComparatorCreateResult> | ComparatorUpdateResult< - Partial & { id: string } + Partial> & { id: string } >; export type FieldComparatorResult = diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-metadata-updater.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-metadata-updater.service.ts index 4e6c0e1179..ac3f8961a2 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-metadata-updater.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-metadata-updater.service.ts @@ -47,9 +47,6 @@ export class WorkspaceMetadataUpdaterService { storage.objectMetadataCreateCollection.map((objectMetadata) => ({ ...objectMetadata, isActive: true, - fields: objectMetadata.fields.map((field) => - this.prepareFieldMetadataForCreation(field), - ), })) as DeepPartial[], ); const identifiers = createdPartialObjectMetadataCollection.map( diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service.ts index e590900bc8..f63b48a3cc 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service.ts @@ -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 { + // 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 { + // 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; + } + } + } + } + } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-object-metadata.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-object-metadata.service.ts index 7d809b3f80..34d456d19d 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-object-metadata.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-object-metadata.service.ts @@ -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'); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts index c56dcf41df..86e9a31ff6 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts @@ -28,6 +28,7 @@ import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/stan import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity'; import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity'; +// TODO: Maybe we should automate this with the DiscoverService of Nest.JS export const standardObjectMetadataDefinitions = [ ActivityTargetWorkspaceEntity, ActivityWorkspaceEntity, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage.ts index 5cf0fd60ab..49bc4b176f 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage.ts @@ -8,9 +8,13 @@ import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/ export class WorkspaceSyncStorage { // Object metadata - private readonly _objectMetadataCreateCollection: ComputedPartialWorkspaceEntity[] = - []; - private readonly _objectMetadataUpdateCollection: (Partial & { + private readonly _objectMetadataCreateCollection: Omit< + ComputedPartialWorkspaceEntity, + 'fields' + >[] = []; + private readonly _objectMetadataUpdateCollection: (Partial< + Omit + > & { id: string; })[] = []; private readonly _objectMetadataDeleteCollection: ObjectMetadataEntity[] = []; @@ -88,7 +92,9 @@ export class WorkspaceSyncStorage { return this._indexMetadataDeleteCollection; } - addCreateObjectMetadata(object: ComputedPartialWorkspaceEntity) { + addCreateObjectMetadata( + object: Omit, + ) { this._objectMetadataCreateCollection.push(object); } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-fields.util.ts similarity index 81% rename from packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util.ts rename to packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-fields.util.ts index c45503534a..7f1a1247bd 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-fields.util.ts @@ -1,8 +1,8 @@ import { - ComputedPartialWorkspaceEntity, - PartialWorkspaceEntity, -} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface'; -import { ComputedPartialFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface'; + ComputedPartialFieldMetadata, + PartialComputedFieldMetadata, + PartialFieldMetadata, +} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; @@ -11,16 +11,18 @@ import { createRelationDeterministicUuid, } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util'; -export const computeStandardObject = ( - standardObjectMetadata: Omit & { - standardId: string | null; - }, +export const computeStandardFields = ( + standardFieldMetadataCollection: ( + | PartialFieldMetadata + | PartialComputedFieldMetadata + )[], originalObjectMetadata: ObjectMetadataEntity, customObjectMetadataCollection: ObjectMetadataEntity[] = [], -): ComputedPartialWorkspaceEntity => { +): ComputedPartialFieldMetadata[] => { const fields: ComputedPartialFieldMetadata[] = []; - for (const partialFieldMetadata of standardObjectMetadata.fields) { + for (const partialFieldMetadata of standardFieldMetadataCollection) { + // Relation from standard object to custom object if ('argsFactory' in partialFieldMetadata) { // Compute standard fields of custom object for (const customObjectMetadata of customObjectMetadataCollection) { @@ -63,6 +65,7 @@ export const computeStandardObject = ( }); } } else { + // Relation from standard object to standard object const labelText = typeof partialFieldMetadata.label === 'function' ? partialFieldMetadata.label(originalObjectMetadata) @@ -80,8 +83,5 @@ export const computeStandardObject = ( } } - return { - ...standardObjectMetadata, - fields, - }; + return fields; };