From aa51ecb9d26781b2d5099932f531b51bbcd95acd Mon Sep 17 00:00:00 2001 From: Weiko Date: Mon, 18 Aug 2025 21:48:39 +0200 Subject: [PATCH] Fix relations creation with metadata v2 (#13967) --- .../composite-field-metadata-type.type.ts | 2 +- .../types/enum-field-metadata-type.type.ts | 2 +- .../relation-field-metadata-type.type.ts | 2 +- ...field-input-to-flat-field-metadata.util.ts | 6 ++-- .../is-composite-flat-field-metadata.util.ts | 2 +- .../utils/is-enum-flat-field-metadata.util.ts | 2 +- ...> is-flat-field-metadata-of-types.util.ts} | 0 .../is-relation-flat-field-metadata.util.ts | 2 +- .../is-relation-field-metadata-type.util.ts | 11 ++++-- .../workspace-schema-migration.exception.ts | 1 + ...pace-schema-field-action-runner.service.ts | 34 +++++++++++++------ 11 files changed, 41 insertions(+), 23 deletions(-) rename packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/{is-falt-field-metadata-of-types.util.ts => is-flat-field-metadata-of-types.util.ts} (100%) diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/composite-field-metadata-type.type.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/composite-field-metadata-type.type.ts index a5b38d32eef..64be06a8948 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/composite-field-metadata-type.type.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/composite-field-metadata-type.type.ts @@ -13,6 +13,6 @@ const compositeFieldTypes = [ export type CompositeFieldMetadataType = (typeof compositeFieldTypes)[number]; -export const COMPOSITE_FIELD_TYPES: CompositeFieldMetadataType[] = [ +export const COMPOSITE_FIELD_TYPES: FieldMetadataType[] = [ ...compositeFieldTypes, ]; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/enum-field-metadata-type.type.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/enum-field-metadata-type.type.ts index a477c7cd65d..3ade9d8b8ce 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/enum-field-metadata-type.type.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/enum-field-metadata-type.type.ts @@ -8,4 +8,4 @@ const enumFieldTypes = [ export type EnumFieldMetadataType = (typeof enumFieldTypes)[number]; -export const ENUM_FIELD_TYPES: EnumFieldMetadataType[] = [...enumFieldTypes]; +export const ENUM_FIELD_TYPES: FieldMetadataType[] = [...enumFieldTypes]; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/relation-field-metadata-type.type.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/relation-field-metadata-type.type.ts index 0e536049a8b..c1de3f9c7a2 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/relation-field-metadata-type.type.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/relation-field-metadata-type.type.ts @@ -7,6 +7,6 @@ const relationFieldTypes = [ export type RelationFieldMetadataType = (typeof relationFieldTypes)[number]; -export const RELATION_FIELD_TYPES: RelationFieldMetadataType[] = [ +export const RELATION_FIELD_TYPES: FieldMetadataType[] = [ ...relationFieldTypes, ]; 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 index 3560a5e0ad3..288590a9927 100644 --- 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 @@ -33,7 +33,7 @@ const computeFieldMetadataRelationSettingsForRelationType = ({ return { relationType: RelationType.MANY_TO_ONE, onDelete: RelationOnDeleteAction.SET_NULL, - joinColumnName: fieldMetadataName, + joinColumnName: `${fieldMetadataName}Id`, }; } @@ -131,9 +131,9 @@ export const fromRelationCreateFieldInputToFlatFieldMetadata = async ({ const targetCreateFieldInput: CreateFieldInput = { icon: relationCreationPayload.targetFieldIcon ?? 'Icon123', label: relationCreationPayload.targetFieldLabel, - name: `${computeMetadataNameFromLabel( + name: computeMetadataNameFromLabel( relationCreationPayload.targetFieldLabel, - )}Id`, + ), objectMetadataId: targetParentFlatObjectMetadata.id, type: FieldMetadataType.RELATION, workspaceId, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-composite-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-composite-flat-field-metadata.util.ts index e4610b742cf..0e81f8a14c8 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-composite-flat-field-metadata.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-composite-flat-field-metadata.util.ts @@ -3,7 +3,7 @@ import { type CompositeFieldMetadataType, } from 'src/engine/metadata-modules/field-metadata/types/composite-field-metadata-type.type'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { isFlatFieldMetadataEntityOfTypes } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-falt-field-metadata-of-types.util'; +import { isFlatFieldMetadataEntityOfTypes } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-types.util'; export const isCompositeFlatFieldMetadata = ( flatFieldMetadata: FlatFieldMetadata, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-enum-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-enum-flat-field-metadata.util.ts index b7025ef4101..f7f488f45e8 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-enum-flat-field-metadata.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-enum-flat-field-metadata.util.ts @@ -3,7 +3,7 @@ import { type EnumFieldMetadataType, } from 'src/engine/metadata-modules/field-metadata/types/enum-field-metadata-type.type'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { isFlatFieldMetadataEntityOfTypes } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-falt-field-metadata-of-types.util'; +import { isFlatFieldMetadataEntityOfTypes } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-types.util'; export const isEnumFlatFieldMetadata = ( flatFieldMetadata: FlatFieldMetadata, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-falt-field-metadata-of-types.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-types.util.ts similarity index 100% rename from packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-falt-field-metadata-of-types.util.ts rename to packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-types.util.ts diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-relation-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-relation-flat-field-metadata.util.ts index 6851052f49f..ef0caf224c7 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-relation-flat-field-metadata.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-relation-flat-field-metadata.util.ts @@ -3,7 +3,7 @@ import { type RelationFieldMetadataType, } from 'src/engine/metadata-modules/field-metadata/types/relation-field-metadata-type.type'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; -import { isFlatFieldMetadataEntityOfTypes } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-falt-field-metadata-of-types.util'; +import { isFlatFieldMetadataEntityOfTypes } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-types.util'; export const isRelationFlatFieldMetadata = ( flatFieldMetadata: FlatFieldMetadata, diff --git a/packages/twenty-server/src/engine/utils/is-relation-field-metadata-type.util.ts b/packages/twenty-server/src/engine/utils/is-relation-field-metadata-type.util.ts index 3a11cc72eb3..831b4ef45e5 100644 --- a/packages/twenty-server/src/engine/utils/is-relation-field-metadata-type.util.ts +++ b/packages/twenty-server/src/engine/utils/is-relation-field-metadata-type.util.ts @@ -1,6 +1,11 @@ -import { FieldMetadataType } from 'twenty-shared/types'; +import { type FieldMetadataType } from 'twenty-shared/types'; + +import { + RELATION_FIELD_TYPES, + type RelationFieldMetadataType, +} from 'src/engine/metadata-modules/field-metadata/types/relation-field-metadata-type.type'; export const isRelationFieldMetadataType = ( type: FieldMetadataType, -): type is FieldMetadataType.RELATION => { - return type === FieldMetadataType.RELATION; +): type is RelationFieldMetadataType => { + return RELATION_FIELD_TYPES.includes(type); }; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-schema-migration-runner/exceptions/workspace-schema-migration.exception.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-schema-migration-runner/exceptions/workspace-schema-migration.exception.ts index 4b950ee9550..e8fdab18baa 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-schema-migration-runner/exceptions/workspace-schema-migration.exception.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-schema-migration-runner/exceptions/workspace-schema-migration.exception.ts @@ -9,4 +9,5 @@ export enum WorkspaceSchemaMigrationExceptionCode { COLUMN_OPERATION_FAILED = 'COLUMN_OPERATION_FAILED', TABLE_OPERATION_FAILED = 'TABLE_OPERATION_FAILED', UNSUPPORTED_COMPOSITE_COLUMN_TYPE = 'UNSUPPORTED_COMPOSITE_COLUMN_TYPE', + NOT_SUPPORTED = 'NOT_SUPPORTED', } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-schema-migration-runner/workspace-schema-field-action-runner.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-schema-migration-runner/workspace-schema-field-action-runner.service.ts index fdf5eb25910..40bb5c0c5e9 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-schema-migration-runner/workspace-schema-field-action-runner.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-schema-migration-runner/workspace-schema-field-action-runner.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; -import { FieldMetadataType, type FromTo } from 'twenty-shared/types'; +import { type FromTo } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; import { type QueryRunner } from 'typeorm'; @@ -18,9 +18,11 @@ import { unserializeDefaultValue } from 'src/engine/metadata-modules/field-metad import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; import { isCompositeFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-composite-flat-field-metadata.util'; import { isEnumFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-enum-flat-field-metadata.util'; +import { isRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-relation-flat-field-metadata.util'; import { findFlatObjectMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/find-flat-object-metadata-in-flat-object-metadata-maps-or-throw.util'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { WorkspaceSchemaManagerService } from 'src/engine/twenty-orm/workspace-schema-manager/workspace-schema-manager.service'; +import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util'; import { type CreateFieldAction, type DeleteFieldAction, @@ -29,6 +31,10 @@ import { } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-field-action-v2'; import { type RunnerMethodForActionType } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/runner-method-for-action-type'; import { type WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type'; +import { + WorkspaceSchemaMigrationException, + WorkspaceSchemaMigrationExceptionCode, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-schema-migration-runner/exceptions/workspace-schema-migration.exception'; import { generateColumnDefinitions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-schema-migration-runner/utils/generate-column-definitions.util'; import { @@ -213,11 +219,11 @@ export class WorkspaceSchemaFieldActionRunnerService const compositeType = getCompositeTypeOrThrow(flatFieldMetadata.type); for (const property of compositeType.properties) { - if ( - property.type === FieldMetadataType.RELATION || - property.type === FieldMetadataType.MORPH_RELATION - ) { - continue; + if (isRelationFieldMetadataType(property.type)) { + throw new WorkspaceSchemaMigrationException( + 'Relation field metadata in composite type is not supported yet', + WorkspaceSchemaMigrationExceptionCode.NOT_SUPPORTED, + ); } const fromCompositeColumnName = computeCompositeColumnName( @@ -238,6 +244,12 @@ export class WorkspaceSchemaFieldActionRunnerService }); } } else { + if (isRelationFlatFieldMetadata(flatFieldMetadata)) { + throw new WorkspaceSchemaMigrationException( + 'Relation field metadata name update is not supported yet', + WorkspaceSchemaMigrationExceptionCode.NOT_SUPPORTED, + ); + } await this.workspaceSchemaManagerService.columnManager.renameColumn({ queryRunner, schemaName, @@ -277,11 +289,11 @@ export class WorkspaceSchemaFieldActionRunnerService const compositeType = getCompositeTypeOrThrow(flatFieldMetadata.type); for (const property of compositeType.properties) { - if ( - property.type === FieldMetadataType.RELATION || - property.type === FieldMetadataType.MORPH_RELATION - ) { - continue; + if (isRelationFieldMetadataType(property.type)) { + throw new WorkspaceSchemaMigrationException( + 'Relation field metadata in composite type is not supported yet', + WorkspaceSchemaMigrationExceptionCode.NOT_SUPPORTED, + ); } const compositeColumnName = computeCompositeColumnName(