Workspace migration v2 builder embed field metadata validation (#13960)
# Introduction Following https://github.com/twentyhq/twenty/pull/13934 Finalizing object migration Also refactored existing to follow same for const loop pattern
This commit is contained in:
+147
-16
@@ -59,8 +59,6 @@ exports[`Workspace migration builder field actions test suite It should build an
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "default flat field metadata description",
|
||||
"flatRelationTargetFieldMetadata": null,
|
||||
"flatRelationTargetObjectMetadata": null,
|
||||
"icon": "icon",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
@@ -73,8 +71,8 @@ exports[`Workspace migration builder field actions test suite It should build an
|
||||
"name": "flatFieldMetadataName",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": null,
|
||||
"relationTargetObjectMetadataId": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"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<String>,
|
||||
"description": "default flat object metadata description",
|
||||
"description": "A rocket",
|
||||
"duplicateCriteria": null,
|
||||
"flatFieldMetadatas": [],
|
||||
"flatIndexMetadatas": [],
|
||||
"icon": "icon",
|
||||
"icon": "IconRocket",
|
||||
"id": Any<String>,
|
||||
"imageIdentifierFieldMetadataId": Any<String>,
|
||||
"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<String>,
|
||||
"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<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
@@ -136,6 +132,141 @@ exports[`Workspace migration builder field actions test suite It should build an
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
{
|
||||
"flatFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "default flat field metadata description",
|
||||
"flatRelationTargetFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "default flat field metadata description",
|
||||
"flatRelationTargetFieldMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"defaultValue": null,
|
||||
"description": "default flat field metadata description",
|
||||
"icon": "icon",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": true,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": false,
|
||||
"isUnique": false,
|
||||
"label": "flat field metadata label",
|
||||
"name": "flatFieldMetadataName",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": null,
|
||||
"standardId": null,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"uniqueIdentifier": "field-metadata-unique-identifier-2",
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"flatRelationTargetObjectMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"description": "A rocket",
|
||||
"duplicateCriteria": null,
|
||||
"icon": "IconRocket",
|
||||
"id": Any<String>,
|
||||
"imageIdentifierFieldMetadataId": null,
|
||||
"isActive": true,
|
||||
"isAuditLogged": true,
|
||||
"isCustom": true,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isRemote": false,
|
||||
"isSearchable": true,
|
||||
"isSystem": false,
|
||||
"labelIdentifierFieldMetadataId": Any<String>,
|
||||
"labelPlural": "Rockets",
|
||||
"labelSingular": "Rocket",
|
||||
"namePlural": "rockets",
|
||||
"nameSingular": "rocket",
|
||||
"shortcut": null,
|
||||
"standardId": null,
|
||||
"standardOverrides": null,
|
||||
"targetTableName": "DEPRECATED",
|
||||
"uniqueIdentifier": "d78ec657-74a4-4652-a350-1f44ff62970a",
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"icon": "icon",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": true,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": false,
|
||||
"isUnique": false,
|
||||
"label": "flat field metadata label",
|
||||
"name": "flatFieldMetadataName",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": null,
|
||||
"standardId": null,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"uniqueIdentifier": "field-metadata-unique-identifier-1",
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"flatRelationTargetObjectMetadata": {
|
||||
"createdAt": Any<String>,
|
||||
"description": null,
|
||||
"duplicateCriteria": null,
|
||||
"icon": "IconCat",
|
||||
"id": Any<String>,
|
||||
"imageIdentifierFieldMetadataId": null,
|
||||
"isActive": true,
|
||||
"isAuditLogged": true,
|
||||
"isCustom": true,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isRemote": false,
|
||||
"isSearchable": true,
|
||||
"isSystem": false,
|
||||
"labelIdentifierFieldMetadataId": Any<String>,
|
||||
"labelPlural": "Pets",
|
||||
"labelSingular": "Pet",
|
||||
"namePlural": "pets",
|
||||
"nameSingular": "pet",
|
||||
"shortcut": null,
|
||||
"standardId": null,
|
||||
"standardOverrides": null,
|
||||
"targetTableName": "DEPRECATED",
|
||||
"uniqueIdentifier": "d34e0f07-1b8c-4de0-938e-599cf05e1f7f",
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"icon": "icon",
|
||||
"id": Any<String>,
|
||||
"isActive": true,
|
||||
"isCustom": true,
|
||||
"isLabelSyncedWithName": false,
|
||||
"isNullable": true,
|
||||
"isSystem": false,
|
||||
"isUnique": false,
|
||||
"label": "flat field metadata label",
|
||||
"name": "flatFieldMetadataName",
|
||||
"objectMetadataId": Any<String>,
|
||||
"options": null,
|
||||
"relationTargetFieldMetadataId": Any<String>,
|
||||
"relationTargetObjectMetadataId": Any<String>,
|
||||
"settings": null,
|
||||
"standardId": null,
|
||||
"standardOverrides": null,
|
||||
"type": "RELATION",
|
||||
"uniqueIdentifier": "field-metadata-unique-identifier-2",
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
|
||||
+52
-20
@@ -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,
|
||||
|
||||
+1
-1
@@ -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<WorkspaceMigrationActionTypeV2>;
|
||||
|
||||
+15
-6
@@ -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))(
|
||||
|
||||
-6
@@ -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;
|
||||
+5
-3
@@ -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],
|
||||
})
|
||||
+44
-33
@@ -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<FlatObjectMetadataMaps, 'FlatObjectMetadataMaps'>;
|
||||
@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,
|
||||
],
|
||||
},
|
||||
+249
@@ -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<WorkspaceMigrationFieldActionV2>
|
||||
> {
|
||||
const validateAndBuildResult: ValidateAndBuildMetadataResult<WorkspaceMigrationFieldActionV2> =
|
||||
{
|
||||
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<WorkspaceMigrationFieldActionV2>
|
||||
> {
|
||||
let validateAndBuildResult: ValidateAndBuildMetadataResult<WorkspaceMigrationFieldActionV2> =
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
+178
@@ -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<WorkspaceMigrationObjectActionV2>
|
||||
> {
|
||||
const validateAndBuildResult: ValidateAndBuildMetadataResult<WorkspaceMigrationObjectActionV2> =
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
-10
@@ -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<T>[];
|
||||
};
|
||||
-10
@@ -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
|
||||
)[];
|
||||
};
|
||||
-10
@@ -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<T>;
|
||||
optimisticFlatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
};
|
||||
-7
@@ -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<T>;
|
||||
-8
@@ -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;
|
||||
};
|
||||
+15
@@ -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;
|
||||
};
|
||||
+4
-4
@@ -9,7 +9,7 @@ import {
|
||||
|
||||
export type UpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix = {
|
||||
flatObjectMetadata: FlatObjectMetadata;
|
||||
} & CustomDeletedCreatedUpdatedMatrix<'flatFieldMetadata', FlatFieldMetadata>;
|
||||
} & CustomDeletedCreatedUpdatedMatrix<'flatFieldMetadatas', FlatFieldMetadata>;
|
||||
|
||||
export const computeUpdatedObjectMetadataDeletedCreatedUpdatedFieldMatrix = (
|
||||
updatedObjectMetadata: FromTo<FlatObjectMetadata>[],
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
-19
@@ -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 =
|
||||
<T extends WorkspaceMigrationActionV2>(
|
||||
metadataBuildResults: MetadataValidateAndBuildResult<T>[],
|
||||
): FailedAndSuccessfulMetadataValidateAndBuildRecord<T> =>
|
||||
metadataBuildResults.reduce(
|
||||
(acc, buildResult) =>
|
||||
buildResult.status === 'fail'
|
||||
? {
|
||||
...acc,
|
||||
failed: [...acc.failed, buildResult],
|
||||
}
|
||||
: { ...acc, successful: [...acc.successful, buildResult] },
|
||||
EMPTY_FAILED_AND_SUCCESSFUL_METADATA_BUILD_RECORD,
|
||||
);
|
||||
-75
@@ -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<UpdateFieldAction>(({ 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;
|
||||
};
|
||||
-202
@@ -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<WorkspaceMigrationObjectActionV2>
|
||||
> {
|
||||
let optimisticFlatObjectMetadataMaps = structuredClone(
|
||||
fromFlatObjectMetadataMaps,
|
||||
);
|
||||
const createdObjectBuildResults = await Promise.all(
|
||||
createdFlatObjectMetadata.map<
|
||||
Promise<
|
||||
MetadataValidateAndBuildResult<WorkspaceMigrationObjectActionV2>
|
||||
>
|
||||
>(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<WorkspaceMigrationObjectActionV2>
|
||||
>((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<WorkspaceMigrationObjectActionV2>
|
||||
>(({ 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,
|
||||
],
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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';
|
||||
|
||||
|
||||
+8
-2
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user