From b5114a5fa3e00ea501b6246a99257a4e74baf847 Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Fri, 29 Aug 2025 11:59:32 +0200 Subject: [PATCH] Morph relation v2 delete: retrieve related field metadata to delete (#14142) close https://github.com/twentyhq/core-team-issues/issues/1411 --- .../relation-field-metadata-type.type.ts | 8 +-- ...related-to-morph-relation-or-throw.util.ts | 67 +++++++++++++++++++ ...-to-flat-field-metadatas-to-delete.util.ts | 36 +++++++++- .../is-relation-flat-field-metadata.util.ts | 4 +- .../is-relation-field-metadata-type.util.ts | 2 +- 5 files changed, 106 insertions(+), 11 deletions(-) create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/find-flat-field-metadatas-related-to-morph-relation-or-throw.util.ts 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 c1de3f9c7a..296c45e4bc 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 @@ -1,12 +1,8 @@ import { FieldMetadataType } from 'twenty-shared/types'; -const relationFieldTypes = [ +export const RELATION_FIELD_TYPES = [ FieldMetadataType.RELATION, FieldMetadataType.MORPH_RELATION, ] as const; -export type RelationFieldMetadataType = (typeof relationFieldTypes)[number]; - -export const RELATION_FIELD_TYPES: FieldMetadataType[] = [ - ...relationFieldTypes, -]; +export type RelationFieldMetadataType = (typeof RELATION_FIELD_TYPES)[number]; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/find-flat-field-metadatas-related-to-morph-relation-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/find-flat-field-metadatas-related-to-morph-relation-or-throw.util.ts new file mode 100644 index 0000000000..34b998df6b --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/find-flat-field-metadatas-related-to-morph-relation-or-throw.util.ts @@ -0,0 +1,67 @@ +import { FieldMetadataType } from 'twenty-shared/types'; +import { isDefined } from 'twenty-shared/utils'; + +import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-relation-flat-field-metadatas-target-flat-field-metadata-or-throw.util'; +import { isFlatFieldMetadataEntityOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util'; +import { + FlatObjectMetadataMapsException, + FlatObjectMetadataMapsExceptionCode, +} from 'src/engine/metadata-modules/flat-object-metadata-maps/flat-object-metadata-maps.exception'; +import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; + +export type FindFlatFieldMetadatasRelatedToMorphRelationOrThrowArgs = { + flatObjectMetadataMaps: FlatObjectMetadataMaps; + flatFieldMetadata: FlatFieldMetadata; +}; +export const findFlatFieldMetadatasRelatedToMorphRelationOrThrow = ({ + flatObjectMetadataMaps, + flatFieldMetadata: morphRelationFlatFieldMetadata, +}: FindFlatFieldMetadatasRelatedToMorphRelationOrThrowArgs): FlatFieldMetadata[] => { + const flatObjectMetadataWithFlatFieldMaps = + flatObjectMetadataMaps.byId[ + morphRelationFlatFieldMetadata.objectMetadataId + ]; + + if (!isDefined(flatObjectMetadataWithFlatFieldMaps)) { + throw new FlatObjectMetadataMapsException( + 'Morph field relation object metadata not found', + FlatObjectMetadataMapsExceptionCode.OBJECT_METADATA_NOT_FOUND, + ); + } + + if ( + !isDefined( + flatObjectMetadataWithFlatFieldMaps.fieldsById[ + morphRelationFlatFieldMetadata.id + ], + ) + ) { + throw new FlatObjectMetadataMapsException( + 'Morph relation field not found in related object metadata', + FlatObjectMetadataMapsExceptionCode.FIELD_METADATA_NOT_FOUND, + ); + } + + return flatObjectMetadataWithFlatFieldMaps.flatFieldMetadatas.flatMap( + (flatFieldMetadata) => { + if ( + !isFlatFieldMetadataEntityOfType( + flatFieldMetadata, + FieldMetadataType.MORPH_RELATION, + ) || + flatFieldMetadata.name !== morphRelationFlatFieldMetadata.name + ) { + return []; + } + + const relationTargetFlatFieldMetadata = + findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow({ + flatFieldMetadata, + flatObjectMetadataMaps, + }); + + return [flatFieldMetadata, relationTargetFlatFieldMetadata]; + }, + ); +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-delete-field-input-to-flat-field-metadatas-to-delete.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-delete-field-input-to-flat-field-metadatas-to-delete.util.ts index 0c37a0a743..3c19ca5211 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-delete-field-input-to-flat-field-metadatas-to-delete.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-delete-field-input-to-flat-field-metadatas-to-delete.util.ts @@ -10,6 +10,7 @@ import { FieldMetadataExceptionCode, } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; +import { findFlatFieldMetadatasRelatedToMorphRelationOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-flat-field-metadatas-related-to-morph-relation-or-throw.util'; import { findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-relation-flat-field-metadatas-target-flat-field-metadata-or-throw.util'; import { isFlatFieldMetadataEntityOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util'; import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type'; @@ -45,11 +46,23 @@ export const fromDeleteFieldInputToFlatFieldMetadatasToDelete = ({ if ( isFlatFieldMetadataEntityOfType( flatFieldMetadataToDelete, - FieldMetadataType.RELATION, - ) || + FieldMetadataType.MORPH_RELATION, + ) + ) { + return findFlatFieldMetadatasRelatedToMorphRelationOrThrow({ + flatObjectMetadataMaps: existingFlatObjectMetadataMaps, + flatFieldMetadata: flatFieldMetadataToDelete, + }); + } + + if ( isFlatFieldMetadataEntityOfType( flatFieldMetadataToDelete, - FieldMetadataType.MORPH_RELATION, + FieldMetadataType.RELATION, + ) && + isFlatFieldMetadataEntityOfType( + flatFieldMetadataToDelete.flatRelationTargetFieldMetadata, + FieldMetadataType.RELATION, ) ) { const relationTargetFlatFieldMetadata = @@ -61,5 +74,22 @@ export const fromDeleteFieldInputToFlatFieldMetadatasToDelete = ({ return [flatFieldMetadataToDelete, relationTargetFlatFieldMetadata]; } + if ( + isFlatFieldMetadataEntityOfType( + flatFieldMetadataToDelete, + FieldMetadataType.RELATION, + ) && + isFlatFieldMetadataEntityOfType( + flatFieldMetadataToDelete.flatRelationTargetFieldMetadata, + FieldMetadataType.MORPH_RELATION, + ) + ) { + return findFlatFieldMetadatasRelatedToMorphRelationOrThrow({ + flatObjectMetadataMaps: existingFlatObjectMetadataMaps, + flatFieldMetadata: + flatFieldMetadataToDelete.flatRelationTargetFieldMetadata, + }); + } + return [flatFieldMetadataToDelete]; }; 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 ef0caf224c..9d08916f27 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 @@ -8,4 +8,6 @@ import { isFlatFieldMetadataEntityOfTypes } from 'src/engine/metadata-modules/fl export const isRelationFlatFieldMetadata = ( flatFieldMetadata: FlatFieldMetadata, ): flatFieldMetadata is FlatFieldMetadata => - isFlatFieldMetadataEntityOfTypes(flatFieldMetadata, RELATION_FIELD_TYPES); + isFlatFieldMetadataEntityOfTypes(flatFieldMetadata, [ + ...RELATION_FIELD_TYPES, + ]); 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 831b4ef45e..2f923214f6 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 @@ -7,5 +7,5 @@ import { export const isRelationFieldMetadataType = ( type: FieldMetadataType, ): type is RelationFieldMetadataType => { - return RELATION_FIELD_TYPES.includes(type); + return RELATION_FIELD_TYPES.includes(type as RelationFieldMetadataType); };