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 index b670f504bc5..6123a63ed84 100644 --- 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 @@ -4,8 +4,8 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su { "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", + "message": "Morph relation creation payloads must have the same relation type", + "userFriendlyMessage": "Morph relation creation payloads must have the same relation type", }, "status": "fail", } @@ -32,8 +32,8 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su { "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", + "message": "Morph relation creation payloads must have only relation to the same object metadata", + "userFriendlyMessage": "Morph relation creation payloads must only contain relation to the same object metadata", }, "status": "fail", } @@ -42,10 +42,9 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su 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": [], + "code": "FIELD_METADATA_RELATION_MALFORMED", + "message": "Morph relation creation payloads are empty", + "userFriendlyMessage": "At least one relation is require", }, "status": "fail", } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service.ts index 62335eca695..d45fcbac083 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service.ts @@ -6,16 +6,12 @@ import { FieldMetadataType } from 'twenty-shared/types'; import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; -import { - FieldMetadataException, - FieldMetadataExceptionCode, -} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; +import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; import { ValidateOneFieldMetadataArgs } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service'; import { type FlatFieldMetadataTypeValidator } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-type-validator.type'; import { FlatFieldMetadataValidationError } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-validation-error.type'; -import { isEnumValidateOneFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-enum-validate-one-field-metadata-args.util'; import { validateEnumSelectFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-enum-flat-field-metadata.util'; -import { validateRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-flat-field-metadata.util'; +import { validateRelationOrMorphRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-or-morph-relation-flat-field-metadata.util'; @Injectable() export class FlatFieldMetadataTypeValidatorService { constructor(private readonly featureFlagService: FeatureFlagService) {} @@ -52,7 +48,12 @@ export class FlatFieldMetadataTypeValidatorService { LINKS: async (_args) => { return []; }, - MORPH_RELATION: async ({ workspaceId }) => { + MORPH_RELATION: async ({ + workspaceId, + existingFlatObjectMetadataMaps, + flatFieldMetadataToValidate, + otherFlatObjectMetadataMapsToValidate, + }) => { const isMorphRelationEnabled = await this.featureFlagService.isFeatureEnabled( FeatureFlagKey.IS_MORPH_RELATION_ENABLED, @@ -69,18 +70,26 @@ export class FlatFieldMetadataTypeValidatorService { ]; } - return []; + return validateRelationOrMorphRelationFlatFieldMetadata({ + existingFlatObjectMetadataMaps, + flatFieldMetadataToValidate, + workspaceId, + otherFlatObjectMetadataMapsToValidate, + }); }, - MULTI_SELECT: (args) => { - if (!isEnumValidateOneFieldMetadata(args)) { - throw new FieldMetadataException( - 'Should never occur, invalid enum field metadata type', - FieldMetadataExceptionCode.INTERNAL_SERVER_ERROR, - ); - } + MULTI_SELECT: ({ + existingFlatObjectMetadataMaps, + flatFieldMetadataToValidate, + workspaceId, + otherFlatObjectMetadataMapsToValidate, + }) => + validateEnumSelectFlatFieldMetadata({ + existingFlatObjectMetadataMaps, + flatFieldMetadataToValidate, + workspaceId, + otherFlatObjectMetadataMapsToValidate, + }), - return validateEnumSelectFlatFieldMetadata(args); - }, NUMBER: async (_args) => { return []; }, @@ -93,36 +102,51 @@ export class FlatFieldMetadataTypeValidatorService { POSITION: async (_args) => { return []; }, - RATING: (args) => { - if (!isEnumValidateOneFieldMetadata(args)) { - throw new FieldMetadataException( - 'Should never occur, invalid enum field metadata type', - FieldMetadataExceptionCode.INTERNAL_SERVER_ERROR, - ); - } - - return validateEnumSelectFlatFieldMetadata(args); - }, + RATING: ({ + existingFlatObjectMetadataMaps, + flatFieldMetadataToValidate, + workspaceId, + otherFlatObjectMetadataMapsToValidate, + }) => + validateEnumSelectFlatFieldMetadata({ + existingFlatObjectMetadataMaps, + flatFieldMetadataToValidate, + workspaceId, + otherFlatObjectMetadataMapsToValidate, + }), RAW_JSON: async (_args) => { return []; }, - RELATION: validateRelationFlatFieldMetadata, + RELATION: ({ + existingFlatObjectMetadataMaps, + flatFieldMetadataToValidate, + workspaceId, + otherFlatObjectMetadataMapsToValidate, + }) => + validateRelationOrMorphRelationFlatFieldMetadata({ + existingFlatObjectMetadataMaps, + flatFieldMetadataToValidate, + workspaceId, + otherFlatObjectMetadataMapsToValidate, + }), RICH_TEXT: async (_args) => { return []; }, RICH_TEXT_V2: async (_args) => { return []; }, - SELECT: (args) => { - if (!isEnumValidateOneFieldMetadata(args)) { - throw new FieldMetadataException( - 'Should never occur, invalid enum field metadata type', - FieldMetadataExceptionCode.INTERNAL_SERVER_ERROR, - ); - } - - return validateEnumSelectFlatFieldMetadata(args); - }, + SELECT: ({ + existingFlatObjectMetadataMaps, + flatFieldMetadataToValidate, + workspaceId, + otherFlatObjectMetadataMapsToValidate, + }) => + validateEnumSelectFlatFieldMetadata({ + existingFlatObjectMetadataMaps, + flatFieldMetadataToValidate, + workspaceId, + otherFlatObjectMetadataMapsToValidate, + }), TEXT: async (_args) => { return []; }, 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 index a0b46882060..4e5fc051918 100644 --- 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 @@ -35,8 +35,7 @@ export const fromMorphRelationCreateFieldInputToFlatFieldMetadatas = async ({ if ( !isDefined(rawMorphCreationPayload) || - !Array.isArray(rawMorphCreationPayload) || - rawMorphCreationPayload.length === 0 + !Array.isArray(rawMorphCreationPayload) ) { return { status: 'fail', diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-enum-validate-one-field-metadata-args.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-enum-validate-one-field-metadata-args.util.ts deleted file mode 100644 index 8b30ba39e8b..00000000000 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/is-enum-validate-one-field-metadata-args.util.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { - type EnumFieldMetadataType, - type FieldMetadataType, -} from 'twenty-shared/types'; - -import { isEnumFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util'; -import { type ValidateOneFieldMetadataArgs } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service'; - -export const isEnumValidateOneFieldMetadata = ( - args: ValidateOneFieldMetadataArgs, -): args is ValidateOneFieldMetadataArgs & - ValidateOneFieldMetadataArgs => - isEnumFieldMetadataType(args.flatFieldMetadataToValidate.type); 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 index f3e788a602a..2d5d077ca2c 100644 --- 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 @@ -1,12 +1,12 @@ -import { type RelationCreationPayload } from 'twenty-shared/types'; import { t } from '@lingui/core/macro'; import { isDefined } from 'class-validator'; +import { type RelationCreationPayload } from 'twenty-shared/types'; import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; import { type FailedFieldInputTranspilation, - type SuccessfulFieldInputTranspilation, type FieldInputTranspilationResult, + type SuccessfulFieldInputTranspilation, } 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'; @@ -27,6 +27,17 @@ export const validateMorphRelationCreationPayload = async ({ }: ValidateMorphRelationCreationPayloadUtilArgs): Promise< FieldInputTranspilationResult > => { + if (morphRelationCreationPayload.length === 0) { + return { + status: 'fail', + error: { + code: FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED, + message: 'Morph relation creation payloads are empty', + userFriendlyMessage: t`At least one relation is require`, + }, + }; + } + const allRelationType = [ ...new Set( morphRelationCreationPayload.map( @@ -40,8 +51,9 @@ export const validateMorphRelationCreationPayload = async ({ 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`, + message: + 'Morph relation creation payloads must have the same relation type', + userFriendlyMessage: t`Morph relation creation payloads must have the same relation type`, }, }; } @@ -61,8 +73,8 @@ export const validateMorphRelationCreationPayload = async ({ 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`, + 'Morph relation creation payloads must have only relation to the same object metadata', + userFriendlyMessage: t`Morph relation creation payloads must only contain relation to the same object metadata`, }, }; } diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-flat-field-metadata.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-or-morph-relation-flat-field-metadata.util.ts similarity index 90% rename from packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-flat-field-metadata.util.ts rename to packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-or-morph-relation-flat-field-metadata.util.ts index ea55c1ffcc2..a8f7101cf68 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-flat-field-metadata.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-or-morph-relation-flat-field-metadata.util.ts @@ -1,16 +1,16 @@ import { t } from '@lingui/core/macro'; -import { type FieldMetadataType } from 'twenty-shared/types'; import { isDefined, isValidUuid } from 'twenty-shared/utils'; 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 { type ValidateOneFieldMetadataArgs } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service'; import { type FlatFieldMetadataValidationError } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-validation-error.type'; -export const validateRelationFlatFieldMetadata = async ({ +export const validateRelationOrMorphRelationFlatFieldMetadata = async ({ existingFlatObjectMetadataMaps, flatFieldMetadataToValidate, otherFlatObjectMetadataMapsToValidate, -}: ValidateOneFieldMetadataArgs): Promise< +}: ValidateOneFieldMetadataArgs): Promise< FlatFieldMetadataValidationError[] > => { const { relationTargetFieldMetadataId, relationTargetObjectMetadataId } =