From 83a560c936bc25b6bc2bd7fbcef58fb0c594b12b Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Thu, 7 Aug 2025 17:19:07 +0200 Subject: [PATCH] Refactor `FieldMetadataService` and validation to consume `FlatObjectMetadataMaps` (#13719) # Introduction Following recent `FlatObjectMetadataMaps` manipulation, transpilers utils introduction in https://github.com/twentyhq/twenty/pull/13620 Refactored the field metadata service and validator to iterate over `FlatObjectMetadataMaps` instead of `FlatObjectMetadata[]`. The object metadata service v2 is shadow coding --- .../services/field-metadata.service-v2.ts | 209 ++++++++++-------- .../flat-field-metadata-validator.service.ts | 36 ++- ...-relation-flat-field-metadata.validator.ts | 33 ++- ...-in-flat-object-metadata-maps.util.test.ts | 22 +- ...object-metadata-maps-or-throw.spec.ts.snap | 5 + ...adata-in-flat-object-metadata-maps.spec.ts | 65 ++++++ ...flat-object-metadata-maps-or-throw.spec.ts | 2 +- ...flat-object-metadata-maps-or-throw.spec.ts | 109 +++++++++ ...s-out-of-flat-object-metadata-maps.spec.ts | 58 +++++ ...adata-in-flat-object-metadata-maps.spec.ts | 4 + ...flat-object-metadata-maps-or-throw.util.ts | 2 +- ...adata-in-flat-object-metadata-maps.util.ts | 15 ++ ...data-with-flat-field-maps-or-throw.util.ts | 4 + ...flat-object-metadata-maps-or-throw.util.ts | 43 ++++ ...flat-object-metadata-maps-or-throw.util.ts | 46 ++++ ...s-out-of-flat-object-metadata-maps.util.ts | 17 ++ ...data-maps-to-flat-object-metadatas.util.ts | 13 ++ ...ject-metadata-with-flat-field-maps.util.ts | 2 + ...data-maps-to-flat-object-metadatas.util.ts | 18 -- .../object-metadata-v2.service.ts | 19 +- 20 files changed, 557 insertions(+), 165 deletions(-) create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/__snapshots__/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.spec.ts.snap create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/add-flat-field-metadata-in-flat-object-metadata-maps.spec.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.spec.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps.spec.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-with-field-maps-to-flat-object-metadata-maps-or-throw.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-maps-to-flat-object-metadatas.util.ts delete mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-maps-to-flat-object-metadatas.util.ts diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata.service-v2.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata.service-v2.ts index 1d732d431b..179dbfd58a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata.service-v2.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata.service-v2.ts @@ -15,12 +15,15 @@ import { } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; import { FlatFieldMetadataValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service'; import { FailedFlatFieldMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type'; +import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; import { fromCreateFieldInputToFlatFieldAndItsFlatObjectMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-and-its-flat-object-metadata.util'; import { isFlatFieldMetadataEntityOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util'; -import { mergeFlatFieldMetadatasInFlatObjectMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/merge-flat-field-metadatas-in-flat-object-metadata.util'; -import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; -import { dispatchAndMergeFlatFieldMetadatasInFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/dispatch-and-merge-flat-field-metadatas-in-flat-object-metadatas.util'; -import { fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-with-flat-field-maps-to-flat-object-metadatas.util'; +import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util'; +import { addFlatFieldMetadataInFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps.util'; +import { extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.util'; +import { extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps.util'; +import { fromFlatObjectMetadataMapsToFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-maps-to-flat-object-metadatas.util'; import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service'; import { WorkspaceMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service'; import { WorkspaceMigrationRunnerV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-migration-runner-v2.service'; @@ -53,6 +56,57 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService + isFlatFieldMetadataEntityOfType( + relatedFlatFieldMetadata, + FieldMetadataType.RELATION, + ) && + relatedFlatFieldMetadata.id === + flatFieldMetadataToCreate.relationTargetFieldMetadataId, + ); + + if (!isDefined(relatedFlatFieldMetadataToCreate)) { + return undefined; + } + + const flatObjectMetadataMapsWithRelatedObjectMetadata = + extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps({ + flatObjectMetadataMaps, + objectMetadataIds: [relatedFlatFieldMetadataToCreate.objectMetadataId], + }); + + if (!isDefined(flatObjectMetadataMapsWithRelatedObjectMetadata)) { + return undefined; + } + + return addFlatFieldMetadataInFlatObjectMetadataMaps({ + flatFieldMetadata: relatedFlatFieldMetadataToCreate, + flatObjectMetadataMaps: flatObjectMetadataMapsWithRelatedObjectMetadata, + }); + } + async createMany( fieldMetadataInputs: CreateFieldInput[], ): Promise { @@ -79,86 +133,27 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService flatFieldMetadata.objectMetadataId, - ), - ), - ); - const filterFlatObjectMetadatasByImpactedIds = ( - flatObjectMetadatas: FlatObjectMetadata[], - ) => - flatObjectMetadatas.filter((flatObjectMetadata) => - impactedObjectMetadataIds.includes(flatObjectMetadata.id), - ); - const impactedExistingFlatObjectMetadatas = - filterFlatObjectMetadatasByImpactedIds(existingFlatObjectMetadatas); - const allValidationErrors: FailedFlatFieldMetadataValidationExceptions[] = []; - let sequentiallyOptimisticallyRenderedFlatObjectMetadatas = structuredClone( - existingFlatObjectMetadatas, + let optimisticFlatObjectMetadataMaps = structuredClone( + existingFlatObjectMetadataMaps, ); for (const flatFieldMetadataToCreate of flatFieldMetadatasToCreate) { - let otherFlatObjectMetadataToValidate: FlatObjectMetadata | undefined = - undefined; - - if ( - isFlatFieldMetadataEntityOfType( + const otherFlatObjectMetadataMapsToValidate = + this.computeOtherFlatObjectMetadataMapsToValidate({ + flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, + flatFieldMetadatasToCreate, flatFieldMetadataToCreate, - FieldMetadataType.RELATION, - ) || - isFlatFieldMetadataEntityOfType( - flatFieldMetadataToCreate, - FieldMetadataType.MORPH_RELATION, - ) - ) { - const relatedFlatFieldMetadataToCreate = - flatFieldMetadatasToCreate.find( - (relatedFlatFieldMetadata) => - isFlatFieldMetadataEntityOfType( - relatedFlatFieldMetadata, - FieldMetadataType.RELATION, - ) && - relatedFlatFieldMetadata.id === - flatFieldMetadataToCreate.relationTargetFieldMetadataId, - ); - const relatedFlatObjectMetadata = isDefined( - relatedFlatFieldMetadataToCreate, - ) - ? existingFlatObjectMetadataMaps.byId[ - relatedFlatFieldMetadataToCreate.objectMetadataId - ] - : undefined; - - otherFlatObjectMetadataToValidate = - isDefined(relatedFlatObjectMetadata) && - isDefined(relatedFlatFieldMetadataToCreate) - ? mergeFlatFieldMetadatasInFlatObjectMetadata({ - flatFieldMetadatas: [relatedFlatFieldMetadataToCreate], - flatObjectMetadata: relatedFlatObjectMetadata, - }) - : undefined; - } + }); const validationErrors = await this.flatFieldMetadataValidatorService.validateOneFlatFieldMetadata( { - existingFlatObjectMetadatas: - sequentiallyOptimisticallyRenderedFlatObjectMetadatas, + existingFlatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, flatFieldMetadataToValidate: flatFieldMetadataToCreate, workspaceId, - othersFlatObjectMetadataToValidate: isDefined( - otherFlatObjectMetadataToValidate, - ) - ? [otherFlatObjectMetadataToValidate] - : undefined, + otherFlatObjectMetadataMapsToValidate, }, ); @@ -167,12 +162,18 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService 0) { @@ -182,20 +183,48 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService flatFieldMetadata.objectMetadataId, ), - }, - inferDeletionFromMissingObjectFieldIndex: false, - workspaceId, - }); + ), + ); - await this.workspaceMigrationRunnerV2Service.run(workspaceMigration); + try { + const fromImpactedFlatObjectMetadataMaps = + extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({ + flatObjectMetadataMaps: existingFlatObjectMetadataMaps, + objectMetadataIds: impactedObjectMetadataIds, + }); + const toImpactedFlatObjectMetadataMaps = + extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({ + flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, + objectMetadataIds: impactedObjectMetadataIds, + }); + const workspaceMigration = this.workspaceMigrationBuilderV2.build({ + objectMetadataFromToInputs: { + from: fromFlatObjectMetadataMapsToFlatObjectMetadatas( + fromImpactedFlatObjectMetadataMaps, + ), + to: fromFlatObjectMetadataMapsToFlatObjectMetadatas( + toImpactedFlatObjectMetadataMaps, + ), + }, + inferDeletionFromMissingObjectFieldIndex: false, + workspaceId, + }); - // TODO refactor once the runner has been refactored to return created entities - return []; + await this.workspaceMigrationRunnerV2Service.run(workspaceMigration); + + // TODO refactor once the runner has been refactored to return created entities + return []; + } catch { + // TODO prastoin We should pass the internal error here + throw new FieldMetadataException( + 'Workspace migration failed to run', + FieldMetadataExceptionCode.INTERNAL_SERVER_ERROR, + ); + } } } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service.ts index 50d78eb46a..662355e40e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service.ts @@ -11,8 +11,7 @@ import { FlatFieldMetadataTypeValidatorService } from 'src/engine/metadata-modul import { FailedFlatFieldMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type'; import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; import { validateFlatFieldMetadataNameAvailability } from 'src/engine/metadata-modules/flat-field-metadata/validators/validate-flat-field-metadata-name-availability.validator'; -import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; -import { mergeTwoFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/merge-two-flat-object-metadatas.util'; +import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; import { ObjectMetadataException, ObjectMetadataExceptionCode, @@ -27,8 +26,8 @@ import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/ export type ValidateOneFieldMetadataArgs< T extends FieldMetadataType = FieldMetadataType, > = { - existingFlatObjectMetadatas: FlatObjectMetadata[]; - othersFlatObjectMetadataToValidate?: FlatObjectMetadata[]; + existingFlatObjectMetadataMaps: FlatObjectMetadataMaps; + otherFlatObjectMetadataMapsToValidate?: FlatObjectMetadataMaps; flatFieldMetadataToValidate: FlatFieldMetadata; workspaceId: string; }; @@ -42,32 +41,27 @@ export class FlatFieldMetadataValidatorService { async validateOneFlatFieldMetadata< T extends FieldMetadataType = FieldMetadataType, >({ - existingFlatObjectMetadatas, + existingFlatObjectMetadataMaps, flatFieldMetadataToValidate, - othersFlatObjectMetadataToValidate, + otherFlatObjectMetadataMapsToValidate, workspaceId, }: ValidateOneFieldMetadataArgs): Promise< FailedFlatFieldMetadataValidationExceptions[] > { const errors: FailedFlatFieldMetadataValidationExceptions[] = []; - const allFlatObjectMetadata = isDefined(othersFlatObjectMetadataToValidate) - ? mergeTwoFlatObjectMetadatas({ - destFlatObjectMetadatas: existingFlatObjectMetadatas, - toMergeFlatObjectMetadatas: othersFlatObjectMetadataToValidate, - }) - : existingFlatObjectMetadatas; - - const parentFlatObjectMetadata = allFlatObjectMetadata.find( - (existingFlatObjectMetadata) => - existingFlatObjectMetadata.id === - flatFieldMetadataToValidate.objectMetadataId, - ); + const parentFlatObjectMetadata = + otherFlatObjectMetadataMapsToValidate?.byId[ + flatFieldMetadataToValidate.objectMetadataId + ] ?? + existingFlatObjectMetadataMaps.byId[ + flatFieldMetadataToValidate.objectMetadataId + ]; if (!isDefined(parentFlatObjectMetadata)) { errors.push( new FieldMetadataException( - isDefined(othersFlatObjectMetadataToValidate) + isDefined(otherFlatObjectMetadataMapsToValidate) ? 'Object metadata not found in both existing and about to be created object metadatas' : 'Object metadata not found', FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND, @@ -139,10 +133,10 @@ export class FlatFieldMetadataValidatorService { } else { const fieldMetadataTypeValidatorExceptions = await fieldMetadataTypeValidator({ - existingFlatObjectMetadatas, + existingFlatObjectMetadataMaps, flatFieldMetadataToValidate, workspaceId, - othersFlatObjectMetadataToValidate, + otherFlatObjectMetadataMapsToValidate, }); errors.push(...fieldMetadataTypeValidatorExceptions); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/validate-relation-flat-field-metadata.validator.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/validate-relation-flat-field-metadata.validator.ts index 0daf457fd9..82c99c89ed 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/validate-relation-flat-field-metadata.validator.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/validate-relation-flat-field-metadata.validator.ts @@ -7,17 +7,16 @@ import { } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; import { ValidateOneFieldMetadataArgs } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service'; import { FailedFlatFieldMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type'; -import { mergeTwoFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/merge-two-flat-object-metadatas.util'; // Remark: This is duplicated with api metadata transpilers exceptions handlers // We might wanna have an NotValidatedFlatFieldMetadata and NotValidatedFlatObjectMetadata, in order to avoid export const validateRelationFlatFieldMetadata = async ({ - existingFlatObjectMetadatas, + existingFlatObjectMetadataMaps, flatFieldMetadataToValidate: { relationTargetFieldMetadataId, relationTargetObjectMetadataId, }, - othersFlatObjectMetadataToValidate, + otherFlatObjectMetadataMapsToValidate, }: ValidateOneFieldMetadataArgs): Promise< FailedFlatFieldMetadataValidationExceptions[] > => { @@ -38,22 +37,16 @@ export const validateRelationFlatFieldMetadata = async ({ } const errors: FailedFlatFieldMetadataValidationExceptions[] = []; - const allFlatObjectMetadata = isDefined(othersFlatObjectMetadataToValidate) - ? mergeTwoFlatObjectMetadatas({ - destFlatObjectMetadatas: existingFlatObjectMetadatas, - toMergeFlatObjectMetadatas: othersFlatObjectMetadataToValidate, - }) - : existingFlatObjectMetadatas; - const targetRelationFlatObjectMetadata = allFlatObjectMetadata.find( - (flatObjectMetadata) => - flatObjectMetadata.id === relationTargetObjectMetadataId, - ); + const targetRelationFlatObjectMetadata = + otherFlatObjectMetadataMapsToValidate?.byId[ + relationTargetObjectMetadataId + ] ?? existingFlatObjectMetadataMaps.byId[relationTargetObjectMetadataId]; if (!isDefined(targetRelationFlatObjectMetadata)) { errors.push( new FieldMetadataException( - isDefined(othersFlatObjectMetadataToValidate) + isDefined(otherFlatObjectMetadataMapsToValidate) ? 'Relation target object metadata not found in both existing and about to be created object metadatas' : 'Relation target object metadata not found', FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND, @@ -62,15 +55,15 @@ export const validateRelationFlatFieldMetadata = async ({ } const targetRelationFlatFieldMetadata = - targetRelationFlatObjectMetadata?.flatFieldMetadatas.find( - (flatFieldMetadata) => - flatFieldMetadata.id === relationTargetFieldMetadataId, - ); + targetRelationFlatObjectMetadata?.fieldsById[relationTargetFieldMetadataId]; - if (!isDefined(targetRelationFlatFieldMetadata)) { + if ( + isDefined(targetRelationFlatObjectMetadata) && + !isDefined(targetRelationFlatFieldMetadata) + ) { errors.push( new FieldMetadataException( - isDefined(othersFlatObjectMetadataToValidate) + isDefined(otherFlatObjectMetadataMapsToValidate) ? 'Relation field target metadata not found in both existing and about to be created field metadatas' : 'Relation field target metadata not found', FieldMetadataExceptionCode.FIELD_METADATA_NOT_FOUND, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/__tests__/utils/expect-flat-field-metadata-to-be-in-flat-object-metadata-maps.util.test.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/__tests__/utils/expect-flat-field-metadata-to-be-in-flat-object-metadata-maps.util.test.ts index bdbe6416cc..0d43b5e387 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/__tests__/utils/expect-flat-field-metadata-to-be-in-flat-object-metadata-maps.util.test.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/__tests__/utils/expect-flat-field-metadata-to-be-in-flat-object-metadata-maps.util.test.ts @@ -15,9 +15,10 @@ export const expectFlatFieldMetadataToBeInFlatObjectMetadataMaps = ({ flatObjectMetadataMaps, }: ExpectFlatFieldMetadataToBeInFlatObjectMetadataMapsArgs) => { const { objectMetadataId, id: flatFieldMetadataId } = flatFieldMetadata; - const petObject = flatObjectMetadataMaps.byId[objectMetadataId]; + const matchingFlatObjectMetadata = + flatObjectMetadataMaps.byId[objectMetadataId]; - jestExpectToBeDefined(petObject); + jestExpectToBeDefined(matchingFlatObjectMetadata); if ( isFlatFieldMetadataEntityOfType( @@ -27,15 +28,22 @@ export const expectFlatFieldMetadataToBeInFlatObjectMetadataMaps = ({ isDefined(flatFieldMetadata.settings.joinColumnName) ) { expect( - petObject.fieldIdByJoinColumnName[ + matchingFlatObjectMetadata.fieldIdByJoinColumnName[ flatFieldMetadata.settings.joinColumnName ], ).toEqual(flatFieldMetadataId); } - expect(petObject.fieldsById[flatFieldMetadataId]).toBeDefined(); - expect(petObject.fieldsById[flatFieldMetadataId]).toEqual(flatFieldMetadata); - expect(petObject.fieldIdByName[flatFieldMetadata.name]).toEqual( - flatFieldMetadataId, + expect( + matchingFlatObjectMetadata.fieldsById[flatFieldMetadataId], + ).toBeDefined(); + expect(matchingFlatObjectMetadata.fieldsById[flatFieldMetadataId]).toEqual( + flatFieldMetadata, ); + expect(matchingFlatObjectMetadata.flatFieldMetadatas).toContain( + flatFieldMetadata, + ); + expect( + matchingFlatObjectMetadata.fieldIdByName[flatFieldMetadata.name], + ).toEqual(flatFieldMetadataId); }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/__snapshots__/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.spec.ts.snap b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/__snapshots__/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.spec.ts.snap new file mode 100644 index 0000000000..adfbb9a079 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/__snapshots__/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.spec.ts.snap @@ -0,0 +1,5 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow should throw when extracting twice the same object 1`] = `"addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow: flat object metadata with fields maps to add already exists"`; + +exports[`extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow should throw when object metadata id is not found 1`] = `"extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow object metadata not found"`; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/add-flat-field-metadata-in-flat-object-metadata-maps.spec.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/add-flat-field-metadata-in-flat-object-metadata-maps.spec.ts new file mode 100644 index 0000000000..a540579796 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/add-flat-field-metadata-in-flat-object-metadata-maps.spec.ts @@ -0,0 +1,65 @@ +import { + EachTestingContext, + eachTestingContextFilter, +} from 'twenty-shared/testing'; +import { FieldMetadataType } from 'twenty-shared/types'; + +import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock'; +import { PET_FLAT_FIELDS_MOCK } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/pet-flat-fields.mock'; +import { FLAT_OBJECT_METADATA_MAPS_MOCKS } from 'src/engine/metadata-modules/flat-object-metadata-maps/mocks/flat-object-metadata-maps.mock'; +import { AddFlatFieldMetadataInFlatObjectMetadataMapsOrThrowArgs } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util'; +import { addFlatFieldMetadataInFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps.util'; + +type AddFlatFieldMetadataInFlatObjectMetadataMapsArgsTestCase = { + input: AddFlatFieldMetadataInFlatObjectMetadataMapsOrThrowArgs; +}; + +describe('addFlatFieldMetadataInFlatObjectMetadataMaps', () => { + const testCases: EachTestingContext[] = + [ + { + title: + 'should return undefined when field metadata parent object metadata does not exist', + context: { + input: { + flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + flatFieldMetadata: getFlatFieldMetadataMock({ + objectMetadataId: 'non-existent', + type: FieldMetadataType.TEXT, + uniqueIdentifier: 'unique-id-1', + id: 'unique-id-1', + }), + }, + }, + }, + { + title: + 'should return undefined when field metadata to add already exist in object', + context: { + input: { + flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + flatFieldMetadata: PET_FLAT_FIELDS_MOCK.species, + }, + }, + }, + ]; + + const filteredTestCases = eachTestingContextFilter(testCases); + + it.each(filteredTestCases)( + '$title', + ({ + context: { + input: { flatFieldMetadata, flatObjectMetadataMaps }, + }, + }) => { + const updatedFlatObjectMetadataMaps = + addFlatFieldMetadataInFlatObjectMetadataMaps({ + flatFieldMetadata, + flatObjectMetadataMaps, + }); + + expect(updatedFlatObjectMetadataMaps).toBeUndefined(); + }, + ); +}); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/add-flat-object-metadata-to-flat-object-metadata-maps-or-throw.spec.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/add-flat-object-metadata-to-flat-object-metadata-maps-or-throw.spec.ts index a07a6e8776..bf3a933c0c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/add-flat-object-metadata-to-flat-object-metadata-maps-or-throw.spec.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/add-flat-object-metadata-to-flat-object-metadata-maps-or-throw.spec.ts @@ -78,7 +78,7 @@ describe('addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow', () => { flatObjectMetadataMaps, }); - expect(updatedFlatObjectMetadataMaps).toEqual(expected); + expect(updatedFlatObjectMetadataMaps).toStrictEqual(expected); } }, ); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.spec.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.spec.ts new file mode 100644 index 0000000000..f043ebbadf --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.spec.ts @@ -0,0 +1,109 @@ +import { jestExpectToBeDefined } from 'test/utils/expect-to-be-defined.util.test'; +import { + EachTestingContext, + eachTestingContextFilter, +} from 'twenty-shared/testing'; + +import { FLAT_OBJECT_METADATA_MAPS_MOCKS } from 'src/engine/metadata-modules/flat-object-metadata-maps/mocks/flat-object-metadata-maps.mock'; +import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { + ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs, + extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow, +} from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.util'; +import { PET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/pet-flat-object.mock'; +import { ROCKET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/rocket-flat-object.mock'; +import { fromFlatObjectMetadatasToFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadatas-to-flat-object-metadata-maps.util'; + +type ExtractFlatObjectMetadataMapsTestCase = { + input: ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs; + shouldThrow?: true; + expected?: FlatObjectMetadataMaps; +}; + +describe('extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow', () => { + const testCases: EachTestingContext[] = + [ + { + title: 'should throw when object metadata id is not found', + context: { + input: { + objectMetadataIds: ['non-existent-id'], + flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }, + shouldThrow: true, + }, + }, + { + title: 'should throw when extracting twice the same object', + context: { + input: { + objectMetadataIds: [ + PET_FLAT_OBJECT_MOCK.id, + PET_FLAT_OBJECT_MOCK.id, + ], + flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }, + shouldThrow: true, + }, + }, + { + title: 'should extract single object metadata from maps', + context: { + input: { + objectMetadataIds: [PET_FLAT_OBJECT_MOCK.id], + flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }, + expected: fromFlatObjectMetadatasToFlatObjectMetadataMaps([ + PET_FLAT_OBJECT_MOCK, + ]), + }, + }, + { + title: 'should extract multiple object metadata from maps', + context: { + input: { + objectMetadataIds: [ + PET_FLAT_OBJECT_MOCK.id, + ROCKET_FLAT_OBJECT_MOCK.id, + ], + flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }, + expected: fromFlatObjectMetadatasToFlatObjectMetadataMaps([ + PET_FLAT_OBJECT_MOCK, + ROCKET_FLAT_OBJECT_MOCK, + ]), + }, + }, + ]; + + const filteredTestCases = eachTestingContextFilter(testCases); + + it.each(filteredTestCases)( + '$title', + ({ + context: { + input: { objectMetadataIds, flatObjectMetadataMaps }, + shouldThrow = false, + expected, + }, + }) => { + if (shouldThrow) { + expect(() => + extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({ + objectMetadataIds, + flatObjectMetadataMaps, + }), + ).toThrowErrorMatchingSnapshot(); + } else { + jestExpectToBeDefined(expected); + const result = + extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({ + objectMetadataIds, + flatObjectMetadataMaps, + }); + + expect(result).toEqual(expected); + } + }, + ); +}); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps.spec.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps.spec.ts new file mode 100644 index 0000000000..992a924b24 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps.spec.ts @@ -0,0 +1,58 @@ +import { + EachTestingContext, + eachTestingContextFilter, +} from 'twenty-shared/testing'; + +import { FLAT_OBJECT_METADATA_MAPS_MOCKS } from 'src/engine/metadata-modules/flat-object-metadata-maps/mocks/flat-object-metadata-maps.mock'; +import { ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.util'; +import { extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps.util'; +import { PET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/pet-flat-object.mock'; + +type ExtractFlatObjectMetadataMapsTestCase = { + input: ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs; +}; + +describe('extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps', () => { + const testCases: EachTestingContext[] = + [ + { + title: 'should throw when object metadata id is not found', + context: { + input: { + objectMetadataIds: ['non-existent-id'], + flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }, + }, + }, + { + title: 'should throw when extracting twice the same object', + context: { + input: { + objectMetadataIds: [ + PET_FLAT_OBJECT_MOCK.id, + PET_FLAT_OBJECT_MOCK.id, + ], + flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }, + }, + }, + ]; + + const filteredTestCases = eachTestingContextFilter(testCases); + + it.each(filteredTestCases)( + '$title', + ({ + context: { + input: { objectMetadataIds, flatObjectMetadataMaps }, + }, + }) => { + const result = extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps({ + objectMetadataIds, + flatObjectMetadataMaps, + }); + + expect(result).toBeUndefined(); + }, + ); +}); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/find-flat-object-metadata-in-flat-object-metadata-maps.spec.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/find-flat-object-metadata-in-flat-object-metadata-maps.spec.ts index 7df28348e1..85154db333 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/find-flat-object-metadata-in-flat-object-metadata-maps.spec.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/__tests__/find-flat-object-metadata-in-flat-object-metadata-maps.spec.ts @@ -55,6 +55,10 @@ describe('findFlatObjectMetadataInFlatObjectMetadataMaps', () => { flatObjectMetadataMaps, }); + expect(result?.flatFieldMetadatas.length).toEqual( + expected?.flatFieldMetadatas.length, + ); + expect(result).toEqual(expected); }, ); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util.ts index 68aa3fc806..b61e32eb19 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util.ts @@ -35,6 +35,6 @@ export const addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow = ({ flatObjectMetadataWithFlatFieldMaps, }), }, - idByNameSingular: flatObjectMetadataMaps.idByNameSingular, + idByNameSingular: { ...flatObjectMetadataMaps.idByNameSingular }, }; }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps.util.ts new file mode 100644 index 0000000000..c1f1cd546e --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps.util.ts @@ -0,0 +1,15 @@ +import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { + AddFlatFieldMetadataInFlatObjectMetadataMapsOrThrowArgs, + addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow, +} from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util'; + +export const addFlatFieldMetadataInFlatObjectMetadataMaps = ( + arg: AddFlatFieldMetadataInFlatObjectMetadataMapsOrThrowArgs, +): FlatObjectMetadataMaps | undefined => { + try { + return addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow(arg); + } catch (e) { + return undefined; + } +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-to-flat-object-metadata-with-flat-field-maps-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-to-flat-object-metadata-with-flat-field-maps-or-throw.util.ts index 114ef2214c..595c00b64f 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-to-flat-object-metadata-with-flat-field-maps-or-throw.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-to-flat-object-metadata-with-flat-field-maps-or-throw.util.ts @@ -67,5 +67,9 @@ export const addFlatFieldMetadataToFlatObjectMetadataWithFlatFieldMapsOrThrow = ...flatObjectMetadataWithFlatFieldMaps.fieldsById, [flatFieldMetadata.id]: flatFieldMetadata, }, + flatFieldMetadatas: [ + ...flatObjectMetadataWithFlatFieldMaps.flatFieldMetadatas, + flatFieldMetadata, + ], }; }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-with-field-maps-to-flat-object-metadata-maps-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-with-field-maps-to-flat-object-metadata-maps-or-throw.util.ts new file mode 100644 index 0000000000..6d43d321cc --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-with-field-maps-to-flat-object-metadata-maps-or-throw.util.ts @@ -0,0 +1,43 @@ +import { isDefined } from 'twenty-shared/utils'; + +import { + FlatObjectMetadataMapsException, + FlatObjectMetadataMapsExceptionCode, +} from 'src/engine/metadata-modules/flat-object-metadata-maps/flat-object-metadata-maps.exception'; +import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { FlatObjectMetadataWithFlatFieldMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-with-flat-field-metadata-maps.type'; + +type AddFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrowArgs = + { + flatObjectMetadataWithFlatFieldMaps: FlatObjectMetadataWithFlatFieldMaps; + flatObjectMetadataMaps: FlatObjectMetadataMaps; + }; +export const addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow = + ({ + flatObjectMetadataWithFlatFieldMaps, + flatObjectMetadataMaps, + }: AddFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrowArgs): FlatObjectMetadataMaps => { + if ( + isDefined( + flatObjectMetadataMaps.byId[flatObjectMetadataWithFlatFieldMaps.id], + ) + ) { + throw new FlatObjectMetadataMapsException( + 'addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow: flat object metadata with fields maps to add already exists', + FlatObjectMetadataMapsExceptionCode.OBJECT_METADATA_ALREADY_EXISTS, + ); + } + + return { + byId: { + ...flatObjectMetadataMaps.byId, + [flatObjectMetadataWithFlatFieldMaps.id]: + flatObjectMetadataWithFlatFieldMaps, + }, + idByNameSingular: { + ...flatObjectMetadataMaps.idByNameSingular, + [flatObjectMetadataWithFlatFieldMaps.nameSingular]: + flatObjectMetadataWithFlatFieldMaps.id, + }, + }; + }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.util.ts new file mode 100644 index 0000000000..0b49410bc7 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.util.ts @@ -0,0 +1,46 @@ +import { isDefined } from 'twenty-shared/utils'; + +import { + FlatObjectMetadataMapsException, + FlatObjectMetadataMapsExceptionCode, +} from 'src/engine/metadata-modules/flat-object-metadata-maps/flat-object-metadata-maps.exception'; +import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-with-field-maps-to-flat-object-metadata-maps-or-throw.util'; + +export type ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs = + { + objectMetadataIds: string[]; + flatObjectMetadataMaps: FlatObjectMetadataMaps; + }; +export const extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow = + ({ + flatObjectMetadataMaps: sourceFlatObjectMetadataMaps, + objectMetadataIds, + }: ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs): FlatObjectMetadataMaps => { + const emptyFlatObjectMetadataMaps: FlatObjectMetadataMaps = { + byId: {}, + idByNameSingular: {}, + }; + + return objectMetadataIds.reduce( + (flatObjectMetadataMaps, objectMetadataId) => { + const flatObjectMetadataWithFlatFieldMaps = + sourceFlatObjectMetadataMaps.byId[objectMetadataId]; + + if (!isDefined(flatObjectMetadataWithFlatFieldMaps)) { + throw new FlatObjectMetadataMapsException( + 'extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow object metadata not found', + FlatObjectMetadataMapsExceptionCode.OBJECT_METADATA_NOT_FOUND, + ); + } + + return addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow( + { + flatObjectMetadataMaps, + flatObjectMetadataWithFlatFieldMaps, + }, + ); + }, + emptyFlatObjectMetadataMaps, + ); + }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps.util.ts new file mode 100644 index 0000000000..6e23423a7f --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps.util.ts @@ -0,0 +1,17 @@ +import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { + ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs, + extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow, +} from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.util'; + +export const extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps = ( + args: ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs, +): FlatObjectMetadataMaps | undefined => { + try { + return extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow( + args, + ); + } catch { + return undefined; + } +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-maps-to-flat-object-metadatas.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-maps-to-flat-object-metadatas.util.ts new file mode 100644 index 0000000000..18896e9bb0 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-maps-to-flat-object-metadatas.util.ts @@ -0,0 +1,13 @@ +import { isDefined } from 'twenty-shared/utils'; + +import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-with-flat-field-maps-to-flat-object-metadatas.util'; + +export const fromFlatObjectMetadataMapsToFlatObjectMetadatas = ( + flatObjectMetadataMaps: FlatObjectMetadataMaps, +): FlatObjectMetadata[] => { + return Object.values(flatObjectMetadataMaps.byId) + .filter(isDefined) + .map(fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata); +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-to-flat-object-metadata-with-flat-field-maps.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-to-flat-object-metadata-with-flat-field-maps.util.ts index d7d720c57e..4e75b51f8c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-to-flat-object-metadata-with-flat-field-maps.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-to-flat-object-metadata-with-flat-field-maps.util.ts @@ -8,6 +8,8 @@ export const fromFlatObjectMetadataToFlatObjectMetadataWithFlatFieldMaps = ( const emptyFlatObjectMetadataWithFlatFieldMaps: FlatObjectMetadataWithFlatFieldMaps = { ...flatObjectMetadata, + flatIndexMetadatas: [], + flatFieldMetadatas: [], fieldIdByJoinColumnName: {}, fieldIdByName: {}, fieldsById: {}, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-maps-to-flat-object-metadatas.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-maps-to-flat-object-metadatas.util.ts deleted file mode 100644 index f7abdc263b..0000000000 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-maps-to-flat-object-metadatas.util.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { isDefined } from 'twenty-shared/utils'; - -import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; -import { fromObjectMetadataItemWithFieldMapsToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-item-with-field-maps-to-flat-object-metadata.util'; -import { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps'; - -export const fromObjectMetadataMapsToFlatObjectMetadatas = ( - objectMetadataMaps: ObjectMetadataMaps, -): FlatObjectMetadata[] => { - return Object.values(objectMetadataMaps.byId) - .filter(isDefined) - .map((objectMetadataItemWithFieldMaps) => - fromObjectMetadataItemWithFieldMapsToFlatObjectMetadata({ - objectMetadataItemWithFieldMaps, - objectMetadataMaps, - }), - ); -}; diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata-v2.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata-v2.service.ts index 406f203907..d260fa2f66 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata-v2.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata-v2.service.ts @@ -5,10 +5,11 @@ import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import { Repository } from 'typeorm'; import { fromCreateObjectInputToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-create-object-input-to-flat-object-metadata.util'; -import { fromObjectMetadataMapsToFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-maps-to-flat-object-metadatas.util'; import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service'; import { WorkspaceMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service'; import { WorkspaceMigrationRunnerV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-migration-runner-v2.service'; +import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { fromFlatObjectMetadataMapsToFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-maps-to-flat-object-metadatas.util'; import { ObjectMetadataEntity } from './object-metadata.entity'; @@ -30,8 +31,8 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService { - const { objectMetadataMaps } = - await this.workspaceMetadataCacheService.getExistingOrRecomputeMetadataMaps( + const { flatObjectMetadataMaps } = + await this.workspaceMetadataCacheService.getExistingOrRecomputeFlatObjectMetadataMaps( { workspaceId: objectMetadataInput.workspaceId, }, @@ -39,19 +40,23 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService