From ab3a3ac208db0a50553c0e8ffe5391fb06373469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Magrin?= Date: Wed, 26 Jun 2024 15:27:34 +0200 Subject: [PATCH] feat: better join columns errors --- .../factories/entity-schema-column.factory.ts | 24 ++----- .../entity-schema-relation.factory.ts | 20 ++---- .../twenty-orm/utils/get-join-column.util.ts | 69 +++++++++++++++++++ .../factories/standard-field.factory.ts | 24 ++----- 4 files changed, 89 insertions(+), 48 deletions(-) create mode 100644 packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts index 3e295f7e12c33..83106f92fa684 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts @@ -13,7 +13,7 @@ import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-me import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { getJoinColumn } from 'src/engine/twenty-orm/utils/get-join-column.util'; type EntitySchemaColumnMap = { [key: string]: EntitySchemaColumnOptions; @@ -59,24 +59,14 @@ export class EntitySchemaColumnFactory { }; for (const relationMetadataArgs of relationMetadataArgsCollection) { - const joinColumnMetadataArgs = joinColumnsMetadataArgsCollection.find( - (joinColumnMetadataArgs) => - joinColumnMetadataArgs.relationName === relationMetadataArgs.name, + const joinColumn = getJoinColumn( + joinColumnsMetadataArgsCollection, + relationMetadataArgs, ); - if ( - !joinColumnMetadataArgs && - (relationMetadataArgs.type === RelationMetadataType.ONE_TO_ONE || - relationMetadataArgs.type === RelationMetadataType.MANY_TO_ONE) - ) { - throw new Error( - `Join column not found for relation ${relationMetadataArgs.name}`, - ); - } - - if (joinColumnMetadataArgs) { - entitySchemaColumnMap[joinColumnMetadataArgs.joinColumn] = { - name: joinColumnMetadataArgs.joinColumn, + if (joinColumn) { + entitySchemaColumnMap[joinColumn] = { + name: joinColumn, type: 'uuid', nullable: relationMetadataArgs.isNullable, }; diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts index df7f8de2e2ef8..bc83b460b26a8 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts @@ -8,6 +8,7 @@ import { WorkspaceJoinColumnsMetadataArgs } from 'src/engine/twenty-orm/interfac import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util'; import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { getJoinColumn } from 'src/engine/twenty-orm/utils/get-join-column.util'; type EntitySchemaRelationMap = { [key: string]: EntitySchemaRelationOptions; @@ -29,26 +30,19 @@ export class EntitySchemaRelationFactory { const oppositeObjectName = convertClassNameToObjectMetadataName( oppositeTarget.name, ); - const joinColumnsMetadataArgs = joinColumnsMetadataArgsCollection.find( - (joinColumnsMetadataArgs) => - joinColumnsMetadataArgs.relationName === relationMetadataArgs.name, - ); - const relationType = this.getRelationType(relationMetadataArgs); - - if (!joinColumnsMetadataArgs) { - throw new Error( - `Join columns metadata args are missing for relation ${relationMetadataArgs.name}`, - ); - } + const joinColumn = getJoinColumn( + joinColumnsMetadataArgsCollection, + relationMetadataArgs, + ); entitySchemaRelationMap[relationMetadataArgs.name] = { type: relationType, target: oppositeObjectName, inverseSide: relationMetadataArgs.inverseSideFieldKey ?? objectName, - joinColumn: joinColumnsMetadataArgs.joinColumn + joinColumn: joinColumn ? { - name: joinColumnsMetadataArgs.joinColumn, + name: joinColumn, } : undefined, }; diff --git a/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts b/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts new file mode 100644 index 0000000000000..1f94e232eee13 --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts @@ -0,0 +1,69 @@ +import { WorkspaceJoinColumnsMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-join-columns-metadata-args.interface'; +import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface'; + +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; + +export const getJoinColumn = ( + joinColumnsMetadataArgsCollection: WorkspaceJoinColumnsMetadataArgs[], + relationMetadataArgs: WorkspaceRelationMetadataArgs, +): string | null => { + if ( + relationMetadataArgs.type === RelationMetadataType.ONE_TO_MANY || + relationMetadataArgs.type === RelationMetadataType.MANY_TO_MANY + ) { + return null; + } + + const filteredJoinColumnsMetadataArgsCollection = + joinColumnsMetadataArgsCollection.filter( + (joinColumnsMetadataArgs) => + joinColumnsMetadataArgs.relationName === relationMetadataArgs.name, + ); + + // If we're in a ONE_TO_ONE relation and there are no join columns, we need to find the join column on the inverse side + if ( + relationMetadataArgs.type === RelationMetadataType.ONE_TO_ONE && + filteredJoinColumnsMetadataArgsCollection.length === 0 + ) { + const inverseSideTarget = relationMetadataArgs.inverseSideTarget(); + const inverseSideJoinColumnsMetadataArgsCollection = + metadataArgsStorage.filterJoinColumns(inverseSideTarget); + const inverseSideRelationMetadataArgsCollection = + metadataArgsStorage.filterRelations(inverseSideTarget); + const inverseSideRelationMetadataArgs = + inverseSideRelationMetadataArgsCollection.find( + (inverseSideRelationMetadataArgs) => + inverseSideRelationMetadataArgs.inverseSideFieldKey === + relationMetadataArgs.name, + ); + + if (!inverseSideRelationMetadataArgs) { + throw new Error( + `Inverse side relation metadata args are missing for relation ${relationMetadataArgs.name}`, + ); + } + + return getJoinColumn( + inverseSideJoinColumnsMetadataArgsCollection, + inverseSideRelationMetadataArgs, + ); + } + + // Check if there are multiple join columns for the relation + if (filteredJoinColumnsMetadataArgsCollection.length > 1) { + throw new Error( + `Multiple join columns metadata args found for relation ${relationMetadataArgs.name}`, + ); + } + + const joinColumnsMetadataArgs = filteredJoinColumnsMetadataArgsCollection[0]; + + if (!joinColumnsMetadataArgs) { + throw new Error( + `Join columns metadata args are missing for relation ${relationMetadataArgs.name}`, + ); + } + + return joinColumnsMetadataArgs.joinColumn; +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts index 8b359d1595ae0..8d714e19b2999 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts @@ -16,7 +16,7 @@ import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { createDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util'; -import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { getJoinColumn } from 'src/engine/twenty-orm/utils/get-join-column.util'; @Injectable() export class StandardFieldFactory { @@ -144,10 +144,9 @@ export class StandardFieldFactory { metadataArgsStorage.filterJoinColumns( workspaceRelationMetadataArgs.target, ); - const joinColumnMetadataArgs = joinColumnMetadataArgsCollection.find( - (joinColumnMetadataArgs) => - joinColumnMetadataArgs.relationName === - workspaceRelationMetadataArgs.name, + const joinColumn = getJoinColumn( + joinColumnMetadataArgsCollection, + workspaceRelationMetadataArgs, ); if ( @@ -159,22 +158,11 @@ export class StandardFieldFactory { return []; } - if ( - !joinColumnMetadataArgs && - (workspaceRelationMetadataArgs.type === - RelationMetadataType.MANY_TO_ONE || - workspaceRelationMetadataArgs.type === RelationMetadataType.ONE_TO_ONE) - ) { - throw new Error( - `Join column not found for relation ${workspaceRelationMetadataArgs.name}`, - ); - } - - if (joinColumnMetadataArgs) { + if (joinColumn) { fieldMetadataCollection.push({ type: FieldMetadataType.UUID, standardId: foreignKeyStandardId, - name: joinColumnMetadataArgs.joinColumn, + name: joinColumn, label: `${workspaceRelationMetadataArgs.label} id (foreign key)`, description: `${workspaceRelationMetadataArgs.description} id foreign key`, icon: workspaceRelationMetadataArgs.icon,