Refactor FieldMetadataService and validation to consume FlatObjectMetadataMaps (#13719)

# Introduction
Following recent `FlatObjectMetadataMaps` manipulation, transpilers
utils introduction in https://github.com/twentyhq/twenty/pull/13620
Refactored the field metadata service and validator to iterate over
`FlatObjectMetadataMaps` instead of `FlatObjectMetadata[]`.

The object metadata service v2 is shadow coding
This commit is contained in:
Paul Rastoin
2025-08-07 17:19:07 +02:00
committed by GitHub
parent 05c6805f0a
commit 83a560c936
20 changed files with 557 additions and 165 deletions
@@ -11,8 +11,7 @@ import { FlatFieldMetadataTypeValidatorService } from 'src/engine/metadata-modul
import { FailedFlatFieldMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type';
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { validateFlatFieldMetadataNameAvailability } from 'src/engine/metadata-modules/flat-field-metadata/validators/validate-flat-field-metadata-name-availability.validator';
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
import { mergeTwoFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/merge-two-flat-object-metadatas.util';
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
import {
ObjectMetadataException,
ObjectMetadataExceptionCode,
@@ -27,8 +26,8 @@ import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/
export type ValidateOneFieldMetadataArgs<
T extends FieldMetadataType = FieldMetadataType,
> = {
existingFlatObjectMetadatas: FlatObjectMetadata[];
othersFlatObjectMetadataToValidate?: FlatObjectMetadata[];
existingFlatObjectMetadataMaps: FlatObjectMetadataMaps;
otherFlatObjectMetadataMapsToValidate?: FlatObjectMetadataMaps;
flatFieldMetadataToValidate: FlatFieldMetadata<T>;
workspaceId: string;
};
@@ -42,32 +41,27 @@ export class FlatFieldMetadataValidatorService {
async validateOneFlatFieldMetadata<
T extends FieldMetadataType = FieldMetadataType,
>({
existingFlatObjectMetadatas,
existingFlatObjectMetadataMaps,
flatFieldMetadataToValidate,
othersFlatObjectMetadataToValidate,
otherFlatObjectMetadataMapsToValidate,
workspaceId,
}: ValidateOneFieldMetadataArgs<T>): Promise<
FailedFlatFieldMetadataValidationExceptions[]
> {
const errors: FailedFlatFieldMetadataValidationExceptions[] = [];
const allFlatObjectMetadata = isDefined(othersFlatObjectMetadataToValidate)
? mergeTwoFlatObjectMetadatas({
destFlatObjectMetadatas: existingFlatObjectMetadatas,
toMergeFlatObjectMetadatas: othersFlatObjectMetadataToValidate,
})
: existingFlatObjectMetadatas;
const parentFlatObjectMetadata = allFlatObjectMetadata.find(
(existingFlatObjectMetadata) =>
existingFlatObjectMetadata.id ===
flatFieldMetadataToValidate.objectMetadataId,
);
const parentFlatObjectMetadata =
otherFlatObjectMetadataMapsToValidate?.byId[
flatFieldMetadataToValidate.objectMetadataId
] ??
existingFlatObjectMetadataMaps.byId[
flatFieldMetadataToValidate.objectMetadataId
];
if (!isDefined(parentFlatObjectMetadata)) {
errors.push(
new FieldMetadataException(
isDefined(othersFlatObjectMetadataToValidate)
isDefined(otherFlatObjectMetadataMapsToValidate)
? 'Object metadata not found in both existing and about to be created object metadatas'
: 'Object metadata not found',
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
@@ -139,10 +133,10 @@ export class FlatFieldMetadataValidatorService {
} else {
const fieldMetadataTypeValidatorExceptions =
await fieldMetadataTypeValidator({
existingFlatObjectMetadatas,
existingFlatObjectMetadataMaps,
flatFieldMetadataToValidate,
workspaceId,
othersFlatObjectMetadataToValidate,
otherFlatObjectMetadataMapsToValidate,
});
errors.push(...fieldMetadataTypeValidatorExceptions);
@@ -7,17 +7,16 @@ import {
} 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 { FailedFlatFieldMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type';
import { mergeTwoFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/merge-two-flat-object-metadatas.util';
// Remark: This is duplicated with api metadata transpilers exceptions handlers
// We might wanna have an NotValidatedFlatFieldMetadata and NotValidatedFlatObjectMetadata, in order to avoid
export const validateRelationFlatFieldMetadata = async ({
existingFlatObjectMetadatas,
existingFlatObjectMetadataMaps,
flatFieldMetadataToValidate: {
relationTargetFieldMetadataId,
relationTargetObjectMetadataId,
},
othersFlatObjectMetadataToValidate,
otherFlatObjectMetadataMapsToValidate,
}: ValidateOneFieldMetadataArgs<FieldMetadataType.RELATION>): Promise<
FailedFlatFieldMetadataValidationExceptions[]
> => {
@@ -38,22 +37,16 @@ export const validateRelationFlatFieldMetadata = async ({
}
const errors: FailedFlatFieldMetadataValidationExceptions[] = [];
const allFlatObjectMetadata = isDefined(othersFlatObjectMetadataToValidate)
? mergeTwoFlatObjectMetadatas({
destFlatObjectMetadatas: existingFlatObjectMetadatas,
toMergeFlatObjectMetadatas: othersFlatObjectMetadataToValidate,
})
: existingFlatObjectMetadatas;
const targetRelationFlatObjectMetadata = allFlatObjectMetadata.find(
(flatObjectMetadata) =>
flatObjectMetadata.id === relationTargetObjectMetadataId,
);
const targetRelationFlatObjectMetadata =
otherFlatObjectMetadataMapsToValidate?.byId[
relationTargetObjectMetadataId
] ?? existingFlatObjectMetadataMaps.byId[relationTargetObjectMetadataId];
if (!isDefined(targetRelationFlatObjectMetadata)) {
errors.push(
new FieldMetadataException(
isDefined(othersFlatObjectMetadataToValidate)
isDefined(otherFlatObjectMetadataMapsToValidate)
? 'Relation target object metadata not found in both existing and about to be created object metadatas'
: 'Relation target object metadata not found',
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
@@ -62,15 +55,15 @@ export const validateRelationFlatFieldMetadata = async ({
}
const targetRelationFlatFieldMetadata =
targetRelationFlatObjectMetadata?.flatFieldMetadatas.find(
(flatFieldMetadata) =>
flatFieldMetadata.id === relationTargetFieldMetadataId,
);
targetRelationFlatObjectMetadata?.fieldsById[relationTargetFieldMetadataId];
if (!isDefined(targetRelationFlatFieldMetadata)) {
if (
isDefined(targetRelationFlatObjectMetadata) &&
!isDefined(targetRelationFlatFieldMetadata)
) {
errors.push(
new FieldMetadataException(
isDefined(othersFlatObjectMetadataToValidate)
isDefined(otherFlatObjectMetadataMapsToValidate)
? 'Relation field target metadata not found in both existing and about to be created field metadatas'
: 'Relation field target metadata not found',
FieldMetadataExceptionCode.FIELD_METADATA_NOT_FOUND,