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 bb56ddc01b..162db82556 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 @@ -8,7 +8,6 @@ import { } from 'twenty-shared/utils'; import { In, Repository } from 'typeorm'; -import { MultipleMetadataValidationErrors } from 'src/engine/core-modules/error/multiple-metadata-validation-errors'; import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; import { type DeleteOneFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/delete-field.input'; import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto'; @@ -18,8 +17,6 @@ import { FieldMetadataException, FieldMetadataExceptionCode, } 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 { type FailedFlatFieldMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; import { fromCreateFieldInputToFlatFieldMetadatasToCreate } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-metadatas-to-create.util'; import { fromDeleteFieldInputToFlatFieldMetadatasToDelete } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-delete-field-input-to-flat-field-metadatas-to-delete.util'; @@ -28,7 +25,6 @@ import { fromUpdateFieldInputToFlatFieldMetadata } from 'src/engine/metadata-mod import { isFlatFieldMetadataEntityOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util'; import { throwOnFieldInputTranspilationsError } from 'src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util'; import { type 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 { deleteFieldFromFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/delete-field-from-flat-object-metadata-maps-or-throw.util'; import { getSubFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/get-sub-flat-object-metadata-maps-or-throw.util'; @@ -44,7 +40,6 @@ export class FieldMetadataServiceV2 { private readonly fieldMetadataRepository: Repository, private readonly workspaceMetadataCacheService: WorkspaceMetadataCacheService, private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService, - private readonly flatFieldMetadataValidatorService: FlatFieldMetadataValidatorService, ) {} async createOne({ @@ -89,23 +84,6 @@ export class FieldMetadataServiceV2 { existingFlatObjectMetadataMaps, }); - const validationErrors = flatFieldMetadatasToDelete.flatMap( - (flatFieldMetadataToDelete) => - this.flatFieldMetadataValidatorService.validateFlatFieldMetadataDeletion( - { - existingFlatObjectMetadataMaps, - flatFieldMetadataToDelete, - }, - ), - ); - - if (validationErrors.length > 0) { - throw new MultipleMetadataValidationErrors( - validationErrors, - 'Multiple validation errors occurred while deleting field', - ); - } - const flatObjectMetadataMapsWithImpactedObject = getSubFlatObjectMetadataMapsOrThrow({ flatObjectMetadataMaps: existingFlatObjectMetadataMaps, @@ -219,22 +197,6 @@ export class FieldMetadataServiceV2 { const optimisticiallyUpdatedFlatFieldMetadata = inputTranspilationResult.result; - const validationErrors = - await this.flatFieldMetadataValidatorService.validateFlatFieldMetadataUpdate( - { - existingFlatObjectMetadataMaps, - flatFieldMetadataToValidate: optimisticiallyUpdatedFlatFieldMetadata, - workspaceId, - }, - ); - - if (validationErrors.length > 0) { - throw new MultipleMetadataValidationErrors( - validationErrors, - 'Multiple validation errors occurred while updating field', - ); - } - const fromFlatObjectMetadataMaps = getSubFlatObjectMetadataMapsOrThrow({ flatObjectMetadataMaps: existingFlatObjectMetadataMaps, objectMetadataIds: [ @@ -306,56 +268,6 @@ export class FieldMetadataServiceV2 { ({ result }) => result, ); - const allValidationErrors: FailedFlatFieldMetadataValidationExceptions[] = - []; - let optimisticFlatObjectMetadataMaps = structuredClone( - existingFlatObjectMetadataMaps, - ); - - for (const flatFieldMetadataToCreate of flatFieldMetadatasToCreate) { - const otherFlatObjectMetadataMapsToValidate = - this.computeOtherFlatObjectMetadataMapsToValidate({ - flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, - flatFieldMetadatasToCreate, - flatFieldMetadataToCreate, - }); - - const validationErrors = - await this.flatFieldMetadataValidatorService.validateFlatFieldMetadataCreation( - { - existingFlatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, - flatFieldMetadataToValidate: flatFieldMetadataToCreate, - workspaceId, - otherFlatObjectMetadataMapsToValidate, - }, - ); - - if (validationErrors.length > 0) { - allValidationErrors.push(...validationErrors); - continue; - } - - try { - optimisticFlatObjectMetadataMaps = - addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow({ - flatFieldMetadata: flatFieldMetadataToCreate, - flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, - }); - } catch { - throw new FieldMetadataException( - 'Optimistic cache manipulation failed, should never occur', - FieldMetadataExceptionCode.INTERNAL_SERVER_ERROR, - ); - } - } - - if (allValidationErrors.length > 0) { - throw new MultipleMetadataValidationErrors( - allValidationErrors, - 'Multiple validation errors occurred while creating field', - ); - } - const impactedObjectMetadataIds = Array.from( new Set( flatFieldMetadatasToCreate.map( @@ -369,7 +281,7 @@ export class FieldMetadataServiceV2 { objectMetadataIds: impactedObjectMetadataIds, }); const toFlatObjectMetadataMaps = getSubFlatObjectMetadataMapsOrThrow({ - flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, + flatObjectMetadataMaps: existingFlatObjectMetadataMaps, objectMetadataIds: impactedObjectMetadataIds, }); @@ -387,7 +299,6 @@ export class FieldMetadataServiceV2 { }, ); - // In the best of the world could consume runner returned value instead of searching in db here return this.fieldMetadataRepository.find({ where: { name: In( diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/services/flat-object-metadata-validator.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/services/flat-object-metadata-validator.service.ts index bbf74f40ba..a9d19b052d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/services/flat-object-metadata-validator.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/services/flat-object-metadata-validator.service.ts @@ -6,17 +6,15 @@ import { isDefined } from 'twenty-shared/utils'; 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 { findRelationFlatFieldMetadataTargetFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-relation-flat-field-metadatas-target-flat-field-metadata.util'; import { isFlatFieldMetadataEntityOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util'; import { type 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 { addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-to-flat-object-metadata-maps-or-throw.util'; import { findFlatObjectMetadataInFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/find-flat-object-metadata-in-flat-object-metadata-maps.util'; -import { getSubFlatObjectMetadataMapsOutOfFlatFieldMetadatas } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/get-sub-flat-object-metadata-maps-out-of-flat-field-metadatas.util'; import { FailedFlatObjectMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-object-metadata/types/failed-flat-object-metadata-validation.type'; import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { areFlatObjectMetadataNamesSyncedWithLabels } from 'src/engine/metadata-modules/flat-object-metadata/utils/are-flat-object-metadata-names-synced-with-labels.util'; +import { computeRelationTargetFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata/utils/compute-relation-target-flat-object-metadata-maps.util'; import { validateFlatObjectMetadataIdentifiers } from 'src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-identifiers.util'; import { validateFlatObjectMetadataLabel } from 'src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-label.util'; import { validateFlatObjectMetadataNames } from 'src/engine/metadata-modules/flat-object-metadata/validators/utils/validate-flat-object-metadata-name.util'; @@ -26,43 +24,7 @@ import { } from 'src/engine/metadata-modules/object-metadata/object-metadata.exception'; import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util'; import { doesOtherObjectWithSameNameExists } from 'src/engine/metadata-modules/utils/validate-no-other-object-with-same-name-exists-or-throw.util'; -import { WorkspaceMigrationV2BuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service'; - -const computeRelationTargetFlatObjectMetadataMapsForValidation = ({ - flatFieldMetadata, - flatObjectMetadataMaps, -}: { - flatFieldMetadata: FlatFieldMetadata; - flatObjectMetadataMaps: FlatObjectMetadataMaps; -}): FlatObjectMetadataMaps | undefined => { - if ( - !isFlatFieldMetadataEntityOfType( - flatFieldMetadata, - FieldMetadataType.RELATION, - ) && - !isFlatFieldMetadataEntityOfType( - flatFieldMetadata, - FieldMetadataType.MORPH_RELATION, - ) - ) { - return undefined; - } - - const relationTargetFlatFieldMetadata = - findRelationFlatFieldMetadataTargetFlatFieldMetadata({ - flatFieldMetadata, - flatObjectMetadataMaps, - }); - - if (!isDefined(relationTargetFlatFieldMetadata)) { - return undefined; - } - - return getSubFlatObjectMetadataMapsOutOfFlatFieldMetadatas({ - flatObjectMetadataMaps, - flatFieldMetadatas: [relationTargetFlatFieldMetadata], - }); -}; +import { WorkspaceMigrationV2BuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.service'; @Injectable() export class FlatObjectMetadataValidatorService { @@ -215,20 +177,29 @@ export class FlatObjectMetadataValidatorService { }); for (const flatFieldMetadataToValidate of flatObjectMetadataToValidate.flatFieldMetadatas) { + const relationTargetFlatObjectMetadataMaps = + (isFlatFieldMetadataEntityOfType( + flatFieldMetadataToValidate, + FieldMetadataType.RELATION, + ) || + isFlatFieldMetadataEntityOfType( + flatFieldMetadataToValidate, + FieldMetadataType.MORPH_RELATION, + )) && + isDefined(otherFlatObjectMetadataMapsToValidate) + ? computeRelationTargetFlatObjectMetadataMaps({ + flatFieldMetadata: flatFieldMetadataToValidate, + flatObjectMetadataMaps: otherFlatObjectMetadataMapsToValidate, + }) + : undefined; const flatFieldValidatorErrors = await this.flatFieldMetadataValidatorService.validateFlatFieldMetadataCreation( { existingFlatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, flatFieldMetadataToValidate, workspaceId: flatObjectMetadataToValidate.workspaceId, - otherFlatObjectMetadataMapsToValidate: isDefined( - otherFlatObjectMetadataMapsToValidate, - ) - ? computeRelationTargetFlatObjectMetadataMapsForValidation({ - flatFieldMetadata: flatFieldMetadataToValidate, - flatObjectMetadataMaps: otherFlatObjectMetadataMapsToValidate, - }) - : undefined, + otherFlatObjectMetadataMapsToValidate: + relationTargetFlatObjectMetadataMaps, }, ); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/compute-relation-target-flat-object-metadata-maps.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/compute-relation-target-flat-object-metadata-maps.util.ts new file mode 100644 index 0000000000..603cf1971a --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-object-metadata/utils/compute-relation-target-flat-object-metadata-maps.util.ts @@ -0,0 +1,32 @@ +import { type FieldMetadataType } from 'twenty-shared/types'; +import { isDefined } from 'twenty-shared/utils'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { findRelationFlatFieldMetadataTargetFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-relation-flat-field-metadatas-target-flat-field-metadata.util'; +import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { getSubFlatObjectMetadataMapsOutOfFlatFieldMetadatas } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/get-sub-flat-object-metadata-maps-out-of-flat-field-metadatas.util'; + +export const computeRelationTargetFlatObjectMetadataMaps = ({ + flatFieldMetadata, + flatObjectMetadataMaps, +}: { + flatFieldMetadata: FlatFieldMetadata< + FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION + >; + flatObjectMetadataMaps: FlatObjectMetadataMaps; +}): FlatObjectMetadataMaps | undefined => { + const relationTargetFlatFieldMetadata = + findRelationFlatFieldMetadataTargetFlatFieldMetadata({ + flatFieldMetadata, + flatObjectMetadataMaps, + }); + + if (!isDefined(relationTargetFlatFieldMetadata)) { + return undefined; + } + + return getSubFlatObjectMetadataMapsOutOfFlatFieldMetadatas({ + flatObjectMetadataMaps, + flatFieldMetadatas: [relationTargetFlatFieldMetadata], + }); +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/__snapshots__/workspace-migration-builder.spec.ts.snap b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/__snapshots__/workspace-migration-builder.spec.ts.snap index 6fd068990a..f13b656aa8 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/__snapshots__/workspace-migration-builder.spec.ts.snap +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/__snapshots__/workspace-migration-builder.spec.ts.snap @@ -59,8 +59,6 @@ exports[`Workspace migration builder field actions test suite It should build an "createdAt": Any, "defaultValue": null, "description": "default flat field metadata description", - "flatRelationTargetFieldMetadata": null, - "flatRelationTargetObjectMetadata": null, "icon": "icon", "id": Any, "isActive": true, @@ -73,8 +71,8 @@ exports[`Workspace migration builder field actions test suite It should build an "name": "flatFieldMetadataName", "objectMetadataId": Any, "options": null, - "relationTargetFieldMetadataId": null, - "relationTargetObjectMetadataId": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, "settings": null, "standardId": null, "standardOverrides": null, @@ -85,13 +83,11 @@ exports[`Workspace migration builder field actions test suite It should build an }, "flatRelationTargetObjectMetadata": { "createdAt": Any, - "description": "default flat object metadata description", + "description": "A rocket", "duplicateCriteria": null, - "flatFieldMetadatas": [], - "flatIndexMetadatas": [], - "icon": "icon", + "icon": "IconRocket", "id": Any, - "imageIdentifierFieldMetadataId": Any, + "imageIdentifierFieldMetadataId": null, "isActive": true, "isAuditLogged": true, "isCustom": true, @@ -100,15 +96,15 @@ exports[`Workspace migration builder field actions test suite It should build an "isSearchable": true, "isSystem": false, "labelIdentifierFieldMetadataId": Any, - "labelPlural": "default flat object metadata label plural", - "labelSingular": "default flat object metadata label singular", - "namePlural": "defaultflatObjectMetadataNamePlural", - "nameSingular": "defaultflatObjectMetadataNameSingular", - "shortcut": "shortcut", + "labelPlural": "Rockets", + "labelSingular": "Rocket", + "namePlural": "rockets", + "nameSingular": "rocket", + "shortcut": null, "standardId": null, "standardOverrides": null, - "targetTableName": "", - "uniqueIdentifier": "object-metadata-unique-identifier-2", + "targetTableName": "DEPRECATED", + "uniqueIdentifier": "d78ec657-74a4-4652-a350-1f44ff62970a", "updatedAt": Any, "workspaceId": Any, }, @@ -136,6 +132,141 @@ exports[`Workspace migration builder field actions test suite It should build an }, "type": "create_field", }, + { + "flatFieldMetadata": { + "createdAt": Any, + "defaultValue": null, + "description": "default flat field metadata description", + "flatRelationTargetFieldMetadata": { + "createdAt": Any, + "defaultValue": null, + "description": "default flat field metadata description", + "flatRelationTargetFieldMetadata": { + "createdAt": Any, + "defaultValue": null, + "description": "default flat field metadata description", + "icon": "icon", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUnique": false, + "label": "flat field metadata label", + "name": "flatFieldMetadataName", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": null, + "standardId": null, + "standardOverrides": null, + "type": "RELATION", + "uniqueIdentifier": "field-metadata-unique-identifier-2", + "updatedAt": Any, + "workspaceId": Any, + }, + "flatRelationTargetObjectMetadata": { + "createdAt": Any, + "description": "A rocket", + "duplicateCriteria": null, + "icon": "IconRocket", + "id": Any, + "imageIdentifierFieldMetadataId": null, + "isActive": true, + "isAuditLogged": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isRemote": false, + "isSearchable": true, + "isSystem": false, + "labelIdentifierFieldMetadataId": Any, + "labelPlural": "Rockets", + "labelSingular": "Rocket", + "namePlural": "rockets", + "nameSingular": "rocket", + "shortcut": null, + "standardId": null, + "standardOverrides": null, + "targetTableName": "DEPRECATED", + "uniqueIdentifier": "d78ec657-74a4-4652-a350-1f44ff62970a", + "updatedAt": Any, + "workspaceId": Any, + }, + "icon": "icon", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUnique": false, + "label": "flat field metadata label", + "name": "flatFieldMetadataName", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": null, + "standardId": null, + "standardOverrides": null, + "type": "RELATION", + "uniqueIdentifier": "field-metadata-unique-identifier-1", + "updatedAt": Any, + "workspaceId": Any, + }, + "flatRelationTargetObjectMetadata": { + "createdAt": Any, + "description": null, + "duplicateCriteria": null, + "icon": "IconCat", + "id": Any, + "imageIdentifierFieldMetadataId": null, + "isActive": true, + "isAuditLogged": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isRemote": false, + "isSearchable": true, + "isSystem": false, + "labelIdentifierFieldMetadataId": Any, + "labelPlural": "Pets", + "labelSingular": "Pet", + "namePlural": "pets", + "nameSingular": "pet", + "shortcut": null, + "standardId": null, + "standardOverrides": null, + "targetTableName": "DEPRECATED", + "uniqueIdentifier": "d34e0f07-1b8c-4de0-938e-599cf05e1f7f", + "updatedAt": Any, + "workspaceId": Any, + }, + "icon": "icon", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUnique": false, + "label": "flat field metadata label", + "name": "flatFieldMetadataName", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": null, + "standardId": null, + "standardOverrides": null, + "type": "RELATION", + "uniqueIdentifier": "field-metadata-unique-identifier-2", + "updatedAt": Any, + "workspaceId": Any, + }, + "type": "create_field", + }, ] `; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-field-test-case.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-field-test-case.ts index fdc3bb6532..4d7cb83d7b 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-field-test-case.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-field-test-case.ts @@ -1,5 +1,6 @@ import { faker } from '@faker-js/faker'; import { FieldMetadataType } from 'twenty-shared/types'; +import { removePropertiesFromRecord } from 'twenty-shared/utils'; import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; @@ -11,11 +12,10 @@ import { FLAT_OBJECT_METADATA_MAPS_MOCKS } from 'src/engine/metadata-modules/fla 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 { deleteFieldFromFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/delete-field-from-flat-object-metadata-maps-or-throw.util'; import { replaceFlatFieldMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/replace-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util'; -import { COMPANY_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/company-flat-object.mock'; -import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock'; 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 { type WorkspaceMigrationBuilderTestCase } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/types/workspace-migration-builder-test-case.type'; +import { fromFlatObjectMetadataToFlatObjectMetadataWithoutFields } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/from-flat-object-metadata-to-flat-object-metadata-without-fields.util'; // TODO prastoin test defaultValue and settings updates // TODO prastoin test standard abstraction in TDD style @@ -25,33 +25,58 @@ const relationTestCases: WorkspaceMigrationBuilderTestCase[] = [ title: 'It should build an create_field action for a RELATION field', context: { input: () => { - const createdFlatRelationFieldMetadata = getFlatFieldMetadataMock({ + const targetRelationId = faker.string.uuid(); + const sourceRelationId = faker.string.uuid(); + const sourceRelationFlatField = getFlatFieldMetadataMock({ + id: sourceRelationId, uniqueIdentifier: 'field-metadata-unique-identifier-1', objectMetadataId: PET_FLAT_OBJECT_MOCK.id, type: FieldMetadataType.RELATION, - relationTargetFieldMetadataId: faker.string.uuid(), - relationTargetObjectMetadataId: faker.string.uuid(), - flatRelationTargetFieldMetadata: getFlatFieldMetadataMock({ - objectMetadataId: COMPANY_FLAT_OBJECT_MOCK.id, - type: FieldMetadataType.RELATION, - uniqueIdentifier: 'field-metadata-unique-identifier-2', - }), - flatRelationTargetObjectMetadata: getFlatObjectMetadataMock({ - uniqueIdentifier: 'object-metadata-unique-identifier-2', - }), + relationTargetFieldMetadataId: targetRelationId, + relationTargetObjectMetadataId: ROCKET_FLAT_OBJECT_MOCK.id, + flatRelationTargetFieldMetadata: undefined, + flatRelationTargetObjectMetadata: + fromFlatObjectMetadataToFlatObjectMetadataWithoutFields( + ROCKET_FLAT_OBJECT_MOCK, + ), }); + const targetRelationFlatField = getFlatFieldMetadataMock({ + id: targetRelationId, + uniqueIdentifier: 'field-metadata-unique-identifier-2', + objectMetadataId: ROCKET_FLAT_OBJECT_MOCK.id, + type: FieldMetadataType.RELATION, + relationTargetFieldMetadataId: sourceRelationId, + relationTargetObjectMetadataId: PET_FLAT_OBJECT_MOCK.id, + flatRelationTargetFieldMetadata: sourceRelationFlatField, + flatRelationTargetObjectMetadata: + fromFlatObjectMetadataToFlatObjectMetadataWithoutFields( + PET_FLAT_OBJECT_MOCK, + ), + }); + + sourceRelationFlatField.flatRelationTargetFieldMetadata = + removePropertiesFromRecord(targetRelationFlatField, [ + 'flatRelationTargetFieldMetadata', + 'flatRelationTargetObjectMetadata', + ]); + const toFlatObjectMetadataMaps = [ + sourceRelationFlatField, + targetRelationFlatField, + ].reduce((flatObjectMetadataMaps, flatFieldMetadata) => { + return addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow({ + flatFieldMetadata, + flatObjectMetadataMaps, + }); + }, FLAT_OBJECT_METADATA_MAPS_MOCKS); + return { fromFlatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, - toFlatObjectMetadataMaps: - addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow({ - flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, - flatFieldMetadata: createdFlatRelationFieldMetadata, - }), + toFlatObjectMetadataMaps, }; }, expectedActionsTypeCounter: { - createField: 1, + createField: 2, }, }, }, @@ -168,7 +193,14 @@ const basicCrudTestCases: WorkspaceMigrationBuilderTestCase[] = [ title: 'It should build a delete_field action', context: { input: { - fromFlatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + fromFlatObjectMetadataMaps: + replaceFlatFieldMetadataInFlatObjectMetadataMapsOrThrow({ + flatFieldMetadata: getFlatFieldMetadataMock({ + ...PET_FLAT_FIELDS_MOCK.species, + isActive: false, + }), + flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }), toFlatObjectMetadataMaps: deleteFieldFromFlatObjectMetadataMapsOrThrow({ fieldMetadataId: PET_FLAT_FIELDS_MOCK.species.id, objectMetadataId: PET_FLAT_FIELDS_MOCK.species.objectMetadataId, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/types/workspace-migration-builder-test-case.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/types/workspace-migration-builder-test-case.type.ts index 26f2810571..a286969391 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/types/workspace-migration-builder-test-case.type.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/types/workspace-migration-builder-test-case.type.ts @@ -1,8 +1,8 @@ import { type EachTestingContext } from 'twenty-shared/testing'; +import { type WorkspaceMigrationBuildArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.service'; import { type ConvertActionTypeToCamelCase } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/convert-action-type-to-camel-case.type'; import { type WorkspaceMigrationActionTypeV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2'; -import { type WorkspaceMigrationBuildArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service'; export type CamelCasedWorkspaceMigrationActionsType = ConvertActionTypeToCamelCase; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/workspace-migration-builder.spec.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/workspace-migration-builder.spec.ts index e21921a064..ef8afcc7ef 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/workspace-migration-builder.spec.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/workspace-migration-builder.spec.ts @@ -6,7 +6,6 @@ import { type FeatureFlagService } from 'src/engine/core-modules/feature-flag/se import { FlatFieldMetadataTypeValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service'; import { FlatFieldMetadataValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service'; import { FlatObjectMetadataValidatorService } from 'src/engine/metadata-modules/flat-object-metadata/services/flat-object-metadata-validator.service'; -import { WorkspaceMigrationV2ObjectActionsBuilder } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-v2-object-actions-builder'; import { WORKSPACE_MIGRATION_FIELD_BUILDER_TEST_CASES } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-field-test-case'; import { WORKSPACE_MIGRATION_INDEX_BUILDER_TEST_CASES } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-index-test-case'; import { WORKSPACE_MIGRATION_OBJECT_BUILDER_TEST_CASES } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/common/workspace-migration-builder-object-test-case'; @@ -15,8 +14,10 @@ import { type ExpectedActionCounters, type WorkspaceMigrationBuilderTestCase, } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/__tests__/types/workspace-migration-builder-test-case.type'; +import { WorkspaceMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.service'; +import { WorkspaceMigrationV2FieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-v2-field-actions-builder.service'; +import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-v2-object-actions-builder.service'; import { type WorkspaceMigrationV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-v2'; -import { WorkspaceMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service'; const allWorkspaceBuilderTestCases: { label: string; @@ -83,7 +84,8 @@ describe.each(allWorkspaceBuilderTestCases)( let flatFieldMetadataTypeValidatorService: FlatFieldMetadataTypeValidatorService; let flatFieldMetadataValidatorService: FlatFieldMetadataValidatorService; let flatObjectMetadataValidatorService: FlatObjectMetadataValidatorService; - let objectActionsBuilder: WorkspaceMigrationV2ObjectActionsBuilder; + let objectActionsBuilder: WorkspaceMigrationV2ObjectActionsBuilderService; + let fieldActionsBuilder: WorkspaceMigrationV2FieldActionsBuilderService; beforeEach(() => { featureFlagService = { @@ -102,10 +104,17 @@ describe.each(allWorkspaceBuilderTestCases)( flatFieldMetadataValidatorService, ); - objectActionsBuilder = new WorkspaceMigrationV2ObjectActionsBuilder( - flatObjectMetadataValidatorService, + objectActionsBuilder = + new WorkspaceMigrationV2ObjectActionsBuilderService( + flatObjectMetadataValidatorService, + ); + fieldActionsBuilder = new WorkspaceMigrationV2FieldActionsBuilderService( + flatFieldMetadataValidatorService, + ); + service = new WorkspaceMigrationBuilderV2Service( + objectActionsBuilder, + fieldActionsBuilder, ); - service = new WorkspaceMigrationBuilderV2Service(objectActionsBuilder); }); it.each(eachTestingContextFilter(testCases))( diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/constants/empty-failed-and-successful-metadata-build-record.constant.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/constants/empty-failed-and-successful-metadata-build-record.constant.ts deleted file mode 100644 index eaf83b73f2..0000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/constants/empty-failed-and-successful-metadata-build-record.constant.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { type FailedAndSuccessfulMetadataValidateAndBuildRecord } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-and-successful-metadata-validate-and-build-record.type'; - -export const EMPTY_FAILED_AND_SUCCESSFUL_METADATA_BUILD_RECORD = { - failed: [], - successful: [], -} as const satisfies FailedAndSuccessfulMetadataValidateAndBuildRecord; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.module.ts similarity index 64% rename from packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts rename to packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.module.ts index f94bcb1248..f18212a584 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.module.ts @@ -4,8 +4,9 @@ import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature- import { FlatFieldMetadataTypeValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service'; import { FlatFieldMetadataValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service'; import { FlatObjectMetadataValidatorService } from 'src/engine/metadata-modules/flat-object-metadata/services/flat-object-metadata-validator.service'; -import { WorkspaceMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service'; -import { WorkspaceMigrationV2ObjectActionsBuilder } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-v2-object-actions-builder'; +import { WorkspaceMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.service'; +import { WorkspaceMigrationV2FieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-v2-field-actions-builder.service'; +import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-v2-object-actions-builder.service'; @Module({ imports: [FeatureFlagModule], @@ -13,8 +14,9 @@ import { WorkspaceMigrationV2ObjectActionsBuilder } from 'src/engine/workspace-m WorkspaceMigrationBuilderV2Service, FlatFieldMetadataValidatorService, FlatFieldMetadataTypeValidatorService, - WorkspaceMigrationV2ObjectActionsBuilder, + WorkspaceMigrationV2ObjectActionsBuilderService, FlatObjectMetadataValidatorService, + WorkspaceMigrationV2FieldActionsBuilderService, ], exports: [WorkspaceMigrationBuilderV2Service], }) diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.service.ts similarity index 64% rename from packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service.ts rename to packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.service.ts index dd52edabfc..ddb3b69ee1 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.service.ts @@ -2,18 +2,19 @@ import { Injectable } from '@nestjs/common'; import { type FromTo } from 'twenty-shared/types'; +import { FailedFlatFieldMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type'; import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { FailedFlatObjectMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-object-metadata/types/failed-flat-object-metadata-validation.type'; import { fromFlatObjectMetadataMapsToFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-maps-to-flat-object-metadatas.util'; import { deletedCreatedUpdatedMatrixDispatcher } from 'src/engine/workspace-manager/workspace-migration-v2/utils/deleted-created-updated-matrix-dispatcher.util'; -import { FailedMetadataValidateAndBuild } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-metadata-validate-and-build.type'; +import { WorkspaceMigrationV2FieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-v2-field-actions-builder.service'; +import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-v2-object-actions-builder.service'; import { WorkspaceMigrationV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-v2'; import { computeUpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/compute-updated-object-metadata-deleted-created-updated-field-matrix.util'; import { computeUpdatedObjectMetadataDeletedCreatedUpdatedIndexMatrix } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/compute-updated-object-metadata-deleted-created-updated-index-matrix.util'; import { getWorkspaceMigrationV2FieldDeleteAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-field-actions'; import { getWorkspaceMigrationV2CreateIndexAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-index-actions'; -import { buildWorkspaceMigrationV2FieldActions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-v2-field-actions-builder'; import { buildWorkspaceMigrationIndexActions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-v2-index-actions-builder'; -import { WorkspaceMigrationV2ObjectActionsBuilder } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-v2-object-actions-builder'; export type WorkspaceMigrationV2BuilderOptions = { inferDeletionFromMissingObjectFieldIndex: boolean; @@ -23,12 +24,12 @@ export type WorkspaceMigrationV2BuilderOptions = { export type WorkspaceMigrationBuildArgs = { workspaceId: string; buildOptions: WorkspaceMigrationV2BuilderOptions; - // Could from be optional ? we still have a race condition when if we recompute cache it could have been different than when we calculated the to } & FromTo; @Injectable() export class WorkspaceMigrationBuilderV2Service { constructor( - private readonly workspaceMigrationV2ObjectActionsBuilder: WorkspaceMigrationV2ObjectActionsBuilder, + private readonly workspaceMigrationV2ObjectActionsBuilderService: WorkspaceMigrationV2ObjectActionsBuilderService, + private readonly workspaceMigrationV2FieldActionsBuilderService: WorkspaceMigrationV2FieldActionsBuilderService, ) {} public async validateAndBuild({ @@ -37,7 +38,13 @@ export class WorkspaceMigrationBuilderV2Service { workspaceId, buildOptions, }: WorkspaceMigrationBuildArgs): Promise< - | FailedMetadataValidateAndBuild + | { + status: 'fail'; + errors: ( + | FailedFlatObjectMetadataValidationExceptions + | FailedFlatFieldMetadataValidationExceptions + )[]; + } | { status: 'success'; workspaceMigration: WorkspaceMigrationV2; @@ -52,9 +59,9 @@ export class WorkspaceMigrationBuilderV2Service { // Dispatch const { - created: createdFlatObjectMetadata, - deleted: deletedFlatObjectMetadata, - updated: updatedFlatObjectMetadata, + created: createdFlatObjectMetadatas, + deleted: deletedFlatObjectMetadatas, + updated: updatedFlatObjectMetadatas, } = deletedCreatedUpdatedMatrixDispatcher({ from: fromFlatObjectMetadatas, to: toFlatObjectMetadatas, @@ -62,30 +69,40 @@ export class WorkspaceMigrationBuilderV2Service { const objectMetadataDeletedCreatedUpdatedIndex = computeUpdatedObjectMetadataDeletedCreatedUpdatedIndexMatrix( - updatedFlatObjectMetadata, + updatedFlatObjectMetadatas, ); const objectMetadataDeletedCreatedUpdatedFields = computeUpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix( - updatedFlatObjectMetadata, + updatedFlatObjectMetadatas, ); /// // Validate and build - const objectWorkspaceMigrationActions = - await this.workspaceMigrationV2ObjectActionsBuilder.validateAndBuildObjectActions( + const objectActionsValidateAndBuildResult = + await this.workspaceMigrationV2ObjectActionsBuilderService.validateAndBuildObjectActions( { fromFlatObjectMetadataMaps, - createdFlatObjectMetadata, - deletedFlatObjectMetadata, + createdFlatObjectMetadatas, + deletedFlatObjectMetadatas, toFlatObjectMetadataMaps, - updatedFlatObjectMetadata, + updatedFlatObjectMetadatas, buildOptions, }, ); + const fieldActionsValidateAndBuildResult = + await this.workspaceMigrationV2FieldActionsBuilderService.validateAndBuildFieldActions( + { + buildOptions, + fromFlatObjectMetadataMaps, + toFlatObjectMetadataMaps, + objectMetadataDeletedCreatedUpdatedFields, + }, + ); + const createdObjectMetadataCreateIndexActions = - createdFlatObjectMetadata.flatMap((objectMetadata) => + createdFlatObjectMetadatas.flatMap((objectMetadata) => objectMetadata.flatIndexMetadatas.map( getWorkspaceMigrationV2CreateIndexAction, ), @@ -93,7 +110,7 @@ export class WorkspaceMigrationBuilderV2Service { const deletedObjectWorkspaceMigrationDeleteFieldActions = buildOptions.inferDeletionFromMissingObjectFieldIndex - ? deletedFlatObjectMetadata.flatMap((flatObjectMetadata) => + ? deletedFlatObjectMetadatas.flatMap((flatObjectMetadata) => flatObjectMetadata.flatFieldMetadatas.map((flatFieldMetadata) => getWorkspaceMigrationV2FieldDeleteAction({ flatFieldMetadata, @@ -103,13 +120,6 @@ export class WorkspaceMigrationBuilderV2Service { ) : []; - const fieldWorkspaceMigrationActions = - buildWorkspaceMigrationV2FieldActions({ - inferDeletionFromMissingObjectFieldIndex: - buildOptions.inferDeletionFromMissingObjectFieldIndex, - objectMetadataDeletedCreatedUpdatedFields, - }); - const indexWorkspaceMigrationActions = buildWorkspaceMigrationIndexActions({ objectMetadataDeletedCreatedUpdatedIndex, inferDeletionFromMissingObjectFieldIndex: @@ -117,12 +127,15 @@ export class WorkspaceMigrationBuilderV2Service { }); /// - if (objectWorkspaceMigrationActions.results.failed.length > 0) { + const allValidateAndBuildResultFailures = [ + ...objectActionsValidateAndBuildResult.failed, + ...fieldActionsValidateAndBuildResult.failed, + ]; + + if (allValidateAndBuildResultFailures.length > 0) { return { status: 'fail', - errors: objectWorkspaceMigrationActions.results.failed.flatMap( - (el) => el.errors, - ), + errors: allValidateAndBuildResultFailures, }; } @@ -132,11 +145,9 @@ export class WorkspaceMigrationBuilderV2Service { workspaceId, actions: [ ...deletedObjectWorkspaceMigrationDeleteFieldActions, - ...objectWorkspaceMigrationActions.results.successful.map( - (el) => el.result, - ), // TMP create util + ...objectActionsValidateAndBuildResult.successful, ...createdObjectMetadataCreateIndexActions, - ...fieldWorkspaceMigrationActions, + ...fieldActionsValidateAndBuildResult.successful, ...indexWorkspaceMigrationActions, ], }, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-v2-field-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-v2-field-actions-builder.service.ts new file mode 100644 index 0000000000..efdf3d4741 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-v2-field-actions-builder.service.ts @@ -0,0 +1,249 @@ +import { Injectable } from '@nestjs/common'; + +import { FieldMetadataType, FromTo } from 'twenty-shared/types'; + +import { FlatFieldMetadataValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service'; +import { compareTwoFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/compare-two-flat-field-metadata.util'; +import { isFlatFieldMetadataEntityOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.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 { deleteFieldFromFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/delete-field-from-flat-object-metadata-maps-or-throw.util'; +import { replaceFlatFieldMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/replace-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util'; +import { computeRelationTargetFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata/utils/compute-relation-target-flat-object-metadata-maps.util'; +import { WorkspaceMigrationV2BuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.service'; +import { ValidateAndBuildMetadataResult } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/validate-and-build-metadata-result.type'; +import { type WorkspaceMigrationFieldActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-field-action-v2'; +import { type UpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/compute-updated-object-metadata-deleted-created-updated-field-matrix.util'; +import { + getWorkspaceMigrationV2FieldCreateAction, + getWorkspaceMigrationV2FieldDeleteAction, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-field-actions'; + +type BuildWorkspaceMigrationV2FieldActionsArgs = FromTo< + FlatObjectMetadataMaps, + 'flatObjectMetadataMaps' +> & { + buildOptions: WorkspaceMigrationV2BuilderOptions; + objectMetadataDeletedCreatedUpdatedFields: UpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix[]; +}; + +type ValidateFlatObjectMetadataFlatFieldMetadataMatrixArgs = FromTo< + FlatObjectMetadataMaps, + 'flatObjectMetadataMaps' +> & + UpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix & { + buildOptions: WorkspaceMigrationV2BuilderOptions; + }; + +@Injectable() +export class WorkspaceMigrationV2FieldActionsBuilderService { + constructor( + private readonly flatFieldMetadataValidatorService: FlatFieldMetadataValidatorService, + ) {} + + private async validateFlatObjectMetadataFlatFieldMetadataMatrix({ + createdFlatFieldMetadatas, + deletedFlatFieldMetadatas, + flatObjectMetadata, + updatedFlatFieldMetadatas, + fromFlatObjectMetadataMaps, + toFlatObjectMetadataMaps, + buildOptions, + }: ValidateFlatObjectMetadataFlatFieldMetadataMatrixArgs): Promise< + ValidateAndBuildMetadataResult + > { + const validateAndBuildResult: ValidateAndBuildMetadataResult = + { + failed: [], + successful: [], + optimisticFlatObjectMetadataMaps: structuredClone( + fromFlatObjectMetadataMaps, + ), + }; + + for (const { + from: fromFlatFieldMetadata, + to: toFlatFieldMetadata, + } of updatedFlatFieldMetadatas) { + const updates = compareTwoFlatFieldMetadata({ + from: fromFlatFieldMetadata, + to: toFlatFieldMetadata, + }); + + if (updates.length === 0) { + continue; + } + + const { + workspaceId, + id: fieldMetadataId, + objectMetadataId, + } = toFlatFieldMetadata; + + const validationErrors = + await this.flatFieldMetadataValidatorService.validateFlatFieldMetadataUpdate( + { + existingFlatObjectMetadataMaps: fromFlatObjectMetadataMaps, + flatFieldMetadataToValidate: toFlatFieldMetadata, + workspaceId, + otherFlatObjectMetadataMapsToValidate: undefined, + }, + ); + + if (validationErrors.length > 0) { + validateAndBuildResult.failed.push(...validationErrors); + continue; + } + + validateAndBuildResult.optimisticFlatObjectMetadataMaps = + replaceFlatFieldMetadataInFlatObjectMetadataMapsOrThrow({ + flatFieldMetadata: toFlatFieldMetadata, + flatObjectMetadataMaps: + validateAndBuildResult.optimisticFlatObjectMetadataMaps, + }); + + validateAndBuildResult.successful.push({ + type: 'update_field', + fieldMetadataId, + objectMetadataId, + workspaceId, + updates, + }); + } + + for (const flatFieldMetadataToCreate of createdFlatFieldMetadatas) { + const relationTargetFlatObjectMetadataMaps = + isFlatFieldMetadataEntityOfType( + flatFieldMetadataToCreate, + FieldMetadataType.RELATION, + ) || + isFlatFieldMetadataEntityOfType( + flatFieldMetadataToCreate, + FieldMetadataType.MORPH_RELATION, + ) + ? computeRelationTargetFlatObjectMetadataMaps({ + flatFieldMetadata: flatFieldMetadataToCreate, + flatObjectMetadataMaps: toFlatObjectMetadataMaps, + }) + : undefined; + + const validationErrors = + await this.flatFieldMetadataValidatorService.validateFlatFieldMetadataCreation( + { + existingFlatObjectMetadataMaps: + validateAndBuildResult.optimisticFlatObjectMetadataMaps, + flatFieldMetadataToValidate: flatFieldMetadataToCreate, + workspaceId: flatFieldMetadataToCreate.workspaceId, + otherFlatObjectMetadataMapsToValidate: + relationTargetFlatObjectMetadataMaps, + }, + ); + + if (validationErrors.length > 0) { + validateAndBuildResult.failed.push(...validationErrors); + continue; + } + + validateAndBuildResult.optimisticFlatObjectMetadataMaps = + addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow({ + flatFieldMetadata: flatFieldMetadataToCreate, + flatObjectMetadataMaps: + validateAndBuildResult.optimisticFlatObjectMetadataMaps, + }); + + const createFieldAction = getWorkspaceMigrationV2FieldCreateAction({ + flatFieldMetadata: flatFieldMetadataToCreate, + flatObjectMetadata, + }); + + validateAndBuildResult.successful.push(createFieldAction); + } + + for (const flatFieldMetadataToDelete of buildOptions.inferDeletionFromMissingObjectFieldIndex + ? deletedFlatFieldMetadatas + : []) { + const validationErrors = + this.flatFieldMetadataValidatorService.validateFlatFieldMetadataDeletion( + { + existingFlatObjectMetadataMaps: + validateAndBuildResult.optimisticFlatObjectMetadataMaps, + flatFieldMetadataToDelete, + }, + ); + + if (validationErrors.length > 0) { + validateAndBuildResult.failed.push(...validationErrors); + continue; + } + + validateAndBuildResult.optimisticFlatObjectMetadataMaps = + deleteFieldFromFlatObjectMetadataMapsOrThrow({ + fieldMetadataId: flatFieldMetadataToDelete.id, + flatObjectMetadataMaps: + validateAndBuildResult.optimisticFlatObjectMetadataMaps, + objectMetadataId: flatFieldMetadataToDelete.objectMetadataId, + }); + + const deleteFieldAction = getWorkspaceMigrationV2FieldDeleteAction({ + flatFieldMetadata: flatFieldMetadataToDelete, + flatObjectMetadata, + }); + + validateAndBuildResult.successful.push(deleteFieldAction); + } + + return validateAndBuildResult; + } + + public async validateAndBuildFieldActions({ + buildOptions, + fromFlatObjectMetadataMaps, + toFlatObjectMetadataMaps, + objectMetadataDeletedCreatedUpdatedFields, + }: BuildWorkspaceMigrationV2FieldActionsArgs): Promise< + ValidateAndBuildMetadataResult + > { + let validateAndBuildResult: ValidateAndBuildMetadataResult = + { + failed: [], + successful: [], + optimisticFlatObjectMetadataMaps: structuredClone( + fromFlatObjectMetadataMaps, + ), + }; + + for (const { + createdFlatFieldMetadatas, + deletedFlatFieldMetadatas, + updatedFlatFieldMetadatas, + flatObjectMetadata, + } of objectMetadataDeletedCreatedUpdatedFields) { + const flatObjectMetadataFlatFieldMatrixValidateAndBuildResult = + await this.validateFlatObjectMetadataFlatFieldMetadataMatrix({ + createdFlatFieldMetadatas, + deletedFlatFieldMetadatas, + flatObjectMetadata, + fromFlatObjectMetadataMaps: + validateAndBuildResult.optimisticFlatObjectMetadataMaps, + updatedFlatFieldMetadatas, + toFlatObjectMetadataMaps, + buildOptions, + }); + + validateAndBuildResult = { + failed: [ + ...validateAndBuildResult.failed, + ...flatObjectMetadataFlatFieldMatrixValidateAndBuildResult.failed, + ], + successful: [ + ...validateAndBuildResult.successful, + ...flatObjectMetadataFlatFieldMatrixValidateAndBuildResult.successful, + ], + optimisticFlatObjectMetadataMaps: + flatObjectMetadataFlatFieldMatrixValidateAndBuildResult.optimisticFlatObjectMetadataMaps, + }; + } + + return validateAndBuildResult; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-v2-object-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-v2-object-actions-builder.service.ts new file mode 100644 index 0000000000..86fe9457d6 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-v2-object-actions-builder.service.ts @@ -0,0 +1,178 @@ +import { Injectable } from '@nestjs/common'; + +import { FromTo } from 'twenty-shared/types'; + +import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-to-flat-object-metadata-maps-or-throw.util'; +import { deleteObjectFromFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/delete-object-from-flat-object-metadata-maps-or-throw.util'; +import { replaceFlatObjectMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/replace-flat-object-metadata-in-flat-object-metadata-maps-or-throw.util'; +import { FlatObjectMetadataValidatorService } from 'src/engine/metadata-modules/flat-object-metadata/services/flat-object-metadata-validator.service'; +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { compareTwoFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/compare-two-flat-object-metadata.util'; +import { type CustomDeletedCreatedUpdatedMatrix } from 'src/engine/workspace-manager/workspace-migration-v2/utils/deleted-created-updated-matrix-dispatcher.util'; +import { WorkspaceMigrationV2BuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.service'; +import { ValidateAndBuildMetadataResult } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/validate-and-build-metadata-result.type'; +import { + UpdateObjectAction, + WorkspaceMigrationObjectActionV2, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-object-action-v2'; +import { getWorkspaceMigrationV2FieldCreateAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-field-actions'; +import { + getWorkspaceMigrationV2ObjectCreateAction, + getWorkspaceMigrationV2ObjectDeleteAction, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-object-actions'; + +export type CreatedDeletedUpdatedObjectMetadataInputMatrix = FromTo< + FlatObjectMetadataMaps, + 'FlatObjectMetadataMaps' +> & + CustomDeletedCreatedUpdatedMatrix< + 'flatObjectMetadatas', + FlatObjectMetadata + > & { + buildOptions: WorkspaceMigrationV2BuilderOptions; + fromFlatObjectMetadataMaps: FlatObjectMetadataMaps; // should be renamed to from + }; + +@Injectable() +export class WorkspaceMigrationV2ObjectActionsBuilderService { + constructor( + private readonly flatObjectMetadataValidatorService: FlatObjectMetadataValidatorService, + ) {} + + public async validateAndBuildObjectActions({ + createdFlatObjectMetadatas, + deletedFlatObjectMetadatas, + updatedFlatObjectMetadatas, + buildOptions, + fromFlatObjectMetadataMaps, + toFlatObjectMetadataMaps, + }: CreatedDeletedUpdatedObjectMetadataInputMatrix): Promise< + ValidateAndBuildMetadataResult + > { + const validateAndBuildResult: ValidateAndBuildMetadataResult = + { + failed: [], + successful: [], + optimisticFlatObjectMetadataMaps: structuredClone( + fromFlatObjectMetadataMaps, + ), + }; + + for (const flatObjectMetadataToCreate of createdFlatObjectMetadatas) { + const validationErrors = + await this.flatObjectMetadataValidatorService.validateFlatObjectMetadataCreation( + { + existingFlatObjectMetadataMaps: + validateAndBuildResult.optimisticFlatObjectMetadataMaps, + flatObjectMetadataToValidate: flatObjectMetadataToCreate, + otherFlatObjectMetadataMapsToValidate: toFlatObjectMetadataMaps, + }, + ); + + if (validationErrors.length > 0) { + validateAndBuildResult.failed.push(...validationErrors); + continue; + } + + validateAndBuildResult.optimisticFlatObjectMetadataMaps = + addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow({ + flatObjectMetadata: flatObjectMetadataToCreate, + flatObjectMetadataMaps: + validateAndBuildResult.optimisticFlatObjectMetadataMaps, + }); + + const createFieldActions = + flatObjectMetadataToCreate.flatFieldMetadatas.map((flatFieldMetadata) => + getWorkspaceMigrationV2FieldCreateAction({ + flatFieldMetadata, + flatObjectMetadata: flatObjectMetadataToCreate, + }), + ); + + const createObjectAction = getWorkspaceMigrationV2ObjectCreateAction({ + flatObjectMetadata: flatObjectMetadataToCreate, + createFieldActions, + }); + + validateAndBuildResult.successful.push(createObjectAction); + } + + for (const flatObjectMetadataToDelete of buildOptions.inferDeletionFromMissingObjectFieldIndex + ? deletedFlatObjectMetadatas + : []) { + const validationErrors = + this.flatObjectMetadataValidatorService.validateFlatObjectMetadataDeletion( + { + buildOptions, + existingFlatObjectMetadataMaps: + validateAndBuildResult.optimisticFlatObjectMetadataMaps, + objectMetadataToDeleteId: flatObjectMetadataToDelete.id, + }, + ); + + if (validationErrors.length > 0) { + validateAndBuildResult.failed.push(...validationErrors); + continue; + } + + validateAndBuildResult.optimisticFlatObjectMetadataMaps = + deleteObjectFromFlatObjectMetadataMapsOrThrow({ + objectMetadataId: flatObjectMetadataToDelete.id, + flatObjectMetadataMaps: + validateAndBuildResult.optimisticFlatObjectMetadataMaps, + }); + + const deleteObjectAction = getWorkspaceMigrationV2ObjectDeleteAction( + flatObjectMetadataToDelete, + ); + + validateAndBuildResult.successful.push(deleteObjectAction); + } + + for (const { + from: fromFlatObjectMetadata, + to: toFlatObjectMetadata, + } of updatedFlatObjectMetadatas) { + const objectUpdatedProperties = compareTwoFlatObjectMetadata({ + from: fromFlatObjectMetadata, + to: toFlatObjectMetadata, + }); + + if (objectUpdatedProperties.length === 0) { + continue; + } + + const validationErrors = + this.flatObjectMetadataValidatorService.validateFlatObjectMetadataUpdate( + { + existingFlatObjectMetadataMaps: + validateAndBuildResult.optimisticFlatObjectMetadataMaps, + updatedFlatObjectMetadata: toFlatObjectMetadata, + }, + ); + + if (validationErrors.length > 0) { + validateAndBuildResult.failed.push(...validationErrors); + continue; + } + + validateAndBuildResult.optimisticFlatObjectMetadataMaps = + replaceFlatObjectMetadataInFlatObjectMetadataMapsOrThrow({ + flatObjectMetadata: toFlatObjectMetadata, + flatObjectMetadataMaps: + validateAndBuildResult.optimisticFlatObjectMetadataMaps, + }); + + const updateObjectAction: UpdateObjectAction = { + type: 'update_object', + objectMetadataId: toFlatObjectMetadata.id, + updates: objectUpdatedProperties, + }; + + validateAndBuildResult.successful.push(updateObjectAction); + } + + return validateAndBuildResult; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-and-successful-metadata-validate-and-build-record.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-and-successful-metadata-validate-and-build-record.type.ts deleted file mode 100644 index db3ee5bcdf..0000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-and-successful-metadata-validate-and-build-record.type.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { type FailedMetadataValidateAndBuild } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-metadata-validate-and-build.type'; -import { type SuccessfulMetadataValidateAndBuild } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/successful-metadata-validate-and-build.type'; -import { type WorkspaceMigrationActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2'; - -export type FailedAndSuccessfulMetadataValidateAndBuildRecord< - T extends WorkspaceMigrationActionV2 = WorkspaceMigrationActionV2, -> = { - failed: FailedMetadataValidateAndBuild[]; - successful: SuccessfulMetadataValidateAndBuild[]; -}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-metadata-validate-and-build.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-metadata-validate-and-build.type.ts deleted file mode 100644 index 5ab45d44a7..0000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-metadata-validate-and-build.type.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { type FailedFlatFieldMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type'; -import { type FailedFlatObjectMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-object-metadata/types/failed-flat-object-metadata-validation.type'; - -export type FailedMetadataValidateAndBuild = { - status: 'fail'; - errors: ( - | FailedFlatFieldMetadataValidationExceptions - | FailedFlatObjectMetadataValidationExceptions - )[]; -}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/metadata-action-validate-and-build-result.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/metadata-action-validate-and-build-result.type.ts deleted file mode 100644 index f1e94da068..0000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/metadata-action-validate-and-build-result.type.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; -import { type FailedAndSuccessfulMetadataValidateAndBuildRecord } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-and-successful-metadata-validate-and-build-record.type'; -import { type WorkspaceMigrationActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2'; - -export type MetadataActionValidateAndBuildResult< - T extends WorkspaceMigrationActionV2, -> = { - results: FailedAndSuccessfulMetadataValidateAndBuildRecord; - optimisticFlatObjectMetadataMaps: FlatObjectMetadataMaps; -}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/metadata-validate-and-build-result.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/metadata-validate-and-build-result.type.ts deleted file mode 100644 index 28398a99f2..0000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/metadata-validate-and-build-result.type.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { type FailedMetadataValidateAndBuild } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-metadata-validate-and-build.type'; -import { type SuccessfulMetadataValidateAndBuild } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/successful-metadata-validate-and-build.type'; -import { type WorkspaceMigrationActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2'; - -export type MetadataValidateAndBuildResult< - T extends WorkspaceMigrationActionV2 = WorkspaceMigrationActionV2, -> = FailedMetadataValidateAndBuild | SuccessfulMetadataValidateAndBuild; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/successful-metadata-validate-and-build.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/successful-metadata-validate-and-build.type.ts deleted file mode 100644 index 2aa6833e63..0000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/successful-metadata-validate-and-build.type.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { type WorkspaceMigrationActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2'; - -export type SuccessfulMetadataValidateAndBuild< - T extends WorkspaceMigrationActionV2 = WorkspaceMigrationActionV2, -> = { - status: 'success'; - result: T; -}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/validate-and-build-metadata-result.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/validate-and-build-metadata-result.type.ts new file mode 100644 index 0000000000..1d4b9f88fd --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/validate-and-build-metadata-result.type.ts @@ -0,0 +1,15 @@ +import { type FailedFlatFieldMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type'; +import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { type FailedFlatObjectMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-object-metadata/types/failed-flat-object-metadata-validation.type'; +import { type WorkspaceMigrationActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2'; + +export type ValidateAndBuildMetadataResult< + T extends WorkspaceMigrationActionV2, +> = { + failed: ( + | FailedFlatFieldMetadataValidationExceptions + | FailedFlatObjectMetadataValidationExceptions + )[]; + successful: T[]; + optimisticFlatObjectMetadataMaps: FlatObjectMetadataMaps; +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/compute-updated-object-metadata-deleted-created-updated-field-matrix.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/compute-updated-object-metadata-deleted-created-updated-field-matrix.util.ts index 6ffe98e6e9..ff16960818 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/compute-updated-object-metadata-deleted-created-updated-field-matrix.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/compute-updated-object-metadata-deleted-created-updated-field-matrix.util.ts @@ -9,7 +9,7 @@ import { export type UpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix = { flatObjectMetadata: FlatObjectMetadata; -} & CustomDeletedCreatedUpdatedMatrix<'flatFieldMetadata', FlatFieldMetadata>; +} & CustomDeletedCreatedUpdatedMatrix<'flatFieldMetadatas', FlatFieldMetadata>; export const computeUpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix = ( updatedObjectMetadata: FromTo[], @@ -25,9 +25,9 @@ export const computeUpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix = ( matrixAccumulator.push({ flatObjectMetadata: to, - createdFlatFieldMetadata: fieldMetadataMatrix.created, - deletedFlatFieldMetadata: fieldMetadataMatrix.deleted, - updatedFlatFieldMetadata: fieldMetadataMatrix.updated, + createdFlatFieldMetadatas: fieldMetadataMatrix.created, + deletedFlatFieldMetadatas: fieldMetadataMatrix.deleted, + updatedFlatFieldMetadatas: fieldMetadataMatrix.updated, }); } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/from-metadata-build-results-to-failed-and-successful-metadata-build-record.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/from-metadata-build-results-to-failed-and-successful-metadata-build-record.util.ts deleted file mode 100644 index b49e0ef36c..0000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/from-metadata-build-results-to-failed-and-successful-metadata-build-record.util.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { EMPTY_FAILED_AND_SUCCESSFUL_METADATA_BUILD_RECORD } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/constants/empty-failed-and-successful-metadata-build-record.constant'; -import { type FailedAndSuccessfulMetadataValidateAndBuildRecord } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/failed-and-successful-metadata-validate-and-build-record.type'; -import { type MetadataValidateAndBuildResult } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/metadata-validate-and-build-result.type'; -import { type WorkspaceMigrationActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2'; - -export const fromMetadataBuildResultsToFailedAndSuccessfulMetadataBuildRecord = - ( - metadataBuildResults: MetadataValidateAndBuildResult[], - ): FailedAndSuccessfulMetadataValidateAndBuildRecord => - metadataBuildResults.reduce( - (acc, buildResult) => - buildResult.status === 'fail' - ? { - ...acc, - failed: [...acc.failed, buildResult], - } - : { ...acc, successful: [...acc.successful, buildResult] }, - EMPTY_FAILED_AND_SUCCESSFUL_METADATA_BUILD_RECORD, - ); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-v2-field-actions-builder.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-v2-field-actions-builder.ts deleted file mode 100644 index 816fc7f176..0000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-v2-field-actions-builder.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { compareTwoFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/compare-two-flat-field-metadata.util'; -import { - type UpdateFieldAction, - type WorkspaceMigrationFieldActionV2, -} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-field-action-v2'; -import { type UpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/compute-updated-object-metadata-deleted-created-updated-field-matrix.util'; -import { - getWorkspaceMigrationV2FieldCreateAction, - getWorkspaceMigrationV2FieldDeleteAction, -} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-field-actions'; - -type BuildWorkspaceMigrationV2FieldActionsArgs = { - inferDeletionFromMissingObjectFieldIndex: boolean; - objectMetadataDeletedCreatedUpdatedFields: UpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix[]; -}; -export const buildWorkspaceMigrationV2FieldActions = ({ - inferDeletionFromMissingObjectFieldIndex, - objectMetadataDeletedCreatedUpdatedFields, -}: BuildWorkspaceMigrationV2FieldActionsArgs): WorkspaceMigrationFieldActionV2[] => { - let allUpdatedObjectMetadataFieldActions: WorkspaceMigrationFieldActionV2[] = - []; - - for (const { - createdFlatFieldMetadata, - deletedFlatFieldMetadata, - updatedFlatFieldMetadata, - flatObjectMetadata, - } of objectMetadataDeletedCreatedUpdatedFields) { - const updateFieldActions = - updatedFlatFieldMetadata.flatMap(({ from, to }) => { - const updates = compareTwoFlatFieldMetadata({ - from, - to, - }); - - if (updates.length === 0) { - return []; - } - - return { - type: 'update_field', - fieldMetadataId: to.id, - objectMetadataId: to.objectMetadataId, - workspaceId: to.workspaceId, - updates, - }; - }); - - const createFieldAction = createdFlatFieldMetadata.map( - (flatFieldMetadata) => - getWorkspaceMigrationV2FieldCreateAction({ - flatFieldMetadata, - flatObjectMetadata, - }), - ); - - const deleteFieldAction = inferDeletionFromMissingObjectFieldIndex - ? deletedFlatFieldMetadata.map((flatFieldMetadata) => - getWorkspaceMigrationV2FieldDeleteAction({ - flatFieldMetadata, - flatObjectMetadata, - }), - ) - : []; - - allUpdatedObjectMetadataFieldActions = - allUpdatedObjectMetadataFieldActions.concat([ - ...createFieldAction, - ...deleteFieldAction, - ...updateFieldActions, - ]); - } - - return allUpdatedObjectMetadataFieldActions; -}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-v2-object-actions-builder.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-v2-object-actions-builder.ts deleted file mode 100644 index 020ba1e10c..0000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-v2-object-actions-builder.ts +++ /dev/null @@ -1,202 +0,0 @@ -import { Injectable } from '@nestjs/common'; - -import { FromTo } from 'twenty-shared/types'; - -import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; -import { addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-to-flat-object-metadata-maps-or-throw.util'; -import { deleteObjectFromFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/delete-object-from-flat-object-metadata-maps-or-throw.util'; -import { replaceFlatObjectMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/replace-flat-object-metadata-in-flat-object-metadata-maps-or-throw.util'; -import { FlatObjectMetadataValidatorService } from 'src/engine/metadata-modules/flat-object-metadata/services/flat-object-metadata-validator.service'; -import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; -import { compareTwoFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/compare-two-flat-object-metadata.util'; -import { type CustomDeletedCreatedUpdatedMatrix } from 'src/engine/workspace-manager/workspace-migration-v2/utils/deleted-created-updated-matrix-dispatcher.util'; -import { MetadataActionValidateAndBuildResult } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/metadata-action-validate-and-build-result.type'; -import { MetadataValidateAndBuildResult } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/metadata-validate-and-build-result.type'; -import { - UpdateObjectAction, - WorkspaceMigrationObjectActionV2, -} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-object-action-v2'; -import { fromMetadataBuildResultsToFailedAndSuccessfulMetadataBuildRecord } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/from-metadata-build-results-to-failed-and-successful-metadata-build-record.util'; -import { getWorkspaceMigrationV2FieldCreateAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-field-actions'; -import { - getWorkspaceMigrationV2ObjectCreateAction, - getWorkspaceMigrationV2ObjectDeleteAction, -} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/get-workspace-migration-v2-object-actions'; -import { WorkspaceMigrationV2BuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service'; - -export type CreatedDeletedUpdatedObjectMetadataInputMatrix = FromTo< - FlatObjectMetadataMaps, - 'FlatObjectMetadataMaps' -> & - CustomDeletedCreatedUpdatedMatrix< - 'flatObjectMetadata', - FlatObjectMetadata - > & { - buildOptions: WorkspaceMigrationV2BuilderOptions; - fromFlatObjectMetadataMaps: FlatObjectMetadataMaps; // should be renamed to from - }; - -@Injectable() -export class WorkspaceMigrationV2ObjectActionsBuilder { - constructor( - private readonly flatObjectMetadataValidatorService: FlatObjectMetadataValidatorService, - ) {} - - public async validateAndBuildObjectActions({ - createdFlatObjectMetadata, - deletedFlatObjectMetadata, - updatedFlatObjectMetadata, - buildOptions, - fromFlatObjectMetadataMaps, - toFlatObjectMetadataMaps, - }: CreatedDeletedUpdatedObjectMetadataInputMatrix): Promise< - MetadataActionValidateAndBuildResult - > { - let optimisticFlatObjectMetadataMaps = structuredClone( - fromFlatObjectMetadataMaps, - ); - const createdObjectBuildResults = await Promise.all( - createdFlatObjectMetadata.map< - Promise< - MetadataValidateAndBuildResult - > - >(async (flatObjectMetadata) => { - const validationErrors = - await this.flatObjectMetadataValidatorService.validateFlatObjectMetadataCreation( - { - existingFlatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, - flatObjectMetadataToValidate: flatObjectMetadata, - otherFlatObjectMetadataMapsToValidate: toFlatObjectMetadataMaps, - }, - ); - - if (validationErrors.length > 0) { - return { - status: 'fail', - errors: validationErrors, - }; - } - - optimisticFlatObjectMetadataMaps = - addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow({ - flatObjectMetadata: flatObjectMetadata, - flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, - }); - - const createFieldActions = flatObjectMetadata.flatFieldMetadatas.map( - (flatFieldMetadata) => - getWorkspaceMigrationV2FieldCreateAction({ - flatFieldMetadata, - flatObjectMetadata, - }), - ); - - const createObjectAction = getWorkspaceMigrationV2ObjectCreateAction({ - flatObjectMetadata, - createFieldActions, - }); - - return { - status: 'success', - result: createObjectAction, - }; - }), - ); - - const deletedObjectBuildResults = - buildOptions.inferDeletionFromMissingObjectFieldIndex - ? deletedFlatObjectMetadata.map< - MetadataValidateAndBuildResult - >((flatObjectMetadataToDelete) => { - const validationErrors = - this.flatObjectMetadataValidatorService.validateFlatObjectMetadataDeletion( - { - buildOptions, - existingFlatObjectMetadataMaps: - optimisticFlatObjectMetadataMaps, - objectMetadataToDeleteId: flatObjectMetadataToDelete.id, - }, - ); - - if (validationErrors.length > 0) { - return { - status: 'fail', - errors: validationErrors, - }; - } - - optimisticFlatObjectMetadataMaps = - deleteObjectFromFlatObjectMetadataMapsOrThrow({ - objectMetadataId: flatObjectMetadataToDelete.id, - flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, - }); - - const deleteObjectAction = - getWorkspaceMigrationV2ObjectDeleteAction( - flatObjectMetadataToDelete, - ); - - return { - status: 'success', - result: deleteObjectAction, - }; - }) - : []; - - const updatedObjectBuildResults = updatedFlatObjectMetadata.flatMap< - MetadataValidateAndBuildResult - >(({ from: fromFlatObjectMetadata, to: toFlatObjectMetadata }) => { - const objectUpdatedProperties = compareTwoFlatObjectMetadata({ - from: fromFlatObjectMetadata, - to: toFlatObjectMetadata, - }); - - if (objectUpdatedProperties.length === 0) { - return []; - } - - const validationErrors = - this.flatObjectMetadataValidatorService.validateFlatObjectMetadataUpdate( - { - existingFlatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, - updatedFlatObjectMetadata: toFlatObjectMetadata, - }, - ); - - if (validationErrors.length > 0) { - return { - status: 'fail', - errors: validationErrors, - }; - } - - optimisticFlatObjectMetadataMaps = - replaceFlatObjectMetadataInFlatObjectMetadataMapsOrThrow({ - flatObjectMetadata: toFlatObjectMetadata, - flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps, - }); - - const updateObjectAction: UpdateObjectAction = { - type: 'update_object', - objectMetadataId: toFlatObjectMetadata.id, - updates: objectUpdatedProperties, - }; - - return { - status: 'success', - result: updateObjectAction, - }; - }); - - return { - optimisticFlatObjectMetadataMaps, - results: fromMetadataBuildResultsToFailedAndSuccessfulMetadataBuildRecord( - [ - ...createdObjectBuildResults, - ...deletedObjectBuildResults, - ...updatedObjectBuildResults, - ], - ), - }; - } -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module.ts index 54c3f5a533..8327c3ec2d 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; -import { WorkspaceMigrationBuilderV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module'; +import { WorkspaceMigrationBuilderV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-migration-builder-v2.module'; import { WorkspaceMigrationRunnerV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-migration-runner-v2.module'; import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-validate-build-and-run-service'; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-validate-build-and-run-service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-validate-build-and-run-service.ts index 1890d7a984..9191eda028 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-validate-build-and-run-service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-validate-build-and-run-service.ts @@ -1,10 +1,10 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { MultipleMetadataValidationErrors } from 'src/engine/core-modules/error/multiple-metadata-validation-errors'; import { WorkspaceMigrationBuildArgs, WorkspaceMigrationBuilderV2Service, -} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service'; +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/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 { WorkspaceMigrationV2Exception, @@ -13,6 +13,10 @@ import { @Injectable() export class WorkspaceMigrationValidateBuildAndRunService { + private readonly logger = new Logger( + WorkspaceMigrationValidateBuildAndRunService.name, + ); + constructor( private readonly workspaceMigrationBuilderV2Service: WorkspaceMigrationBuilderV2Service, private readonly workspaceMigrationRunnerV2Service: WorkspaceMigrationRunnerV2Service, @@ -25,6 +29,7 @@ export class WorkspaceMigrationValidateBuildAndRunService { const validateAndBuildResult = await this.workspaceMigrationBuilderV2Service .validateAndBuild(builderArgs) .catch((error) => { + this.logger.error(error); throw new WorkspaceMigrationV2Exception( WorkspaceMigrationV2ExceptionCode.BUILDER_INTERNAL_SERVER_ERROR, error.message, @@ -41,6 +46,7 @@ export class WorkspaceMigrationValidateBuildAndRunService { await this.workspaceMigrationRunnerV2Service .run(validateAndBuildResult.workspaceMigration) .catch((error) => { + this.logger.error(error); throw new WorkspaceMigrationV2Exception( WorkspaceMigrationV2ExceptionCode.RUNNER_INTERNAL_SERVER_ERROR, error.message,