Refactor morph field name and morph data loader (#14299)
# Introduction Storing morph relation field names directly in database, using morphId to aggregate them Removing dynamic morph field metadata computation in schemas and data loader Will add integration tests on morph data loader entry closes https://github.com/twentyhq/core-team-issues/issues/1425 closes https://github.com/twentyhq/core-team-issues/issues/1424 closes https://github.com/twentyhq/core-team-issues/issues/1423
This commit is contained in:
+56
@@ -0,0 +1,56 @@
|
||||
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 { isFlatFieldMetadataOfType } 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 FindAllMorphRelationFlatFieldMetadatasOrThrowArgs = {
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
flatFieldMetadata: FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>;
|
||||
};
|
||||
export const findAllOthersMorphRelationFlatFieldMetadatasOrThrow = ({
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadata: morphRelationFlatFieldMetadata,
|
||||
}: FindAllMorphRelationFlatFieldMetadatasOrThrowArgs): FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>[] => {
|
||||
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.filter(
|
||||
(
|
||||
flatFieldMetadata,
|
||||
): flatFieldMetadata is FlatFieldMetadata<FieldMetadataType.MORPH_RELATION> =>
|
||||
isFlatFieldMetadataOfType(
|
||||
flatFieldMetadata,
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
) &&
|
||||
flatFieldMetadata.morphId === morphRelationFlatFieldMetadata.morphId &&
|
||||
flatFieldMetadata.id !== morphRelationFlatFieldMetadata.id,
|
||||
);
|
||||
};
|
||||
+21
-54
@@ -1,14 +1,9 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { type MorphOrRelationFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/types/morph-or-relation-field-metadata-type.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { findAllOthersMorphRelationFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-all-others-morph-relation-flat-field-metadatas-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 { isFlatFieldMetadataOfType } 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 = {
|
||||
@@ -19,54 +14,26 @@ export const findFlatFieldMetadatasRelatedToMorphRelationOrThrow = ({
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadata: morphRelationFlatFieldMetadata,
|
||||
}: FindFlatFieldMetadatasRelatedToMorphRelationOrThrowArgs): FlatFieldMetadata<MorphOrRelationFieldMetadataType>[] => {
|
||||
const flatObjectMetadataWithFlatFieldMaps =
|
||||
flatObjectMetadataMaps.byId[
|
||||
morphRelationFlatFieldMetadata.objectMetadataId
|
||||
];
|
||||
const allMorphFlatFieldMetadatas =
|
||||
findAllOthersMorphRelationFlatFieldMetadatasOrThrow({
|
||||
flatFieldMetadata: morphRelationFlatFieldMetadata,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatObjectMetadataWithFlatFieldMaps)) {
|
||||
throw new FlatObjectMetadataMapsException(
|
||||
'Morph field relation object metadata not found',
|
||||
FlatObjectMetadataMapsExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
return [
|
||||
morphRelationFlatFieldMetadata,
|
||||
...allMorphFlatFieldMetadatas,
|
||||
].flatMap((flatFieldMetadata) => {
|
||||
const relationTargetFlatFieldMetadata =
|
||||
findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow({
|
||||
flatFieldMetadata,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
if (
|
||||
!isDefined(
|
||||
flatObjectMetadataWithFlatFieldMaps.fieldsById[
|
||||
morphRelationFlatFieldMetadata.id
|
||||
],
|
||||
)
|
||||
) {
|
||||
throw new FlatObjectMetadataMapsException(
|
||||
'Morph relation field not found in related object metadata',
|
||||
FlatObjectMetadataMapsExceptionCode.FIELD_METADATA_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
if (flatFieldMetadata.id === morphRelationFlatFieldMetadata.id) {
|
||||
return [relationTargetFlatFieldMetadata];
|
||||
}
|
||||
|
||||
return flatObjectMetadataWithFlatFieldMaps.flatFieldMetadatas.flatMap(
|
||||
(flatFieldMetadata) => {
|
||||
if (
|
||||
!isFlatFieldMetadataOfType(
|
||||
flatFieldMetadata,
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
) ||
|
||||
flatFieldMetadata.name !== morphRelationFlatFieldMetadata.name
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const relationTargetFlatFieldMetadata =
|
||||
findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow({
|
||||
flatFieldMetadata,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
if (flatFieldMetadata.id === morphRelationFlatFieldMetadata.id) {
|
||||
return [relationTargetFlatFieldMetadata];
|
||||
}
|
||||
|
||||
return [flatFieldMetadata, relationTargetFlatFieldMetadata];
|
||||
},
|
||||
);
|
||||
return [flatFieldMetadata, relationTargetFlatFieldMetadata];
|
||||
});
|
||||
};
|
||||
|
||||
+28
-3
@@ -1,8 +1,9 @@
|
||||
import { type FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatRelationTargetFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-relation-target-field-metadata.type';
|
||||
|
||||
export const fromFlatFieldMetadataToFieldMetadataDto = (
|
||||
flatFieldMetadata: FlatFieldMetadata,
|
||||
flatFieldMetadata: FlatFieldMetadata | FlatRelationTargetFieldMetadata,
|
||||
): FieldMetadataDTO => {
|
||||
const {
|
||||
createdAt,
|
||||
@@ -13,11 +14,35 @@ export const fromFlatFieldMetadataToFieldMetadataDto = (
|
||||
isNullable,
|
||||
isUnique,
|
||||
settings,
|
||||
...rest
|
||||
id,
|
||||
label,
|
||||
name,
|
||||
objectMetadataId,
|
||||
type,
|
||||
workspaceId,
|
||||
defaultValue,
|
||||
isActive,
|
||||
isCustom,
|
||||
isLabelSyncedWithName,
|
||||
isSystem,
|
||||
isUIReadOnly,
|
||||
options,
|
||||
} = flatFieldMetadata;
|
||||
|
||||
return {
|
||||
...rest,
|
||||
id,
|
||||
label,
|
||||
name,
|
||||
objectMetadataId,
|
||||
type,
|
||||
workspaceId,
|
||||
defaultValue,
|
||||
isActive,
|
||||
isCustom,
|
||||
isLabelSyncedWithName,
|
||||
isSystem,
|
||||
isUIReadOnly,
|
||||
options,
|
||||
createdAt: new Date(createdAt),
|
||||
updatedAt: new Date(updatedAt),
|
||||
description: description ?? undefined,
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
import { type MorphOrRelationFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/types/morph-or-relation-field-metadata-type.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { fromFlatFieldMetadataToFieldMetadataDto } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-flat-field-metadata-to-field-metadata-dto.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { fromFlatObjectMetadataToObjectMetadataDto } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-to-object-metadata-dto.util';
|
||||
|
||||
export const fromMorphOrRelationFlatFieldMetadataToRelationDto = ({
|
||||
flatFieldMetadata,
|
||||
sourceFlatObjectMetadata,
|
||||
}: {
|
||||
sourceFlatObjectMetadata: FlatObjectMetadata;
|
||||
flatFieldMetadata: FlatFieldMetadata<MorphOrRelationFieldMetadataType>;
|
||||
}) => ({
|
||||
type: flatFieldMetadata.settings.relationType,
|
||||
sourceObjectMetadata: fromFlatObjectMetadataToObjectMetadataDto(
|
||||
sourceFlatObjectMetadata,
|
||||
),
|
||||
sourceFieldMetadata:
|
||||
fromFlatFieldMetadataToFieldMetadataDto(flatFieldMetadata),
|
||||
targetObjectMetadata: fromFlatObjectMetadataToObjectMetadataDto(
|
||||
flatFieldMetadata.flatRelationTargetObjectMetadata,
|
||||
),
|
||||
targetFieldMetadata: fromFlatFieldMetadataToFieldMetadataDto(
|
||||
flatFieldMetadata.flatRelationTargetFieldMetadata,
|
||||
),
|
||||
});
|
||||
+11
-8
@@ -1,14 +1,13 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
import {
|
||||
computeMorphRelationFieldJoinColumnName,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
|
||||
import { type MorphOrRelationFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/types/morph-or-relation-field-metadata-type.type';
|
||||
import { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.util';
|
||||
import { computeMorphRelationFieldName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-relation-field-name.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 { generateMorphOrRelationFlatFieldMetadataPair } from 'src/engine/metadata-modules/flat-field-metadata/utils/generate-morph-or-relation-flat-field-metadata-pair.util';
|
||||
@@ -68,17 +67,21 @@ export const fromMorphRelationCreateFieldInputToFlatFieldMetadatas = async ({
|
||||
const morphId = v4();
|
||||
const flatFieldMetadatas = morphRelationCreationPayload.flatMap(
|
||||
({ relationCreationPayload, targetFlatObjectMetadata }) => {
|
||||
const currentMorphRelationFieldName = computeMorphRelationFieldName({
|
||||
fieldName: createFieldInput.name,
|
||||
relationType: relationCreationPayload.type,
|
||||
targetObjectMetadata: targetFlatObjectMetadata,
|
||||
});
|
||||
const sourceFlatObjectMetadataJoinColumnName =
|
||||
computeMorphRelationFieldJoinColumnName({
|
||||
name: createFieldInput.name,
|
||||
targetObjectMetadataNameSingular:
|
||||
targetFlatObjectMetadata.nameSingular,
|
||||
computeMorphOrRelationFieldJoinColumnName({
|
||||
name: currentMorphRelationFieldName,
|
||||
});
|
||||
|
||||
return generateMorphOrRelationFlatFieldMetadataPair({
|
||||
createFieldInput: {
|
||||
...createFieldInput,
|
||||
relationCreationPayload,
|
||||
name: currentMorphRelationFieldName,
|
||||
},
|
||||
sourceFlatObjectMetadataJoinColumnName,
|
||||
sourceFlatObjectMetadata,
|
||||
|
||||
+5
-4
@@ -4,7 +4,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { FieldMetadataExceptionCode } 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 { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.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 { generateMorphOrRelationFlatFieldMetadataPair } from 'src/engine/metadata-modules/flat-field-metadata/utils/generate-morph-or-relation-flat-field-metadata-pair.util';
|
||||
@@ -58,9 +58,10 @@ export const fromRelationCreateFieldInputToFlatFieldMetadatas = async ({
|
||||
...createFieldInput,
|
||||
relationCreationPayload,
|
||||
},
|
||||
sourceFlatObjectMetadataJoinColumnName: computeRelationFieldJoinColumnName({
|
||||
name: createFieldInput.name,
|
||||
}),
|
||||
sourceFlatObjectMetadataJoinColumnName:
|
||||
computeMorphOrRelationFieldJoinColumnName({
|
||||
name: createFieldInput.name,
|
||||
}),
|
||||
sourceFlatObjectMetadata,
|
||||
targetFlatObjectMetadata,
|
||||
workspaceId,
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ import { v4 } from 'uuid';
|
||||
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { type MorphOrRelationFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/types/morph-or-relation-field-metadata-type.type';
|
||||
import { computeRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-relation-field-join-column-name.util';
|
||||
import { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.util';
|
||||
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 FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
@@ -92,7 +92,7 @@ export const generateMorphOrRelationFlatFieldMetadataPair = ({
|
||||
};
|
||||
const targetFlatFieldMetadataSettings =
|
||||
computeFieldMetadataRelationSettingsForRelationType({
|
||||
joinColumnName: computeRelationFieldJoinColumnName({
|
||||
joinColumnName: computeMorphOrRelationFieldJoinColumnName({
|
||||
name: targetCreateFieldInput.name,
|
||||
}),
|
||||
relationType:
|
||||
|
||||
Reference in New Issue
Block a user