diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-morph-relation.service.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-morph-relation.service.ts index 0900c21843..00168da0d3 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-morph-relation.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/services/field-metadata-morph-relation.service.ts @@ -2,7 +2,10 @@ import { Injectable } from '@nestjs/common'; import omit from 'lodash.omit'; import { FieldMetadataType } from 'twenty-shared/types'; -import { isDefined } from 'twenty-shared/utils'; +import { + computeMorphRelationFieldJoinColumnName, + isDefined, +} from 'twenty-shared/utils'; import { type Repository } from 'typeorm'; import { v4 } from 'uuid'; @@ -15,7 +18,6 @@ import { FieldMetadataExceptionCode, } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; import { FieldMetadataRelationService } from 'src/engine/metadata-modules/field-metadata/services/field-metadata-relation.service'; -import { computeMorphRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-relation-field-join-column-name.util'; import { computeRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-relation-field-join-column-name.util'; import { prepareCustomFieldMetadataForCreation } from 'src/engine/metadata-modules/field-metadata/utils/prepare-field-metadata-for-creation.util'; import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/compute-morph-relation-field-join-column-name.util.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/compute-morph-relation-field-join-column-name.util.ts deleted file mode 100644 index b09e70f432..0000000000 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/compute-morph-relation-field-join-column-name.util.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { capitalize } from 'twenty-shared/utils'; - -type ComputeMorphRelationFieldJoinColumnNameArgs = { - name: string; - targetObjectMetadataNameSingular: string; -}; - -export const computeMorphRelationFieldJoinColumnName = ({ - name, - targetObjectMetadataNameSingular, -}: ComputeMorphRelationFieldJoinColumnNameArgs) => { - return `${name}${capitalize(targetObjectMetadataNameSingular)}Id`; -}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/__snapshots__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts.snap b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/__snapshots__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts.snap new file mode 100644 index 0000000000..b670f504bc --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/__snapshots__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts.snap @@ -0,0 +1,693 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test suite Failure cases should fail when morphRelationsCreationPayload has different relation types 1`] = ` +{ + "error": { + "code": "FIELD_METADATA_RELATION_MALFORMED", + "message": "Morph relation relations must have the same relation type", + "userFriendlyMessage": "Morph relation relations must have the same relation type", + }, + "status": "fail", +} +`; + +exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test suite Failure cases should fail when morphRelationsCreationPayload has invalid relation payload 1`] = ` +{ + "error": { + "code": "FIELD_METADATA_RELATION_MALFORMED", + "message": "Morph relation input transpilation failed", + "userFriendlyMessage": "Invalid morph relation input", + "value": [ + { + "targetObjectMetadataId": Any, + "type": "ONE_TO_MANY", + }, + ], + }, + "status": "fail", +} +`; + +exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test suite Failure cases should fail when morphRelationsCreationPayload has several references to same object metadata 1`] = ` +{ + "error": { + "code": "FIELD_METADATA_RELATION_MALFORMED", + "message": "Morph relation relations must have only relation to the same object metadata", + "userFriendlyMessage": "Morph relation relations must have only relation to the same object metadata", + }, + "status": "fail", +} +`; + +exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test suite Failure cases should fail when morphRelationsCreationPayload is empty array 1`] = ` +{ + "error": { + "code": "INVALID_FIELD_INPUT", + "message": "Relation creation payload is required", + "userFriendlyMessage": "Relation creation payload is required", + "value": [], + }, + "status": "fail", +} +`; + +exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test suite Failure cases should fail when morphRelationsCreationPayload is missing 1`] = ` +{ + "error": { + "code": "INVALID_FIELD_INPUT", + "message": "Relation creation payload is required", + "userFriendlyMessage": "Relation creation payload is required", + "value": undefined, + }, + "status": "fail", +} +`; + +exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test suite Failure cases should fail when target object metadata is not found 1`] = ` +{ + "error": { + "code": "FIELD_METADATA_RELATION_MALFORMED", + "message": "Morph relation input transpilation failed", + "userFriendlyMessage": "Invalid morph relation input", + "value": [ + { + "targetFieldIcon": "IconPet", + "targetFieldLabel": "Pet", + "targetObjectMetadataId": Any, + "type": "ONE_TO_MANY", + }, + ], + }, + "status": "fail", +} +`; + +exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test suite Success cases should create morph relation field metadata with valid input on rocket object to pet object 1`] = ` +{ + "result": [ + { + "createdAt": Any, + "defaultValue": null, + "description": "new field description", + "flatRelationTargetFieldMetadata": { + "createdAt": Any, + "defaultValue": null, + "description": null, + "flatRelationTargetFieldMetadata": { + "createdAt": Any, + "defaultValue": null, + "description": "new field description", + "flatRelationTargetFieldMetadata": null, + "flatRelationTargetObjectMetadata": { + "createdAt": Any, + "description": null, + "duplicateCriteria": null, + "flatFieldMetadatas": [], + "flatIndexMetadatas": [], + "icon": "IconCat", + "id": Any, + "imageIdentifierFieldMetadataId": null, + "isActive": true, + "isAuditLogged": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isRemote": false, + "isSearchable": true, + "isSystem": false, + "isUIReadOnly": false, + "labelIdentifierFieldMetadataId": Any, + "labelPlural": "Pets", + "labelSingular": "Pet", + "namePlural": "pets", + "nameSingular": "pet", + "shortcut": null, + "standardId": null, + "standardOverrides": null, + "targetTableName": "DEPRECATED", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "icon": "IconRelationOneToMany", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": null, + "label": "newFieldLabel", + "name": "newField", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": { + "relationType": "ONE_TO_MANY", + }, + "standardId": null, + "standardOverrides": null, + "type": "MORPH_RELATION", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "flatRelationTargetObjectMetadata": { + "createdAt": Any, + "description": "A rocket", + "duplicateCriteria": null, + "flatFieldMetadatas": [], + "flatIndexMetadatas": [], + "icon": "IconRocket", + "id": Any, + "imageIdentifierFieldMetadataId": null, + "isActive": true, + "isAuditLogged": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isRemote": false, + "isSearchable": true, + "isSystem": false, + "isUIReadOnly": false, + "labelIdentifierFieldMetadataId": Any, + "labelPlural": "Rockets", + "labelSingular": "Rocket", + "namePlural": "rockets", + "nameSingular": "rocket", + "shortcut": null, + "standardId": null, + "standardOverrides": null, + "targetTableName": "DEPRECATED", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "icon": "IconPet", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": null, + "label": "Pet", + "name": "pet", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": { + "joinColumnName": "petId", + "onDelete": "SET_NULL", + "relationType": "MANY_TO_ONE", + }, + "standardId": null, + "standardOverrides": null, + "type": "RELATION", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "flatRelationTargetObjectMetadata": { + "createdAt": Any, + "description": null, + "duplicateCriteria": null, + "flatFieldMetadatas": [], + "flatIndexMetadatas": [], + "icon": "IconCat", + "id": Any, + "imageIdentifierFieldMetadataId": null, + "isActive": true, + "isAuditLogged": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isRemote": false, + "isSearchable": true, + "isSystem": false, + "isUIReadOnly": false, + "labelIdentifierFieldMetadataId": Any, + "labelPlural": "Pets", + "labelSingular": "Pet", + "namePlural": "pets", + "nameSingular": "pet", + "shortcut": null, + "standardId": null, + "standardOverrides": null, + "targetTableName": "DEPRECATED", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "icon": "IconRelationOneToMany", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": null, + "label": "newFieldLabel", + "name": "newField", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": { + "relationType": "ONE_TO_MANY", + }, + "standardId": null, + "standardOverrides": null, + "type": "MORPH_RELATION", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + { + "createdAt": Any, + "defaultValue": null, + "description": null, + "flatRelationTargetFieldMetadata": { + "createdAt": Any, + "defaultValue": null, + "description": "new field description", + "flatRelationTargetFieldMetadata": null, + "flatRelationTargetObjectMetadata": { + "createdAt": Any, + "description": null, + "duplicateCriteria": null, + "flatFieldMetadatas": [], + "flatIndexMetadatas": [], + "icon": "IconCat", + "id": Any, + "imageIdentifierFieldMetadataId": null, + "isActive": true, + "isAuditLogged": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isRemote": false, + "isSearchable": true, + "isSystem": false, + "isUIReadOnly": false, + "labelIdentifierFieldMetadataId": Any, + "labelPlural": "Pets", + "labelSingular": "Pet", + "namePlural": "pets", + "nameSingular": "pet", + "shortcut": null, + "standardId": null, + "standardOverrides": null, + "targetTableName": "DEPRECATED", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "icon": "IconRelationOneToMany", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": null, + "label": "newFieldLabel", + "name": "newField", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": { + "relationType": "ONE_TO_MANY", + }, + "standardId": null, + "standardOverrides": null, + "type": "MORPH_RELATION", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "flatRelationTargetObjectMetadata": { + "createdAt": Any, + "description": "A rocket", + "duplicateCriteria": null, + "flatFieldMetadatas": [], + "flatIndexMetadatas": [], + "icon": "IconRocket", + "id": Any, + "imageIdentifierFieldMetadataId": null, + "isActive": true, + "isAuditLogged": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isRemote": false, + "isSearchable": true, + "isSystem": false, + "isUIReadOnly": false, + "labelIdentifierFieldMetadataId": Any, + "labelPlural": "Rockets", + "labelSingular": "Rocket", + "namePlural": "rockets", + "nameSingular": "rocket", + "shortcut": null, + "standardId": null, + "standardOverrides": null, + "targetTableName": "DEPRECATED", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "icon": "IconPet", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": null, + "label": "Pet", + "name": "pet", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": { + "joinColumnName": "petId", + "onDelete": "SET_NULL", + "relationType": "MANY_TO_ONE", + }, + "standardId": null, + "standardOverrides": null, + "type": "RELATION", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + { + "createdAt": Any, + "defaultValue": null, + "description": "new field description", + "flatRelationTargetFieldMetadata": { + "createdAt": Any, + "defaultValue": null, + "description": null, + "flatRelationTargetFieldMetadata": { + "createdAt": Any, + "defaultValue": null, + "description": "new field description", + "flatRelationTargetFieldMetadata": null, + "flatRelationTargetObjectMetadata": { + "createdAt": Any, + "description": "A company", + "duplicateCriteria": null, + "flatFieldMetadatas": [], + "flatIndexMetadatas": [], + "icon": "IconBuildingSkyscraper", + "id": Any, + "imageIdentifierFieldMetadataId": null, + "isActive": true, + "isAuditLogged": true, + "isCustom": false, + "isLabelSyncedWithName": false, + "isRemote": false, + "isSearchable": true, + "isSystem": false, + "isUIReadOnly": false, + "labelIdentifierFieldMetadataId": Any, + "labelPlural": "Companies", + "labelSingular": "Company", + "namePlural": "companies", + "nameSingular": "company", + "shortcut": "C", + "standardId": Any, + "standardOverrides": null, + "targetTableName": "DEPRECATED", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "icon": "IconRelationOneToMany", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": null, + "label": "newFieldLabel", + "name": "newField", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": { + "relationType": "ONE_TO_MANY", + }, + "standardId": null, + "standardOverrides": null, + "type": "MORPH_RELATION", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "flatRelationTargetObjectMetadata": { + "createdAt": Any, + "description": "A rocket", + "duplicateCriteria": null, + "flatFieldMetadatas": [], + "flatIndexMetadatas": [], + "icon": "IconRocket", + "id": Any, + "imageIdentifierFieldMetadataId": null, + "isActive": true, + "isAuditLogged": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isRemote": false, + "isSearchable": true, + "isSystem": false, + "isUIReadOnly": false, + "labelIdentifierFieldMetadataId": Any, + "labelPlural": "Rockets", + "labelSingular": "Rocket", + "namePlural": "rockets", + "nameSingular": "rocket", + "shortcut": null, + "standardId": null, + "standardOverrides": null, + "targetTableName": "DEPRECATED", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "icon": "IconBuilding", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": null, + "label": "Company", + "name": "company", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": { + "joinColumnName": "companyId", + "onDelete": "SET_NULL", + "relationType": "MANY_TO_ONE", + }, + "standardId": null, + "standardOverrides": null, + "type": "RELATION", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "flatRelationTargetObjectMetadata": { + "createdAt": Any, + "description": "A company", + "duplicateCriteria": null, + "flatFieldMetadatas": [], + "flatIndexMetadatas": [], + "icon": "IconBuildingSkyscraper", + "id": Any, + "imageIdentifierFieldMetadataId": null, + "isActive": true, + "isAuditLogged": true, + "isCustom": false, + "isLabelSyncedWithName": false, + "isRemote": false, + "isSearchable": true, + "isSystem": false, + "isUIReadOnly": false, + "labelIdentifierFieldMetadataId": Any, + "labelPlural": "Companies", + "labelSingular": "Company", + "namePlural": "companies", + "nameSingular": "company", + "shortcut": "C", + "standardId": Any, + "standardOverrides": null, + "targetTableName": "DEPRECATED", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "icon": "IconRelationOneToMany", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": null, + "label": "newFieldLabel", + "name": "newField", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": { + "relationType": "ONE_TO_MANY", + }, + "standardId": null, + "standardOverrides": null, + "type": "MORPH_RELATION", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + { + "createdAt": Any, + "defaultValue": null, + "description": null, + "flatRelationTargetFieldMetadata": { + "createdAt": Any, + "defaultValue": null, + "description": "new field description", + "flatRelationTargetFieldMetadata": null, + "flatRelationTargetObjectMetadata": { + "createdAt": Any, + "description": "A company", + "duplicateCriteria": null, + "flatFieldMetadatas": [], + "flatIndexMetadatas": [], + "icon": "IconBuildingSkyscraper", + "id": Any, + "imageIdentifierFieldMetadataId": null, + "isActive": true, + "isAuditLogged": true, + "isCustom": false, + "isLabelSyncedWithName": false, + "isRemote": false, + "isSearchable": true, + "isSystem": false, + "isUIReadOnly": false, + "labelIdentifierFieldMetadataId": Any, + "labelPlural": "Companies", + "labelSingular": "Company", + "namePlural": "companies", + "nameSingular": "company", + "shortcut": "C", + "standardId": Any, + "standardOverrides": null, + "targetTableName": "DEPRECATED", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "icon": "IconRelationOneToMany", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": null, + "label": "newFieldLabel", + "name": "newField", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": { + "relationType": "ONE_TO_MANY", + }, + "standardId": null, + "standardOverrides": null, + "type": "MORPH_RELATION", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "flatRelationTargetObjectMetadata": { + "createdAt": Any, + "description": "A rocket", + "duplicateCriteria": null, + "flatFieldMetadatas": [], + "flatIndexMetadatas": [], + "icon": "IconRocket", + "id": Any, + "imageIdentifierFieldMetadataId": null, + "isActive": true, + "isAuditLogged": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isRemote": false, + "isSearchable": true, + "isSystem": false, + "isUIReadOnly": false, + "labelIdentifierFieldMetadataId": Any, + "labelPlural": "Rockets", + "labelSingular": "Rocket", + "namePlural": "rockets", + "nameSingular": "rocket", + "shortcut": null, + "standardId": null, + "standardOverrides": null, + "targetTableName": "DEPRECATED", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + "icon": "IconBuilding", + "id": Any, + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": null, + "label": "Company", + "name": "company", + "objectMetadataId": Any, + "options": null, + "relationTargetFieldMetadataId": Any, + "relationTargetObjectMetadataId": Any, + "settings": { + "joinColumnName": "companyId", + "onDelete": "SET_NULL", + "relationType": "MANY_TO_ONE", + }, + "standardId": null, + "standardOverrides": null, + "type": "RELATION", + "uniqueIdentifier": Any, + "updatedAt": Any, + "workspaceId": Any, + }, + ], + "status": "success", +} +`; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts new file mode 100644 index 0000000000..9099b322f1 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__tests__/morph-relation-from-create-field-input-to-flat-field-metadatas-to-create.spec.ts @@ -0,0 +1,273 @@ +import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any'; +import { type EachTestingContext } from 'twenty-shared/testing'; +import { FieldMetadataType } from 'twenty-shared/types'; + +import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; + +import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; +import { fromCreateFieldInputToFlatFieldMetadatasToCreate } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-metadatas-to-create.util'; +import { FLAT_OBJECT_METADATA_MAPS_MOCKS } from 'src/engine/metadata-modules/flat-object-metadata-maps/mocks/flat-object-metadata-maps.mock'; +import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +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 { COMPANY_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/company-flat-object.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'; + +const existingFlatObjectMetadataMaps = [ + COMPANY_FLAT_OBJECT_MOCK, + ROCKET_FLAT_OBJECT_MOCK, + PET_FLAT_OBJECT_MOCK, +].reduce((flatObjectMetadataMaps, flatObjectMetadata) => { + return replaceFlatObjectMetadataInFlatObjectMetadataMapsOrThrow({ + flatObjectMetadata: { + ...flatObjectMetadata, + flatFieldMetadatas: [], + }, + flatObjectMetadataMaps, + }); +}, FLAT_OBJECT_METADATA_MAPS_MOCKS); + +type TestCase = EachTestingContext<{ + input: { + rawCreateFieldInput: CreateFieldInput & + Required>; + workspaceId: string; + existingFlatObjectMetadataMaps: FlatObjectMetadataMaps; + }; + expected: 'success' | 'fail'; +}>; + +describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test suite', () => { + const mockWorkspaceId = 'mock-workspace-id'; + + describe('Success cases', () => { + const successTestCases: TestCase[] = [ + { + title: + 'should create morph relation field metadata with valid input on rocket object to pet object', + context: { + input: { + rawCreateFieldInput: { + name: 'newField', + label: 'newFieldLabel', + description: 'new field description', + type: FieldMetadataType.MORPH_RELATION, + objectMetadataId: ROCKET_FLAT_OBJECT_MOCK.id, + workspaceId: mockWorkspaceId, + morphRelationsCreationPayload: [ + { + type: RelationType.ONE_TO_MANY, + targetObjectMetadataId: PET_FLAT_OBJECT_MOCK.id, + targetFieldLabel: 'Pet', + targetFieldIcon: 'IconPet', + }, + { + type: RelationType.ONE_TO_MANY, + targetObjectMetadataId: COMPANY_FLAT_OBJECT_MOCK.id, + targetFieldLabel: 'Company', + targetFieldIcon: 'IconBuilding', + }, + ], + }, + workspaceId: mockWorkspaceId, + existingFlatObjectMetadataMaps, + }, + expected: 'success', + }, + }, + ]; + + test.each(successTestCases)( + '$title', + async ({ context: { input, expected } }) => { + const result = + await fromCreateFieldInputToFlatFieldMetadatasToCreate(input); + + expect(result.status).toEqual(expected); + if (result.status !== 'success') { + throw new Error('Should never occur, typecheck'); + } + expect(result.result.length).toBe( + input.rawCreateFieldInput.morphRelationsCreationPayload.length * 2, + ); + expect(result).toMatchSnapshot( + extractRecordIdsAndDatesAsExpectAny(result), + ); + }, + ); + }); + + describe('Failure cases', () => { + const failureTestCases: TestCase[] = [ + { + title: 'should fail when morphRelationsCreationPayload is missing', + context: { + input: { + rawCreateFieldInput: { + name: 'newField', + label: 'newFieldLabel', + description: 'new field description', + type: FieldMetadataType.MORPH_RELATION, + objectMetadataId: ROCKET_FLAT_OBJECT_MOCK.id, + workspaceId: mockWorkspaceId, + morphRelationsCreationPayload: undefined as any, + }, + workspaceId: mockWorkspaceId, + existingFlatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }, + expected: 'fail', + }, + }, + { + title: 'should fail when morphRelationsCreationPayload is empty array', + context: { + input: { + rawCreateFieldInput: { + name: 'newField', + label: 'newFieldLabel', + description: 'new field description', + type: FieldMetadataType.MORPH_RELATION, + objectMetadataId: ROCKET_FLAT_OBJECT_MOCK.id, + workspaceId: mockWorkspaceId, + morphRelationsCreationPayload: [], + }, + workspaceId: mockWorkspaceId, + existingFlatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }, + expected: 'fail', + }, + }, + { + title: + 'should fail when morphRelationsCreationPayload has different relation types', + context: { + input: { + rawCreateFieldInput: { + name: 'newField', + label: 'newFieldLabel', + description: 'new field description', + type: FieldMetadataType.MORPH_RELATION, + objectMetadataId: ROCKET_FLAT_OBJECT_MOCK.id, + workspaceId: mockWorkspaceId, + morphRelationsCreationPayload: [ + { + type: RelationType.ONE_TO_MANY, + targetObjectMetadataId: PET_FLAT_OBJECT_MOCK.id, + targetFieldLabel: 'Pet', + targetFieldIcon: 'IconPet', + }, + { + type: RelationType.MANY_TO_ONE, + targetObjectMetadataId: COMPANY_FLAT_OBJECT_MOCK.id, + targetFieldLabel: 'Company', + targetFieldIcon: 'IconPet', + }, + ], + }, + workspaceId: mockWorkspaceId, + existingFlatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }, + expected: 'fail', + }, + }, + { + title: + 'should fail when morphRelationsCreationPayload has several references to same object metadata', + context: { + input: { + rawCreateFieldInput: { + name: 'newField', + label: 'newFieldLabel', + description: 'new field description', + type: FieldMetadataType.MORPH_RELATION, + objectMetadataId: ROCKET_FLAT_OBJECT_MOCK.id, + workspaceId: mockWorkspaceId, + morphRelationsCreationPayload: [ + { + type: RelationType.MANY_TO_ONE, + targetObjectMetadataId: PET_FLAT_OBJECT_MOCK.id, + targetFieldLabel: 'Pet', + targetFieldIcon: 'IconPet', + }, + { + type: RelationType.MANY_TO_ONE, + targetObjectMetadataId: PET_FLAT_OBJECT_MOCK.id, + targetFieldLabel: 'Pet', + targetFieldIcon: 'IconPet', + }, + ], + }, + workspaceId: mockWorkspaceId, + existingFlatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }, + expected: 'fail', + }, + }, + { + title: + 'should fail when morphRelationsCreationPayload has invalid relation payload', + context: { + input: { + rawCreateFieldInput: { + name: 'newField', + label: 'newFieldLabel', + description: 'new field description', + type: FieldMetadataType.MORPH_RELATION, + objectMetadataId: ROCKET_FLAT_OBJECT_MOCK.id, + workspaceId: mockWorkspaceId, + morphRelationsCreationPayload: [ + { + type: RelationType.ONE_TO_MANY, + targetObjectMetadataId: PET_FLAT_OBJECT_MOCK.id, + // Missing required fields + } as any, + ], + }, + workspaceId: mockWorkspaceId, + existingFlatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }, + expected: 'fail', + }, + }, + { + title: 'should fail when target object metadata is not found', + context: { + input: { + rawCreateFieldInput: { + name: 'newField', + label: 'newFieldLabel', + description: 'new field description', + type: FieldMetadataType.MORPH_RELATION, + objectMetadataId: ROCKET_FLAT_OBJECT_MOCK.id, + workspaceId: mockWorkspaceId, + morphRelationsCreationPayload: [ + { + type: RelationType.ONE_TO_MANY, + targetObjectMetadataId: 'non-existent-id', + targetFieldLabel: 'Pet', + targetFieldIcon: 'IconPet', + }, + ], + }, + workspaceId: mockWorkspaceId, + existingFlatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS, + }, + expected: 'fail', + }, + }, + ]; + + test.each(failureTestCases)( + '$title', + async ({ context: { input, expected } }) => { + const result = + await fromCreateFieldInputToFlatFieldMetadatasToCreate(input); + + expect(result.status).toEqual(expected); + expect(result).toMatchSnapshot( + extractRecordIdsAndDatesAsExpectAny(result), + ); + }, + ); + }); +}); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-metadatas-to-create.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-metadatas-to-create.util.ts index af18916a1b..a1af7d4675 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-metadatas-to-create.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-metadatas-to-create.util.ts @@ -9,15 +9,16 @@ import { v4 } from 'uuid'; import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface'; -import { UserInputError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; import { generateRatingOptions } from 'src/engine/metadata-modules/field-metadata/utils/generate-rating-optionts.util'; import { type FieldInputTranspilationResult } from 'src/engine/metadata-modules/flat-field-metadata/types/field-input-transpilation-result.type'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { fromRelationCreateFieldInputToFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-relation-create-field-input-to-flat-field-metadata.util'; +import { fromMorphRelationCreateFieldInputToFlatFieldMetadatas } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-morph-relation-create-field-input-to-flat-field-metadatas.util'; +import { fromRelationCreateFieldInputToFlatFieldMetadatas } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-relation-create-field-input-to-flat-field-metadatas.util'; import { getDefaultFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/get-default-flat-field-metadata-from-create-field-input.util'; import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-with-flat-field-maps-to-flat-object-metadatas.util'; type FromCreateFieldInputToFlatObjectMetadataArgs = { rawCreateFieldInput: Omit; @@ -46,10 +47,10 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({ rawCreateFieldInput, ['description', 'icon', 'label', 'name', 'objectMetadataId', 'type'], ); - const parentFlatObjectMetadata = + const parentFlatObjectMetadataWithFlatFieldMaps = existingFlatObjectMetadataMaps.byId[createFieldInput.objectMetadataId]; - if (!isDefined(parentFlatObjectMetadata)) { + if (!isDefined(parentFlatObjectMetadataWithFlatFieldMaps)) { return { status: 'fail', error: { @@ -60,6 +61,11 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({ }; } + const parentFlatObjectMetadata = + fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata( + parentFlatObjectMetadataWithFlatFieldMaps, + ); + const fieldMetadataId = v4(); const commonFlatFieldMetadata = getDefaultFlatFieldMetadata({ createFieldInput, @@ -69,15 +75,24 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({ switch (createFieldInput.type) { case FieldMetadataType.MORPH_RELATION: { - throw new UserInputError( - 'Morph relation feature is not migrated to workspace migration v2 yet', - ); + return await fromMorphRelationCreateFieldInputToFlatFieldMetadatas({ + createFieldInput: { + ...createFieldInput, + type: createFieldInput.type, + }, + existingFlatObjectMetadataMaps, + sourceFlatObjectMetadata: parentFlatObjectMetadata, + workspaceId, + }); } case FieldMetadataType.RELATION: { - return await fromRelationCreateFieldInputToFlatFieldMetadata({ + return await fromRelationCreateFieldInputToFlatFieldMetadatas({ existingFlatObjectMetadataMaps, - sourceParentFlatObjectMetadata: parentFlatObjectMetadata, - createFieldInput, + sourceFlatObjectMetadata: parentFlatObjectMetadata, + createFieldInput: { + ...createFieldInput, + type: createFieldInput.type, + }, workspaceId, }); } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-morph-relation-create-field-input-to-flat-field-metadatas.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-morph-relation-create-field-input-to-flat-field-metadatas.util.ts new file mode 100644 index 0000000000..a0b4688206 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-morph-relation-create-field-input-to-flat-field-metadatas.util.ts @@ -0,0 +1,91 @@ +import { t } from '@lingui/core/macro'; +import { type FieldMetadataType } from 'twenty-shared/types'; +import { + computeMorphRelationFieldJoinColumnName, + isDefined, +} from 'twenty-shared/utils'; + +import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; +import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; +import { type FieldInputTranspilationResult } from 'src/engine/metadata-modules/flat-field-metadata/types/field-input-transpilation-result.type'; +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { generateRelationOrMorphRelationFlatFieldMetadataPair } from 'src/engine/metadata-modules/flat-field-metadata/utils/generate-relation-or-morph-relation-flat-field-metadata-pair.util'; +import { validateMorphRelationCreationPayload } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-relation-creation-payload.util'; +import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; + +type FromMorphRelationCreateFieldInputToFlatFieldMetadatasArgs = { + createFieldInput: Omit & { + type: FieldMetadataType.MORPH_RELATION; + }; + existingFlatObjectMetadataMaps: FlatObjectMetadataMaps; + sourceFlatObjectMetadata: FlatObjectMetadata; + workspaceId: string; +}; +export const fromMorphRelationCreateFieldInputToFlatFieldMetadatas = async ({ + createFieldInput, + existingFlatObjectMetadataMaps, + sourceFlatObjectMetadata, + workspaceId, +}: FromMorphRelationCreateFieldInputToFlatFieldMetadatasArgs): Promise< + FieldInputTranspilationResult +> => { + const rawMorphCreationPayload = + createFieldInput.morphRelationsCreationPayload; + + if ( + !isDefined(rawMorphCreationPayload) || + !Array.isArray(rawMorphCreationPayload) || + rawMorphCreationPayload.length === 0 + ) { + return { + status: 'fail', + error: { + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: `Relation creation payload is required`, + userFriendlyMessage: t`Relation creation payload is required`, + value: rawMorphCreationPayload, + }, + }; + } + + const morphRelationCreationPayloadValidation = + await validateMorphRelationCreationPayload({ + existingFlatObjectMetadataMaps, + morphRelationCreationPayload: rawMorphCreationPayload, + }); + + if (morphRelationCreationPayloadValidation.status === 'fail') { + return morphRelationCreationPayloadValidation; + } + + const morphRelationCreationPayload = + morphRelationCreationPayloadValidation.result; + + const flatFieldMetadatas = morphRelationCreationPayload.flatMap( + ({ relationCreationPayload, targetFlatObjectMetadata }) => { + const sourceFlatObjectMetadataJoinColumnName = + computeMorphRelationFieldJoinColumnName({ + name: createFieldInput.name, + targetObjectMetadataNameSingular: + targetFlatObjectMetadata.nameSingular, + }); + + return generateRelationOrMorphRelationFlatFieldMetadataPair({ + createFieldInput: { + ...createFieldInput, + relationCreationPayload, + }, + sourceFlatObjectMetadataJoinColumnName, + sourceFlatObjectMetadata, + targetFlatObjectMetadata, + workspaceId, + }); + }, + ); + + return { + status: 'success', + result: flatFieldMetadatas, + }; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-relation-create-field-input-to-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-relation-create-field-input-to-flat-field-metadata.util.ts deleted file mode 100644 index c3a8a6f9c1..0000000000 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-relation-create-field-input-to-flat-field-metadata.util.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { t } from '@lingui/core/macro'; -import { FieldMetadataType } from 'twenty-shared/types'; -import { - isDefined, - trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties, -} from 'twenty-shared/utils'; -import { v4 } from 'uuid'; - -import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; - -import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; -import { - FieldMetadataException, - FieldMetadataExceptionCode, -} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; -import { validateRelationCreationPayloadOrThrow } from 'src/engine/metadata-modules/field-metadata/utils/validate-relation-creation-payload-or-throw.util'; -import { type FieldInputTranspilationResult } from 'src/engine/metadata-modules/flat-field-metadata/types/field-input-transpilation-result.type'; -import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { getDefaultFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/get-default-flat-field-metadata-from-create-field-input.util'; -import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; -import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; -import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type'; -import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util'; - -type ComputeFieldMetadataRelationSettingsForRelationTypeArgs = { - relationType: RelationType; - fieldMetadataName: string; -}; -const computeFieldMetadataRelationSettingsForRelationType = ({ - fieldMetadataName, - relationType, -}: ComputeFieldMetadataRelationSettingsForRelationTypeArgs) => { - if (relationType === RelationType.MANY_TO_ONE) { - return { - relationType: RelationType.MANY_TO_ONE, - onDelete: RelationOnDeleteAction.SET_NULL, - joinColumnName: `${fieldMetadataName}Id`, - }; - } - - return { - relationType: RelationType.ONE_TO_MANY, - }; -}; - -type FromRelationCreateFieldInputToFlatFieldMetadataArgs = { - createFieldInput: Omit; - existingFlatObjectMetadataMaps: FlatObjectMetadataMaps; - sourceParentFlatObjectMetadata: FlatObjectMetadata; - workspaceId: string; -}; -export const fromRelationCreateFieldInputToFlatFieldMetadata = async ({ - existingFlatObjectMetadataMaps, - sourceParentFlatObjectMetadata, - createFieldInput, - workspaceId, -}: FromRelationCreateFieldInputToFlatFieldMetadataArgs): Promise< - FieldInputTranspilationResult -> => { - const rawCreationPayload = createFieldInput.relationCreationPayload; - - if (!isDefined(rawCreationPayload)) { - return { - status: 'fail', - error: { - code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, - message: `Relation creation payload is required`, - userFriendlyMessage: t`Relation creation payload is required`, - value: rawCreationPayload, - }, - }; - } - - const relationCreationPayload = - trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties( - rawCreationPayload, - ['targetFieldIcon', 'targetFieldLabel', 'targetObjectMetadataId', 'type'], - ); - - try { - await validateRelationCreationPayloadOrThrow(relationCreationPayload); - } catch (error) { - if (error instanceof FieldMetadataException) { - return { - status: 'fail', - error: { - code: FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED, - message: `Relation creation payload is invalid ${JSON.stringify(relationCreationPayload)}`, - userFriendlyMessage: t`Invalid relation creation payload`, - value: relationCreationPayload, - }, - }; - } else { - throw error; - } - } - - const targetParentFlatObjectMetadata = - existingFlatObjectMetadataMaps.byId[ - relationCreationPayload.targetObjectMetadataId - ]; - - if (!isDefined(targetParentFlatObjectMetadata)) { - return { - status: 'fail', - error: { - code: FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED, - message: `Object metadata relation target not found for relation creation payload`, - userFriendlyMessage: t`Object targeted by field to create not found`, - value: relationCreationPayload, - }, - }; - } - - const sourceFlatFieldMetadataSettings = - computeFieldMetadataRelationSettingsForRelationType({ - fieldMetadataName: createFieldInput.name, - relationType: relationCreationPayload.type, - }); - const targetRelationTargetFieldMetadataId = v4(); - const sourceRelationTargetFieldMetadataId = v4(); - const sourceFlatFieldMetadata: Omit< - FlatFieldMetadata, - 'flatRelationTargetFieldMetadata' - > = { - ...getDefaultFlatFieldMetadata({ - createFieldInput, - workspaceId, - fieldMetadataId: sourceRelationTargetFieldMetadataId, - }), - icon: createFieldInput.icon ?? 'IconRelationOneToMany', - type: FieldMetadataType.RELATION, - defaultValue: null, - settings: sourceFlatFieldMetadataSettings, - options: null, - relationTargetFieldMetadataId: targetRelationTargetFieldMetadataId, // Note: this won't work until we enable deferred transaction - relationTargetObjectMetadataId: targetParentFlatObjectMetadata.id, - flatRelationTargetObjectMetadata: targetParentFlatObjectMetadata, - }; - - const targetCreateFieldInput: CreateFieldInput = { - icon: relationCreationPayload.targetFieldIcon ?? 'Icon123', - label: relationCreationPayload.targetFieldLabel, - name: computeMetadataNameFromLabel( - relationCreationPayload.targetFieldLabel, - ), - objectMetadataId: targetParentFlatObjectMetadata.id, - type: FieldMetadataType.RELATION, - workspaceId, - }; - const targetFlatFieldMetadataSettings = - computeFieldMetadataRelationSettingsForRelationType({ - fieldMetadataName: targetCreateFieldInput.name, - relationType: - relationCreationPayload.type === RelationType.ONE_TO_MANY - ? RelationType.MANY_TO_ONE - : RelationType.ONE_TO_MANY, - }); - const targetFlatFieldMetadata: FlatFieldMetadata = - { - ...getDefaultFlatFieldMetadata({ - createFieldInput: targetCreateFieldInput, - workspaceId, - fieldMetadataId: targetRelationTargetFieldMetadataId, - }), - type: FieldMetadataType.RELATION, - defaultValue: null, - settings: targetFlatFieldMetadataSettings, - options: null, - relationTargetFieldMetadataId: sourceRelationTargetFieldMetadataId, - relationTargetObjectMetadataId: sourceParentFlatObjectMetadata.id, - flatRelationTargetFieldMetadata: sourceFlatFieldMetadata, - flatRelationTargetObjectMetadata: sourceParentFlatObjectMetadata, - }; - - return { - status: 'success', - result: [ - { - ...sourceFlatFieldMetadata, - flatRelationTargetFieldMetadata: targetFlatFieldMetadata, - }, - targetFlatFieldMetadata, - ] satisfies FlatFieldMetadata[], - }; -}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-relation-create-field-input-to-flat-field-metadatas.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-relation-create-field-input-to-flat-field-metadatas.util.ts new file mode 100644 index 0000000000..d370766099 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-relation-create-field-input-to-flat-field-metadatas.util.ts @@ -0,0 +1,76 @@ +import { t } from '@lingui/core/macro'; +import { type FieldMetadataType } from 'twenty-shared/types'; +import { isDefined } from 'twenty-shared/utils'; + +import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; +import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; +import { type RelationFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/types/relation-field-metadata-type.type'; +import { computeRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-relation-field-join-column-name.util'; +import { type FieldInputTranspilationResult } from 'src/engine/metadata-modules/flat-field-metadata/types/field-input-transpilation-result.type'; +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { generateRelationOrMorphRelationFlatFieldMetadataPair } from 'src/engine/metadata-modules/flat-field-metadata/utils/generate-relation-or-morph-relation-flat-field-metadata-pair.util'; +import { validateRelationCreationPayload } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-creation-payload.util'; +import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; + +type FromRelationCreateFieldInputToFlatFieldMetadataArgs = { + createFieldInput: Omit & { + type: FieldMetadataType.RELATION; + }; + existingFlatObjectMetadataMaps: FlatObjectMetadataMaps; + sourceFlatObjectMetadata: FlatObjectMetadata; + workspaceId: string; +}; +export const fromRelationCreateFieldInputToFlatFieldMetadatas = async ({ + existingFlatObjectMetadataMaps, + sourceFlatObjectMetadata, + createFieldInput, + workspaceId, +}: FromRelationCreateFieldInputToFlatFieldMetadataArgs): Promise< + FieldInputTranspilationResult[]> +> => { + const rawCreationPayload = createFieldInput.relationCreationPayload; + + if (!isDefined(rawCreationPayload)) { + return { + status: 'fail', + error: { + code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT, + message: `Relation creation payload is required`, + userFriendlyMessage: t`Relation creation payload is required`, + value: rawCreationPayload, + }, + }; + } + + const relationValidationResult = await validateRelationCreationPayload({ + existingFlatObjectMetadataMaps, + relationCreationPayload: rawCreationPayload, + }); + + if (relationValidationResult.status === 'fail') { + return relationValidationResult; + } + const { relationCreationPayload, targetFlatObjectMetadata } = + relationValidationResult.result; + + const flatFieldMetadatas = + generateRelationOrMorphRelationFlatFieldMetadataPair({ + createFieldInput: { + ...createFieldInput, + relationCreationPayload, + }, + sourceFlatObjectMetadataJoinColumnName: + computeRelationFieldJoinColumnName({ + name: createFieldInput.name, + }), + sourceFlatObjectMetadata, + targetFlatObjectMetadata, + workspaceId, + }); + + return { + status: 'success', + result: flatFieldMetadatas, + }; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/generate-relation-or-morph-relation-flat-field-metadata-pair.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/generate-relation-or-morph-relation-flat-field-metadata-pair.util.ts new file mode 100644 index 0000000000..d91ffe3aab --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/generate-relation-or-morph-relation-flat-field-metadata-pair.util.ts @@ -0,0 +1,124 @@ +import { FieldMetadataType, RelationType } from 'twenty-shared/types'; +import { v4 } from 'uuid'; + +import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; +import { type RelationFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/types/relation-field-metadata-type.type'; +import { computeRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-relation-field-join-column-name.util'; +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { getDefaultFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/get-default-flat-field-metadata-from-create-field-input.util'; +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type'; +import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util'; + +type ComputeFieldMetadataRelationSettingsForRelationTypeArgs = { + relationType: RelationType; + joinColumnName: string; +}; +const computeFieldMetadataRelationSettingsForRelationType = ({ + relationType, + joinColumnName, +}: ComputeFieldMetadataRelationSettingsForRelationTypeArgs) => { + if (relationType === RelationType.MANY_TO_ONE) { + return { + relationType: RelationType.MANY_TO_ONE, + onDelete: RelationOnDeleteAction.SET_NULL, + joinColumnName, + }; + } + + return { + relationType: RelationType.ONE_TO_MANY, + }; +}; + +type GenerateRelationOrMorphRelationFlatFieldMetadataPairArgs = { + targetFlatObjectMetadata: FlatObjectMetadata; + sourceFlatObjectMetadata: FlatObjectMetadata; + sourceFlatObjectMetadataJoinColumnName: string; + createFieldInput: Omit & + Required< + Pick + > & { type: RelationFieldMetadataType }; + workspaceId: string; +}; +export const generateRelationOrMorphRelationFlatFieldMetadataPair = ({ + createFieldInput, + sourceFlatObjectMetadata, + targetFlatObjectMetadata, + workspaceId, + sourceFlatObjectMetadataJoinColumnName, +}: GenerateRelationOrMorphRelationFlatFieldMetadataPairArgs): FlatFieldMetadata[] => { + const { relationCreationPayload } = createFieldInput; + + const sourceFlatFieldMetadataSettings = + computeFieldMetadataRelationSettingsForRelationType({ + joinColumnName: sourceFlatObjectMetadataJoinColumnName, + relationType: relationCreationPayload.type, + }); + const targetRelationTargetFieldMetadataId = v4(); + const sourceRelationTargetFieldMetadataId = v4(); + const sourceFlatFieldMetadata: Omit< + FlatFieldMetadata, + 'flatRelationTargetFieldMetadata' + > = { + ...getDefaultFlatFieldMetadata({ + createFieldInput, + workspaceId, + fieldMetadataId: sourceRelationTargetFieldMetadataId, + }), + objectMetadataId: sourceFlatObjectMetadata.id, + icon: createFieldInput.icon ?? 'IconRelationOneToMany', + type: createFieldInput.type, + defaultValue: null, + settings: sourceFlatFieldMetadataSettings, + options: null, + relationTargetFieldMetadataId: targetRelationTargetFieldMetadataId, + relationTargetObjectMetadataId: targetFlatObjectMetadata.id, + flatRelationTargetObjectMetadata: targetFlatObjectMetadata, + }; + + const targetCreateFieldInput: CreateFieldInput = { + icon: relationCreationPayload.targetFieldIcon ?? 'Icon123', + label: relationCreationPayload.targetFieldLabel, + name: computeMetadataNameFromLabel( + relationCreationPayload.targetFieldLabel, + ), + objectMetadataId: targetFlatObjectMetadata.id, + type: FieldMetadataType.RELATION, + workspaceId, + }; + const targetFlatFieldMetadataSettings = + computeFieldMetadataRelationSettingsForRelationType({ + joinColumnName: computeRelationFieldJoinColumnName({ + name: targetCreateFieldInput.name, + }), + relationType: + relationCreationPayload.type === RelationType.ONE_TO_MANY + ? RelationType.MANY_TO_ONE + : RelationType.ONE_TO_MANY, + }); + const targetFlatFieldMetadata: FlatFieldMetadata = + { + ...getDefaultFlatFieldMetadata({ + createFieldInput: targetCreateFieldInput, + workspaceId, + fieldMetadataId: targetRelationTargetFieldMetadataId, + }), + type: FieldMetadataType.RELATION, + defaultValue: null, + settings: targetFlatFieldMetadataSettings, + options: null, + relationTargetFieldMetadataId: sourceRelationTargetFieldMetadataId, + relationTargetObjectMetadataId: sourceFlatObjectMetadata.id, + flatRelationTargetFieldMetadata: sourceFlatFieldMetadata, + flatRelationTargetObjectMetadata: sourceFlatObjectMetadata, + }; + + return [ + { + ...sourceFlatFieldMetadata, + flatRelationTargetFieldMetadata: targetFlatFieldMetadata, + }, + targetFlatFieldMetadata, + ] satisfies FlatFieldMetadata[]; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-relation-creation-payload.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-relation-creation-payload.util.ts new file mode 100644 index 0000000000..f3e788a602 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-relation-creation-payload.util.ts @@ -0,0 +1,122 @@ +import { type RelationCreationPayload } from 'twenty-shared/types'; +import { t } from '@lingui/core/macro'; +import { isDefined } from 'class-validator'; + +import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; +import { + type FailedFieldInputTranspilation, + type SuccessfulFieldInputTranspilation, + type FieldInputTranspilationResult, +} from 'src/engine/metadata-modules/flat-field-metadata/types/field-input-transpilation-result.type'; +import { validateRelationCreationPayload } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-creation-payload.util'; +import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; + +type RelationCreationPayloadAndObjectMetadata = { + relationCreationPayload: RelationCreationPayload; + targetFlatObjectMetadata: FlatObjectMetadata; +}; + +type ValidateMorphRelationCreationPayloadUtilArgs = { + morphRelationCreationPayload: RelationCreationPayload[]; + existingFlatObjectMetadataMaps: FlatObjectMetadataMaps; +}; +export const validateMorphRelationCreationPayload = async ({ + existingFlatObjectMetadataMaps, + morphRelationCreationPayload, +}: ValidateMorphRelationCreationPayloadUtilArgs): Promise< + FieldInputTranspilationResult +> => { + const allRelationType = [ + ...new Set( + morphRelationCreationPayload.map( + (relationCreationPayload) => relationCreationPayload.type, + ), + ), + ]; + + if (allRelationType.length > 1) { + return { + status: 'fail', + error: { + code: FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED, + message: 'Morph relation relations must have the same relation type', + userFriendlyMessage: t`Morph relation relations must have the same relation type`, + }, + }; + } + + const allRelatedObjectMetadataIds = morphRelationCreationPayload.map( + (relationCreationPayload) => relationCreationPayload.targetObjectMetadataId, + ); + const allRelatedObjectMetadataIdsSet = [ + ...new Set(allRelatedObjectMetadataIds), + ]; + + if ( + allRelatedObjectMetadataIds.length !== allRelatedObjectMetadataIdsSet.length + ) { + return { + status: 'fail', + error: { + code: FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED, + message: + 'Morph relation relations must have only relation to the same object metadata', + userFriendlyMessage: t`Morph relation relations must have only relation to the same object metadata`, + }, + }; + } + + const relationCreationPayloadReport: { + success: SuccessfulFieldInputTranspilation[]; + failed: FailedFieldInputTranspilation[]; + } = { + success: [], + failed: [], + }; + + for (const rawRelationCreationPayload of morphRelationCreationPayload) { + const relationValidationResult = await validateRelationCreationPayload({ + existingFlatObjectMetadataMaps, + relationCreationPayload: rawRelationCreationPayload, + }); + + if (relationValidationResult.status === 'fail') { + relationCreationPayloadReport.failed.push(relationValidationResult); + continue; + } + + const { relationCreationPayload, targetFlatObjectMetadata } = + relationValidationResult.result; + + relationCreationPayloadReport.success.push({ + status: 'success', + result: { + relationCreationPayload, + targetFlatObjectMetadata, + }, + }); + } + + if (relationCreationPayloadReport.failed.length > 0) { + return { + status: 'fail', + error: { + code: FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED, + message: 'Morph relation input transpilation failed', + userFriendlyMessage: t`Invalid morph relation input`, + value: relationCreationPayloadReport.failed + .map((failedTranspilation) => failedTranspilation.error.value) + .filter(isDefined), + }, + }; + } + + return { + status: 'success', + result: relationCreationPayloadReport.success.map( + (relationCreationPayloadValidation) => + relationCreationPayloadValidation.result, + ), + }; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-creation-payload.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-creation-payload.util.ts new file mode 100644 index 0000000000..83dbd5a007 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-creation-payload.util.ts @@ -0,0 +1,82 @@ +import { t } from '@lingui/core/macro'; +import { type RelationCreationPayload } from 'twenty-shared/types'; +import { + isDefined, + trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties, +} from 'twenty-shared/utils'; + +import { + FieldMetadataException, + FieldMetadataExceptionCode, +} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; +import { validateRelationCreationPayloadOrThrow } from 'src/engine/metadata-modules/field-metadata/utils/validate-relation-creation-payload-or-throw.util'; +import { type FieldInputTranspilationResult } from 'src/engine/metadata-modules/flat-field-metadata/types/field-input-transpilation-result.type'; +import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; +import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-with-flat-field-maps-to-flat-object-metadatas.util'; + +type ValidateRelationCreationPayloadUtilArgs = { + relationCreationPayload: RelationCreationPayload; + existingFlatObjectMetadataMaps: FlatObjectMetadataMaps; +}; +export const validateRelationCreationPayload = async ({ + existingFlatObjectMetadataMaps, + relationCreationPayload: rawRelationCreationPayload, +}: ValidateRelationCreationPayloadUtilArgs): Promise< + FieldInputTranspilationResult<{ + relationCreationPayload: RelationCreationPayload; + targetFlatObjectMetadata: FlatObjectMetadata; + }> +> => { + const relationCreationPayload = + trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties( + rawRelationCreationPayload, + ['targetFieldIcon', 'targetFieldLabel', 'targetObjectMetadataId', 'type'], + ); + + try { + await validateRelationCreationPayloadOrThrow(relationCreationPayload); + } catch (error) { + if (error instanceof FieldMetadataException) { + return { + status: 'fail', + error: { + code: FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED, + message: `Relation creation payload is invalid ${JSON.stringify(relationCreationPayload)}`, + userFriendlyMessage: t`Invalid relation creation payload`, + value: relationCreationPayload, + }, + }; + } else { + throw error; + } + } + + const targetFlatObjectMetadataWithFlatFieldMaps = + existingFlatObjectMetadataMaps.byId[ + relationCreationPayload.targetObjectMetadataId + ]; + + if (!isDefined(targetFlatObjectMetadataWithFlatFieldMaps)) { + return { + status: 'fail', + error: { + code: FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED, + message: `Object metadata relation target not found for relation creation payload`, + userFriendlyMessage: t`Object targeted by field to create not found`, + value: relationCreationPayload, + }, + }; + } + + return { + status: 'success', + result: { + relationCreationPayload, + targetFlatObjectMetadata: + fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata( + targetFlatObjectMetadataWithFlatFieldMaps, + ), + }, + }; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-field-relation.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-field-relation.service.ts index 72b946594a..6dda6b4f0e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-field-relation.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-field-relation.service.ts @@ -2,14 +2,17 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { FieldMetadataType } from 'twenty-shared/types'; -import { capitalize, isDefined } from 'twenty-shared/utils'; +import { + capitalize, + computeMorphRelationFieldJoinColumnName, + isDefined, +} from 'twenty-shared/utils'; import { type QueryRunner, Repository } from 'typeorm'; import { v4 as uuidV4 } from 'uuid'; import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { computeMorphRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-relation-field-join-column-name.util'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataException, 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 1adb4e87e9..b904348e81 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 @@ -40,7 +40,7 @@ exports[`Workspace migration builder field actions test suite It should build an "standardId": null, "standardOverrides": null, "type": "TEXT", - "uniqueIdentifier": "field-metadata-unique-identifier-1", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -79,7 +79,7 @@ exports[`Workspace migration builder field actions test suite It should build an "standardId": null, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "field-metadata-unique-identifier-2", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -107,7 +107,7 @@ exports[`Workspace migration builder field actions test suite It should build an "standardId": null, "standardOverrides": null, "targetTableName": "DEPRECATED", - "uniqueIdentifier": "d78ec657-74a4-4652-a350-1f44ff62970a", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -130,7 +130,7 @@ exports[`Workspace migration builder field actions test suite It should build an "standardId": null, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "field-metadata-unique-identifier-1", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -168,7 +168,7 @@ exports[`Workspace migration builder field actions test suite It should build an "standardId": null, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "field-metadata-unique-identifier-2", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -196,7 +196,7 @@ exports[`Workspace migration builder field actions test suite It should build an "standardId": null, "standardOverrides": null, "targetTableName": "DEPRECATED", - "uniqueIdentifier": "d78ec657-74a4-4652-a350-1f44ff62970a", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -219,7 +219,7 @@ exports[`Workspace migration builder field actions test suite It should build an "standardId": null, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "field-metadata-unique-identifier-1", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -247,7 +247,7 @@ exports[`Workspace migration builder field actions test suite It should build an "standardId": null, "standardOverrides": null, "targetTableName": "DEPRECATED", - "uniqueIdentifier": "d34e0f07-1b8c-4de0-938e-599cf05e1f7f", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -270,7 +270,7 @@ exports[`Workspace migration builder field actions test suite It should build an "standardId": null, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "field-metadata-unique-identifier-2", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -370,7 +370,7 @@ exports[`Workspace migration builder index actions test suite It should build an "isUnique": false, "name": "defaultFlatIndexMetadataName", "objectMetadataId": Any, - "uniqueIdentifier": "field-metadata-unique-identifier-1", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -396,7 +396,7 @@ exports[`Workspace migration builder index actions test suite It should build an "isUnique": false, "name": "new index name", "objectMetadataId": Any, - "uniqueIdentifier": "field-metadata-unique-identifier-1", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -437,7 +437,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "UUID", - "uniqueIdentifier": "20202020-eda0-4cee-9577-3eb357e3c22b", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -469,7 +469,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "TEXT", - "uniqueIdentifier": "20202020-ba07-4ffd-ba63-009491f5749c", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -501,7 +501,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "DATE_TIME", - "uniqueIdentifier": "20202020-66ac-4502-9975-e4d959c50311", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -533,7 +533,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "DATE_TIME", - "uniqueIdentifier": "20202020-d767-4622-bdcf-d8a084834d86", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -565,7 +565,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "DATE_TIME", - "uniqueIdentifier": "20202020-b9a7-48d8-8387-b9a3090a50ec", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -600,7 +600,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "ACTOR", - "uniqueIdentifier": "20202020-be0e-4971-865b-32ca87cbb315", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -632,7 +632,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "POSITION", - "uniqueIdentifier": "20202020-c2bd-4e16-bb9a-c8b0411bf49d", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -672,7 +672,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-0be6-444e-88f0-12e0c64ac27d", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -698,7 +698,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-f1ef-4ba4-8f33-1a4577afa477", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -738,7 +738,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-78f7-4d7d-86e9-7562ced0b381", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -764,7 +764,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-a4a7-4686-b296-1c6c3482ee21", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -804,7 +804,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-ca2d-47c0-8253-9d0b662fb01a", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -830,7 +830,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-8d59-46ca-b7b2-73d167712134", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -870,7 +870,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-52b6-4d5e-8f21-ed8b7c09c4a9", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -896,7 +896,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-01fd-4f37-99dc-9427a444018a", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -936,7 +936,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-b98f-473d-85fb-8cebc40b9a50", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -962,7 +962,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-0860-4566-b865-bff3c626c303", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -994,7 +994,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "TS_VECTOR", - "uniqueIdentifier": "70e56537-18ef-4811-b1c7-0a444006b815", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1025,7 +1025,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "targetTableName": "DEPRECATED", - "uniqueIdentifier": "d78ec657-74a4-4652-a350-1f44ff62970a", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1151,7 +1151,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-c54e-4804-8b0d-8795e5166432", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1177,7 +1177,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-01fd-4f37-99dc-9427a444018a", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1209,7 +1209,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "UUID", - "uniqueIdentifier": "20202020-eda0-4cee-9577-3eb357e3c22b", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1241,7 +1241,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "TEXT", - "uniqueIdentifier": "20202020-ba07-4ffd-ba63-009491f5749c", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1273,7 +1273,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "DATE_TIME", - "uniqueIdentifier": "20202020-66ac-4502-9975-e4d959c50311", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1305,7 +1305,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "DATE_TIME", - "uniqueIdentifier": "20202020-d767-4622-bdcf-d8a084834d86", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1337,7 +1337,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "DATE_TIME", - "uniqueIdentifier": "20202020-b9a7-48d8-8387-b9a3090a50ec", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1372,7 +1372,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "ACTOR", - "uniqueIdentifier": "20202020-be0e-4971-865b-32ca87cbb315", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1404,7 +1404,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "POSITION", - "uniqueIdentifier": "20202020-c2bd-4e16-bb9a-c8b0411bf49d", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1444,7 +1444,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-d88f-4020-8c85-d6c600903762", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1470,7 +1470,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-f1ef-4ba4-8f33-1a4577afa477", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1510,7 +1510,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-1bd7-4d10-80dc-968b9f5d1a8a", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1536,7 +1536,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-a4a7-4686-b296-1c6c3482ee21", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1576,7 +1576,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-b715-4658-8b6a-5359824dbddd", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1602,7 +1602,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-8d59-46ca-b7b2-73d167712134", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1642,7 +1642,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-07d9-4d04-8b73-a39ab65943f1", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1668,7 +1668,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-0860-4566-b865-bff3c626c303", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1700,7 +1700,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "TS_VECTOR", - "uniqueIdentifier": "70e56537-18ef-4811-b1c7-0a444006b815", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1775,7 +1775,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "SELECT", - "uniqueIdentifier": "0292cc51-246f-40b8-99e8-3345dac0e688", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1850,7 +1850,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "MULTI_SELECT", - "uniqueIdentifier": "5aaf6be0-b9f5-4222-9810-941d5ab58527", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1882,7 +1882,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "TEXT", - "uniqueIdentifier": "2e726631-d80a-4594-9a5a-3cca0c2a50a9", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1914,7 +1914,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "NUMBER", - "uniqueIdentifier": "ed1573cf-b29e-4d4f-a8e3-19d472d28c0d", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1955,7 +1955,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "ADDRESS", - "uniqueIdentifier": "7b05e127-d0ea-422a-8f98-ef48f41d4388", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -1992,7 +1992,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "PHONES", - "uniqueIdentifier": "92c856ef-5b4b-4202-8c23-b2f22f959eda", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2027,7 +2027,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "EMAILS", - "uniqueIdentifier": "2c89697d-925a-485c-a0ed-adf2f1228e0f", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2059,7 +2059,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "DATE", - "uniqueIdentifier": "13c5b4ed-5746-494f-856b-081bdbb4a8ec", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2091,7 +2091,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "BOOLEAN", - "uniqueIdentifier": "ec3bf27e-70e6-4d4a-932e-6ef026013603", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2127,7 +2127,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "LINKS", - "uniqueIdentifier": "8aa0a700-c308-4d8b-8fbd-f545daa8980a", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2162,7 +2162,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "CURRENCY", - "uniqueIdentifier": "37421848-b64d-4827-be33-da4e337acbb6", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2197,7 +2197,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "FULL_NAME", - "uniqueIdentifier": "84b874dc-983d-47eb-9c67-54f557a99f60", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2260,7 +2260,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "RATING", - "uniqueIdentifier": "42e6c0d2-6d00-4c77-b179-890af8c56236", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2292,7 +2292,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "RICH_TEXT", - "uniqueIdentifier": "fa0ec409-0f29-4b19-b304-31d1018a2344", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2324,7 +2324,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "ARRAY", - "uniqueIdentifier": "2b806a74-e7a5-4ec7-b902-67cf811e8bda", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2356,7 +2356,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "type": "RAW_JSON", - "uniqueIdentifier": "a79bd7c8-c7ce-416a-9d12-a05335c9c596", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2387,7 +2387,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "targetTableName": "DEPRECATED", - "uniqueIdentifier": "d34e0f07-1b8c-4de0-938e-599cf05e1f7f", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2601,7 +2601,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "UUID", - "uniqueIdentifier": "20202020-eda0-4cee-9577-3eb357e3c22b", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2633,7 +2633,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "TEXT", - "uniqueIdentifier": "20202020-ba07-4ffd-ba63-009491f5749c", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2665,7 +2665,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "DATE_TIME", - "uniqueIdentifier": "20202020-66ac-4502-9975-e4d959c50311", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2697,7 +2697,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "DATE_TIME", - "uniqueIdentifier": "20202020-d767-4622-bdcf-d8a084834d86", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2729,7 +2729,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "DATE_TIME", - "uniqueIdentifier": "20202020-b9a7-48d8-8387-b9a3090a50ec", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2764,7 +2764,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "ACTOR", - "uniqueIdentifier": "20202020-be0e-4971-865b-32ca87cbb315", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2796,7 +2796,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "POSITION", - "uniqueIdentifier": "20202020-c2bd-4e16-bb9a-c8b0411bf49d", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2836,7 +2836,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-0be6-444e-88f0-12e0c64ac27d", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2862,7 +2862,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-f1ef-4ba4-8f33-1a4577afa477", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2902,7 +2902,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-78f7-4d7d-86e9-7562ced0b381", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2928,7 +2928,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-a4a7-4686-b296-1c6c3482ee21", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2968,7 +2968,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-ca2d-47c0-8253-9d0b662fb01a", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -2994,7 +2994,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-8d59-46ca-b7b2-73d167712134", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -3034,7 +3034,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-52b6-4d5e-8f21-ed8b7c09c4a9", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -3060,7 +3060,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-01fd-4f37-99dc-9427a444018a", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -3100,7 +3100,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-b98f-473d-85fb-8cebc40b9a50", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -3126,7 +3126,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "RELATION", - "uniqueIdentifier": "20202020-0860-4566-b865-bff3c626c303", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -3158,7 +3158,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": Any, "standardOverrides": null, "type": "TS_VECTOR", - "uniqueIdentifier": "70e56537-18ef-4811-b1c7-0a444006b815", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -3189,7 +3189,7 @@ exports[`Workspace migration builder object actions test suite It should build a "standardId": null, "standardOverrides": null, "targetTableName": "DEPRECATED", - "uniqueIdentifier": "d78ec657-74a4-4652-a350-1f44ff62970a", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, @@ -3206,7 +3206,7 @@ exports[`Workspace migration builder object actions test suite It should build a "isUnique": false, "name": "defaultFlatIndexMetadataName", "objectMetadataId": Any, - "uniqueIdentifier": "field-metadata-unique-identifier-1", + "uniqueIdentifier": Any, "updatedAt": Any, "workspaceId": Any, }, diff --git a/packages/twenty-server/test/utils/extract-record-ids-and-dates-as-expect-any.ts b/packages/twenty-server/test/utils/extract-record-ids-and-dates-as-expect-any.ts index 24e31807ce..c236f33713 100644 --- a/packages/twenty-server/test/utils/extract-record-ids-and-dates-as-expect-any.ts +++ b/packages/twenty-server/test/utils/extract-record-ids-and-dates-as-expect-any.ts @@ -27,6 +27,7 @@ export const extractRecordIdsAndDatesAsExpectAny = ( if ( key.endsWith('Id') || + key === 'uniqueIdentifier' || key === 'id' || key === 'updatedAt' || key === 'deletedAt' ||