Multiple errors on field input transpilation improvement (#13774)

# Introduction
- ~~returning deleted field on deleteOneField~~ postponed for later
cannot build dto from flat atm
- refactor createFieldInput transpilation to handle multiple errors
instead of throwing
- renamed extract function
This commit is contained in:
Paul Rastoin
2025-08-08 16:24:47 +02:00
committed by GitHub
parent 7a90fb2c5f
commit 4523ee45bc
15 changed files with 255 additions and 163 deletions
@@ -19,7 +19,7 @@ import {
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
import { computeRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-relation-field-join-column-name.util';
import { prepareCustomFieldMetadataForCreation } from 'src/engine/metadata-modules/field-metadata/utils/prepare-field-metadata-for-creation.util';
import { validateRelationCreationPayloadOrThrow } from 'src/engine/metadata-modules/field-metadata/utils/validate-relation-creation-payload.util';
import { validateRelationCreationPayloadOrThrow } from 'src/engine/metadata-modules/field-metadata/utils/validate-relation-creation-payload-or-throw.util';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
@@ -22,12 +22,13 @@ import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-m
import { fromCreateFieldInputToFlatFieldMetadatasToCreate } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-metadatas-to-create.util';
import { fromDeleteFieldInputToFlatFieldMetadatasToDelete } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-delete-field-input-to-flat-field-metadatas-to-delete.util';
import { isFlatFieldMetadataEntityOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util';
import { throwOnFieldInputTranspilationsError } from 'src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util';
import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
import { addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util';
import { addFlatFieldMetadataInFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps.util';
import { deleteFieldFromFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/delete-field-from-flat-object-metadata-maps-or-throw.util';
import { extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.util';
import { extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps.util';
import { getSubFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/get-sub-flat-object-metadata-maps-or-throw.util';
import { getSubFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/get-sub-flat-object-metadata-maps.util';
import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service';
import { WorkspaceMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service';
import { WorkspaceMigrationRunnerV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/workspace-migration-runner-v2.service';
@@ -105,7 +106,7 @@ export class FieldMetadataServiceV2 {
}
const flatObjectMetadataMapsWithImpactedObject =
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({
getSubFlatObjectMetadataMapsOrThrow({
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
objectMetadataIds: flatFieldMetadatasToDelete.map(
(flatFieldMetadataToDelete) =>
@@ -132,7 +133,8 @@ export class FieldMetadataServiceV2 {
await this.workspaceMigrationRunnerV2Service.run(workspaceMigration);
return;
// TODO to be discussed with coco regarding storing dates in flat in order to build dtos
// return flatFieldMetadatasToDelete[0];
}
private computeOtherFlatObjectMetadataMapsToValidate({
@@ -171,7 +173,7 @@ export class FieldMetadataServiceV2 {
}
const flatObjectMetadataMapsWithRelatedObjectMetadata =
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps({
getSubFlatObjectMetadataMaps({
flatObjectMetadataMaps,
objectMetadataIds: [relatedFlatFieldMetadataToCreate.objectMetadataId],
});
@@ -202,7 +204,7 @@ export class FieldMetadataServiceV2 {
{ workspaceId },
);
const flatFieldMetadatasToCreate = (
const allInputTranspilationsResults = (
await Promise.all(
fieldMetadataInputs.map(
async (fieldMetadataInput) =>
@@ -215,6 +217,14 @@ export class FieldMetadataServiceV2 {
)
).flat();
throwOnFieldInputTranspilationsError(
allInputTranspilationsResults,
'Multiple validation errors occurred while creating field',
);
const flatFieldMetadatasToCreate = allInputTranspilationsResults.flatMap(
({ result }) => result,
);
const allValidationErrors: FailedFlatFieldMetadataValidationExceptions[] =
[];
let optimisticFlatObjectMetadataMaps = structuredClone(
@@ -274,16 +284,14 @@ export class FieldMetadataServiceV2 {
);
try {
const fromFlatObjectMetadataMaps =
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
objectMetadataIds: impactedObjectMetadataIds,
});
const toFlatObjectMetadataMaps =
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({
flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps,
objectMetadataIds: impactedObjectMetadataIds,
});
const fromFlatObjectMetadataMaps = getSubFlatObjectMetadataMapsOrThrow({
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
objectMetadataIds: impactedObjectMetadataIds,
});
const toFlatObjectMetadataMaps = getSubFlatObjectMetadataMapsOrThrow({
flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps,
objectMetadataIds: impactedObjectMetadataIds,
});
const workspaceMigration = this.workspaceMigrationBuilderV2.build({
fromFlatObjectMetadataMaps,
toFlatObjectMetadataMaps,
@@ -0,0 +1,13 @@
import { type FailedFlatFieldMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type';
export type FailedFieldInputTranspilation = {
status: 'fail';
error: FailedFlatFieldMetadataValidationExceptions;
};
export type SuccessfulFieldInputTranspilation<T> = {
status: 'success';
result: T;
};
export type FieldInputTranspilationResult<T> =
| FailedFieldInputTranspilation
| SuccessfulFieldInputTranspilation<T>;
@@ -15,12 +15,13 @@ import {
FieldMetadataExceptionCode,
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
import { generateRatingOptions } from 'src/engine/metadata-modules/field-metadata/utils/generate-rating-optionts.util';
import { type FieldInputTranspilationResult } from 'src/engine/metadata-modules/flat-field-metadata/types/field-input-transpilation-result.type';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { fromRelationCreateFieldInputToFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-relation-create-field-input-to-flat-field-metadata.util';
import { getDefaultFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/get-default-flat-field-metadata-from-create-field-input.util';
import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
type FromCreateFieldInputToFlatObjectMetadata = {
type FromCreateFieldInputToFlatObjectMetadataArgs = {
rawCreateFieldInput: Omit<CreateFieldInput, 'workspaceId'>;
existingFlatObjectMetadataMaps: FlatObjectMetadataMaps;
workspaceId: string;
@@ -30,12 +31,17 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
rawCreateFieldInput,
workspaceId,
existingFlatObjectMetadataMaps,
}: FromCreateFieldInputToFlatObjectMetadata): Promise<FlatFieldMetadata[]> => {
}: FromCreateFieldInputToFlatObjectMetadataArgs): Promise<
FieldInputTranspilationResult<FlatFieldMetadata[]>
> => {
if (rawCreateFieldInput.isRemoteCreation) {
throw new FieldMetadataException(
"Remote fields aren't supported",
FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
);
return {
status: 'fail',
error: new FieldMetadataException(
"Remote fields aren't supported",
FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
),
};
}
const createFieldInput =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
@@ -46,14 +52,17 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
existingFlatObjectMetadataMaps.byId[createFieldInput.objectMetadataId];
if (!isDefined(parentFlatObjectMetadata)) {
throw new FieldMetadataException(
'Provided object metadata id does not exist',
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
{
userFriendlyMessage:
'Created field metadata, parent object metadata not found',
},
);
return {
status: 'fail',
error: new FieldMetadataException(
'Provided object metadata id does not exist',
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
{
userFriendlyMessage:
'Created field metadata, parent object metadata not found',
},
),
};
}
const fieldMetadataId = v4();
@@ -71,7 +80,7 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
);
}
case FieldMetadataType.RELATION: {
return fromRelationCreateFieldInputToFlatFieldMetadata({
return await fromRelationCreateFieldInputToFlatFieldMetadata({
existingFlatObjectMetadataMaps,
sourceParentFlatObjectMetadata: parentFlatObjectMetadata,
createFieldInput,
@@ -79,15 +88,18 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
});
}
case FieldMetadataType.RATING: {
return [
{
...commonFlatFieldMetadata,
type: createFieldInput.type,
settings: null,
defaultValue: commonFlatFieldMetadata.defaultValue as string, // Could this be improved ?
options: generateRatingOptions(),
} satisfies FlatFieldMetadata<typeof createFieldInput.type>,
];
return {
status: 'success',
result: [
{
...commonFlatFieldMetadata,
type: createFieldInput.type,
settings: null,
defaultValue: commonFlatFieldMetadata.defaultValue as string, // Could this be improved ?
options: generateRatingOptions(),
} satisfies FlatFieldMetadata<typeof createFieldInput.type>,
],
};
}
case FieldMetadataType.SELECT:
case FieldMetadataType.MULTI_SELECT: {
@@ -100,15 +112,18 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
),
}));
return [
{
...commonFlatFieldMetadata,
type: createFieldInput.type,
options,
defaultValue: commonFlatFieldMetadata.defaultValue as string, // Could this be improved ?
settings: null,
} satisfies FlatFieldMetadata<typeof createFieldInput.type>,
];
return {
status: 'success',
result: [
{
...commonFlatFieldMetadata,
type: createFieldInput.type,
options,
defaultValue: commonFlatFieldMetadata.defaultValue as string, // Could this be improved ?
settings: null,
} satisfies FlatFieldMetadata<typeof createFieldInput.type>,
],
};
}
case FieldMetadataType.UUID:
case FieldMetadataType.TEXT:
@@ -130,12 +145,15 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
case FieldMetadataType.ACTOR:
case FieldMetadataType.ARRAY:
case FieldMetadataType.TS_VECTOR: {
return [
{
...commonFlatFieldMetadata,
type: createFieldInput.type,
},
];
return {
status: 'success',
result: [
{
...commonFlatFieldMetadata,
type: createFieldInput.type,
},
],
};
}
default: {
assertUnreachable(createFieldInput.type, 'Encountered an uncovered');
@@ -1,5 +1,8 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import {
isDefined,
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties,
} from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
@@ -9,7 +12,8 @@ import {
FieldMetadataException,
FieldMetadataExceptionCode,
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
import { validateRelationCreationPayloadOrThrow } from 'src/engine/metadata-modules/field-metadata/utils/validate-relation-creation-payload.util';
import { validateRelationCreationPayloadOrThrow } from 'src/engine/metadata-modules/field-metadata/utils/validate-relation-creation-payload-or-throw.util';
import { type FieldInputTranspilationResult } from 'src/engine/metadata-modules/flat-field-metadata/types/field-input-transpilation-result.type';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { getDefaultFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/get-default-flat-field-metadata-from-create-field-input.util';
import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
@@ -50,17 +54,38 @@ export const fromRelationCreateFieldInputToFlatFieldMetadata = async ({
createFieldInput,
workspaceId,
}: FromRelationCreateFieldInputToFlatFieldMetadataArgs): Promise<
FlatFieldMetadata[]
FieldInputTranspilationResult<FlatFieldMetadata[]>
> => {
const { relationCreationPayload } = createFieldInput;
const rawCreationPayload = createFieldInput.relationCreationPayload;
if (!isDefined(relationCreationPayload)) {
throw new FieldMetadataException(
`Relation creation payload is required`,
FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
);
if (!isDefined(rawCreationPayload)) {
return {
status: 'fail',
error: new FieldMetadataException(
`Relation creation payload is required`,
FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
),
};
}
const relationCreationPayload =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
rawCreationPayload,
['targetFieldIcon', 'targetFieldLabel', 'targetObjectMetadataId', 'type'],
);
try {
await validateRelationCreationPayloadOrThrow(relationCreationPayload);
} catch (error) {
if (error instanceof FieldMetadataException) {
return {
status: 'fail',
error,
};
} else {
throw error;
}
}
await validateRelationCreationPayloadOrThrow(relationCreationPayload);
const targetParentFlatObjectMetadata =
existingFlatObjectMetadataMaps.byId[
@@ -68,10 +93,13 @@ export const fromRelationCreateFieldInputToFlatFieldMetadata = async ({
];
if (!isDefined(targetParentFlatObjectMetadata)) {
throw new FieldMetadataException(
`Object metadata relation target not found for relation creation payload`,
FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED,
);
return {
status: 'fail',
error: new FieldMetadataException(
`Object metadata relation target not found for relation creation payload`,
FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED,
),
};
}
const sourceFlatFieldMetadataSettings =
@@ -135,11 +163,14 @@ export const fromRelationCreateFieldInputToFlatFieldMetadata = async ({
flatRelationTargetObjectMetadata: sourceParentFlatObjectMetadata,
};
return [
{
...sourceFlatFieldMetadata,
flatRelationTargetFieldMetadata: targetFlatFieldMetadata,
},
targetFlatFieldMetadata,
] satisfies FlatFieldMetadata<FieldMetadataType.RELATION>[];
return {
status: 'success',
result: [
{
...sourceFlatFieldMetadata,
flatRelationTargetFieldMetadata: targetFlatFieldMetadata,
},
targetFlatFieldMetadata,
] satisfies FlatFieldMetadata<FieldMetadataType.RELATION>[],
};
};
@@ -0,0 +1,27 @@
import { MultipleMetadataValidationErrors } from 'src/engine/core-modules/error/multiple-metadata-validation-errors';
import {
type FieldInputTranspilationResult,
type SuccessfulFieldInputTranspilation,
} from 'src/engine/metadata-modules/flat-field-metadata/types/field-input-transpilation-result.type';
type ThrowOnFieldInputTranspilationsErrorArgs = <T>(
inputTranspilationResults: FieldInputTranspilationResult<T>[],
errorLabel: string,
) => asserts inputTranspilationResults is SuccessfulFieldInputTranspilation<T>[];
export const throwOnFieldInputTranspilationsError: ThrowOnFieldInputTranspilationsErrorArgs =
<T>(
inputTranspilationResults: FieldInputTranspilationResult<T>[],
errorLabel: string,
) => {
const failedInputTranspilationErrors = inputTranspilationResults.flatMap(
(transpilationResult) =>
transpilationResult.status === 'fail' ? transpilationResult.error : [],
);
if (failedInputTranspilationErrors.length > 0) {
throw new MultipleMetadataValidationErrors(
failedInputTranspilationErrors,
errorLabel,
);
}
};
@@ -1,5 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow should throw when extracting twice the same object 1`] = `"addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow: flat object metadata with fields maps to add already exists"`;
exports[`extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow should throw when object metadata id is not found 1`] = `"extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow object metadata not found"`;
@@ -0,0 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`getSubFlatObjectMetadataMapsOrThrow should throw when extracting twice the same object 1`] = `"addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow: flat object metadata with fields maps to add already exists"`;
exports[`getSubFlatObjectMetadataMapsOrThrow should throw when object metadata id is not found 1`] = `"getSubFlatObjectMetadataMapsOrThrow object metadata not found"`;
@@ -1,27 +1,27 @@
import { jestExpectToBeDefined } from 'test/utils/expect-to-be-defined.util.test';
import {
type EachTestingContext,
eachTestingContextFilter,
type EachTestingContext,
} from 'twenty-shared/testing';
import { FLAT_OBJECT_METADATA_MAPS_MOCKS } from 'src/engine/metadata-modules/flat-object-metadata-maps/mocks/flat-object-metadata-maps.mock';
import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
import {
type ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs,
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow,
} from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.util';
getSubFlatObjectMetadataMapsOrThrow,
type GetSubFlatObjectMetadataMapsOrThrowArgs,
} from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/get-sub-flat-object-metadata-maps-or-throw.util';
import { PET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/pet-flat-object.mock';
import { ROCKET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/rocket-flat-object.mock';
import { fromFlatObjectMetadatasToFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadatas-to-flat-object-metadata-maps.util';
type ExtractFlatObjectMetadataMapsTestCase = {
input: ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs;
type GetSubObjectMetadataMapsOrThrowTestCase = {
input: GetSubFlatObjectMetadataMapsOrThrowArgs;
shouldThrow?: true;
expected?: FlatObjectMetadataMaps;
};
describe('extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow', () => {
const testCases: EachTestingContext<ExtractFlatObjectMetadataMapsTestCase>[] =
describe('getSubFlatObjectMetadataMapsOrThrow', () => {
const testCases: EachTestingContext<GetSubObjectMetadataMapsOrThrowTestCase>[] =
[
{
title: 'should throw when object metadata id is not found',
@@ -89,18 +89,17 @@ describe('extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow', () =
}) => {
if (shouldThrow) {
expect(() =>
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({
getSubFlatObjectMetadataMapsOrThrow({
objectMetadataIds,
flatObjectMetadataMaps,
}),
).toThrowErrorMatchingSnapshot();
} else {
jestExpectToBeDefined(expected);
const result =
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({
objectMetadataIds,
flatObjectMetadataMaps,
});
const result = getSubFlatObjectMetadataMapsOrThrow({
objectMetadataIds,
flatObjectMetadataMaps,
});
expect(result).toEqual(expected);
}
@@ -1,19 +1,19 @@
import {
type EachTestingContext,
eachTestingContextFilter,
type EachTestingContext,
} from 'twenty-shared/testing';
import { FLAT_OBJECT_METADATA_MAPS_MOCKS } from 'src/engine/metadata-modules/flat-object-metadata-maps/mocks/flat-object-metadata-maps.mock';
import { type ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.util';
import { extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps.util';
import { type GetSubFlatObjectMetadataMapsOrThrowArgs } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/get-sub-flat-object-metadata-maps-or-throw.util';
import { getSubFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/get-sub-flat-object-metadata-maps.util';
import { PET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/pet-flat-object.mock';
type ExtractFlatObjectMetadataMapsTestCase = {
input: ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs;
type GetSubFlatObjectMetadataMapsTestCase = {
input: GetSubFlatObjectMetadataMapsOrThrowArgs;
};
describe('extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps', () => {
const testCases: EachTestingContext<ExtractFlatObjectMetadataMapsTestCase>[] =
describe('getSubFlatObjectMetadataMaps', () => {
const testCases: EachTestingContext<GetSubFlatObjectMetadataMapsTestCase>[] =
[
{
title: 'should throw when object metadata id is not found',
@@ -47,7 +47,7 @@ describe('extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps', () => {
input: { objectMetadataIds, flatObjectMetadataMaps },
},
}) => {
const result = extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps({
const result = getSubFlatObjectMetadataMaps({
objectMetadataIds,
flatObjectMetadataMaps,
});
@@ -1,42 +0,0 @@
import { isDefined } from 'twenty-shared/utils';
import { EMPTY_FLAT_OBJECT_METADATA_MAPS } from 'src/engine/metadata-modules/flat-object-metadata-maps/constant/empty-flat-object-metadata-maps.constant';
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';
import { addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-with-field-maps-to-flat-object-metadata-maps-or-throw.util';
export type ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs =
{
objectMetadataIds: string[];
flatObjectMetadataMaps: FlatObjectMetadataMaps;
};
export const extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow =
({
flatObjectMetadataMaps: sourceFlatObjectMetadataMaps,
objectMetadataIds,
}: ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs): FlatObjectMetadataMaps => {
return objectMetadataIds.reduce(
(flatObjectMetadataMaps, objectMetadataId) => {
const flatObjectMetadataWithFlatFieldMaps =
sourceFlatObjectMetadataMaps.byId[objectMetadataId];
if (!isDefined(flatObjectMetadataWithFlatFieldMaps)) {
throw new FlatObjectMetadataMapsException(
'extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow object metadata not found',
FlatObjectMetadataMapsExceptionCode.OBJECT_METADATA_NOT_FOUND,
);
}
return addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow(
{
flatObjectMetadataMaps,
flatObjectMetadataWithFlatFieldMaps,
},
);
},
EMPTY_FLAT_OBJECT_METADATA_MAPS,
);
};
@@ -1,17 +0,0 @@
import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
import {
type ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs,
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow,
} from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/extract-flat-object-metadata-maps-out-of-flat-object-metadata-maps-or-throw.util';
export const extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps = (
args: ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs,
): FlatObjectMetadataMaps | undefined => {
try {
return extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow(
args,
);
} catch {
return undefined;
}
};
@@ -0,0 +1,40 @@
import { isDefined } from 'twenty-shared/utils';
import { EMPTY_FLAT_OBJECT_METADATA_MAPS } from 'src/engine/metadata-modules/flat-object-metadata-maps/constant/empty-flat-object-metadata-maps.constant';
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';
import { addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-with-field-maps-to-flat-object-metadata-maps-or-throw.util';
export type GetSubFlatObjectMetadataMapsOrThrowArgs = {
objectMetadataIds: string[];
flatObjectMetadataMaps: FlatObjectMetadataMaps;
};
export const getSubFlatObjectMetadataMapsOrThrow = ({
flatObjectMetadataMaps: sourceFlatObjectMetadataMaps,
objectMetadataIds,
}: GetSubFlatObjectMetadataMapsOrThrowArgs): FlatObjectMetadataMaps => {
return objectMetadataIds.reduce(
(flatObjectMetadataMaps, objectMetadataId) => {
const flatObjectMetadataWithFlatFieldMaps =
sourceFlatObjectMetadataMaps.byId[objectMetadataId];
if (!isDefined(flatObjectMetadataWithFlatFieldMaps)) {
throw new FlatObjectMetadataMapsException(
'getSubFlatObjectMetadataMapsOrThrow object metadata not found',
FlatObjectMetadataMapsExceptionCode.OBJECT_METADATA_NOT_FOUND,
);
}
return addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow(
{
flatObjectMetadataMaps,
flatObjectMetadataWithFlatFieldMaps,
},
);
},
EMPTY_FLAT_OBJECT_METADATA_MAPS,
);
};
@@ -0,0 +1,15 @@
import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
import {
getSubFlatObjectMetadataMapsOrThrow,
type GetSubFlatObjectMetadataMapsOrThrowArgs,
} from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/get-sub-flat-object-metadata-maps-or-throw.util';
export const getSubFlatObjectMetadataMaps = (
args: GetSubFlatObjectMetadataMapsOrThrowArgs,
): FlatObjectMetadataMaps | undefined => {
try {
return getSubFlatObjectMetadataMapsOrThrow(args);
} catch {
return undefined;
}
};