Extract field metadata build out of object metadata build (#14763)

# Introduction

Extracting the legacy fields build and dispatch out of the object one to
follow the generic flat entity build, also update caches entries for
object

## Main tasks
- flat field map cache
- flat field builder
- refactored the dispatch matrix to return flat entity maps instead of
flat entity arrays
- orchestrator aggregator
- removing legacy code
- making universal identifier aka standardId of standard field for
custom object deterministically dynamic
- perfs debug logs for v2

## TODO
- [x] Refactor the generic entity builder to be dependency flat maps in
order to main foreign keys list in flat parent
- [x] Refactor the flat object metadata to contain the array of related
fields and avoid costy find object fields
- [ ] Improve the create field handler to handle multiple field at once
- [ ] Refactor the dispatch to embbed the comparison
- [ ] Improve perf by extracting from elements out of existing
- [ ] Fix the labelIdentifierId validators on object before field
creation ( integ tests are in failing mode )

## Debug logs snippet

```ts
[EntityBuilder fieldMetadata] matrix computation: 0.027ms
[EntityBuilder fieldMetadata] creation validation: 0.001ms
[EntityBuilder fieldMetadata] deletion validation: 0.293ms
[EntityBuilder fieldMetadata] update validation: 0.006ms
[EntityBuilder fieldMetadata] entity processing: 0.363ms
[EntityBuilder fieldMetadata] validateAndBuild: 0.455ms
[EntityBuilder index] matrix computation: 0.005ms
[EntityBuilder index] creation validation: 0.001ms
[EntityBuilder index] deletion validation: 0.146ms
[EntityBuilder index] update validation: 0.004ms
[EntityBuilder index] entity processing: 0.199ms
[EntityBuilder index] validateAndBuild: 0.228ms
[Runner] Initial cache retrieval: 0.549ms
[BaseWorkspaceMigrationRunnerActionHandlerService] delete_index executeForWorkspaceSchema: 11.665ms
[BaseWorkspaceMigrationRunnerActionHandlerService] delete_index executeForMetadata: 12.864ms
[BaseWorkspaceMigrationRunnerActionHandlerService] delete_field executeForWorkspaceSchema: 1.476ms
[BaseWorkspaceMigrationRunnerActionHandlerService] delete_field executeForMetadata: 6.816ms
[BaseWorkspaceMigrationRunnerActionHandlerService] delete_field executeForWorkspaceSchema: 0.062ms
[BaseWorkspaceMigrationRunnerActionHandlerService] delete_field executeForMetadata: 0.889ms
[Runner] Transaction execution: 23.434ms
[Runner] Cache invalidation: 316.662ms
[Runner] Total execution: 340.767ms
```
As you can see cache invalidation is way to long, we could replace the
cache by the optimistic in the end
This commit is contained in:
Paul Rastoin
2025-10-02 18:07:34 +02:00
committed by GitHub
parent d4b83df3f5
commit 170f6d27c5
240 changed files with 11385 additions and 17744 deletions
@@ -1,17 +1,20 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
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 { isFlatFieldMetadataOfType } 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';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
export const computeFlatFieldMetadataRelatedFlatFieldMetadata = ({
flatFieldMetadata,
flatObjectMetadataMaps,
flatObjectMetadata,
flatFieldMetadataMaps,
}: {
flatObjectMetadata: FlatObjectMetadata;
flatFieldMetadata: FlatFieldMetadata;
flatObjectMetadataMaps: FlatObjectMetadataMaps;
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
}): FlatFieldMetadata[] => {
if (
isFlatFieldMetadataOfType(flatFieldMetadata, FieldMetadataType.RELATION)
@@ -19,7 +22,7 @@ export const computeFlatFieldMetadataRelatedFlatFieldMetadata = ({
return [
findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow({
flatFieldMetadata,
flatObjectMetadataMaps,
flatFieldMetadataMaps,
}),
];
}
@@ -32,7 +35,8 @@ export const computeFlatFieldMetadataRelatedFlatFieldMetadata = ({
) {
return findFlatFieldMetadatasRelatedToMorphRelationOrThrow({
flatFieldMetadata,
flatObjectMetadataMaps,
flatFieldMetadataMaps,
flatObjectMetadata,
});
}
@@ -1,48 +1,42 @@
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';
FlatEntityMapsException,
FlatEntityMapsExceptionCode,
} from 'src/engine/core-modules/common/exceptions/flat-entity-maps.exception';
import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { findObjectFieldsInFlatFieldMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util';
import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
export type FindAllMorphRelationFlatFieldMetadatasOrThrowArgs = {
flatObjectMetadataMaps: FlatObjectMetadataMaps;
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
flatFieldMetadata: FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>;
flatObjectMetadata: FlatObjectMetadata;
};
export const findAllOthersMorphRelationFlatFieldMetadatasOrThrow = ({
flatObjectMetadataMaps,
flatFieldMetadataMaps,
flatObjectMetadata,
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
],
)
!isDefined(flatFieldMetadataMaps.byId[morphRelationFlatFieldMetadata.id])
) {
throw new FlatObjectMetadataMapsException(
'Morph relation field not found in related object metadata',
FlatObjectMetadataMapsExceptionCode.FIELD_METADATA_NOT_FOUND,
throw new FlatEntityMapsException(
'Morph relation field not found in flat field metadata maps',
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
);
}
return flatObjectMetadataWithFlatFieldMaps.flatFieldMetadatas.filter(
const { objectFlatFieldMetadatas } =
findObjectFieldsInFlatFieldMetadataMapsOrThrow({
flatFieldMetadataMaps,
flatObjectMetadata,
});
return objectFlatFieldMetadatas.filter(
(
flatFieldMetadata,
): flatFieldMetadata is FlatFieldMetadata<FieldMetadataType.MORPH_RELATION> =>
@@ -1,23 +1,27 @@
import { type FieldMetadataType } from 'twenty-shared/types';
import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
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 { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
export type FindFlatFieldMetadatasRelatedToMorphRelationOrThrowArgs = {
flatObjectMetadataMaps: FlatObjectMetadataMaps;
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
flatFieldMetadata: FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>;
flatObjectMetadata: FlatObjectMetadata;
};
export const findFlatFieldMetadatasRelatedToMorphRelationOrThrow = ({
flatObjectMetadataMaps,
flatFieldMetadataMaps,
flatFieldMetadata: morphRelationFlatFieldMetadata,
flatObjectMetadata,
}: FindFlatFieldMetadatasRelatedToMorphRelationOrThrowArgs): FlatFieldMetadata<MorphOrRelationFieldMetadataType>[] => {
const allMorphFlatFieldMetadatas =
findAllOthersMorphRelationFlatFieldMetadatasOrThrow({
flatFieldMetadata: morphRelationFlatFieldMetadata,
flatObjectMetadataMaps,
flatFieldMetadataMaps,
flatObjectMetadata,
});
return [
@@ -27,7 +31,7 @@ export const findFlatFieldMetadatasRelatedToMorphRelationOrThrow = ({
const relationTargetFlatFieldMetadata =
findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow({
flatFieldMetadata,
flatObjectMetadataMaps,
flatFieldMetadataMaps,
});
if (flatFieldMetadata.id === morphRelationFlatFieldMetadata.id) {
@@ -0,0 +1,32 @@
import { isDefined } from 'twenty-shared/utils';
import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
import { getSubFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/get-sub-flat-entity-maps-or-throw.util';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
type FindObjectFieldsInFlatFieldMetadataMapsArgs = {
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
flatObjectMetadata: FlatObjectMetadata;
};
export const findObjectFieldsInFlatFieldMetadataMapsOrThrow = ({
flatFieldMetadataMaps,
flatObjectMetadata,
}: FindObjectFieldsInFlatFieldMetadataMapsArgs): {
objectFlatFieldMetadataById: FlatEntityMaps<FlatFieldMetadata>;
objectFlatFieldMetadatas: FlatFieldMetadata[];
} => {
const objectFlatFieldMetadataById = getSubFlatEntityMapsOrThrow({
flatEntityIds: flatObjectMetadata.fieldMetadataIds,
flatEntityMaps: flatFieldMetadataMaps,
});
const objectFlatFieldMetadatas = Object.values(
objectFlatFieldMetadataById.byId,
).filter(isDefined);
return {
objectFlatFieldMetadataById,
objectFlatFieldMetadatas,
};
};
@@ -1,5 +1,6 @@
import { isDefined } from 'twenty-shared/utils';
import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
import {
FieldMetadataException,
FieldMetadataExceptionCode,
@@ -7,31 +8,20 @@ import {
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 { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
export type GetRelationFlatFieldMetadatasUtilArgs = {
flatObjectMetadataMaps: FlatObjectMetadataMaps;
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>;
flatFieldMetadata: FlatFieldMetadata<MorphOrRelationFieldMetadataType>;
};
export const findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow = ({
flatObjectMetadataMaps,
flatFieldMetadataMaps,
flatFieldMetadata,
}: GetRelationFlatFieldMetadatasUtilArgs): FlatFieldMetadata<MorphOrRelationFieldMetadataType> => {
const { relationTargetFieldMetadataId, relationTargetObjectMetadataId } =
flatFieldMetadata;
const { relationTargetFieldMetadataId } = flatFieldMetadata;
const relatedFlatObjectMetadata =
flatObjectMetadataMaps.byId[relationTargetObjectMetadataId];
if (!isDefined(relatedFlatObjectMetadata)) {
throw new FieldMetadataException(
`Deleted field metadata relation object metadata target not found`,
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
);
}
const relatedFlatFieldMetadata =
relatedFlatObjectMetadata.fieldsById[relationTargetFieldMetadataId];
flatFieldMetadataMaps.byId[relationTargetFieldMetadataId];
if (!isDefined(relatedFlatFieldMetadata)) {
throw new FieldMetadataException(
@@ -1,18 +0,0 @@
import {
findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow,
type GetRelationFlatFieldMetadatasUtilArgs,
} from 'src/engine/metadata-modules/flat-field-metadata/utils/find-relation-flat-field-metadatas-target-flat-field-metadata-or-throw.util';
export const findRelationFlatFieldMetadataTargetFlatFieldMetadata = (
args: GetRelationFlatFieldMetadatasUtilArgs,
):
| ReturnType<
typeof findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow
>
| undefined => {
try {
return findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow(args);
} catch {
return undefined;
}
};
@@ -9,6 +9,7 @@ import { v4 } from 'uuid';
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
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 { generateRatingOptions } from 'src/engine/metadata-modules/field-metadata/utils/generate-rating-optionts.util';
@@ -18,19 +19,16 @@ import { fromMorphRelationCreateFieldInputToFlatFieldMetadatas } from 'src/engin
import { fromRelationCreateFieldInputToFlatFieldMetadatas } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-relation-create-field-input-to-flat-field-metadatas.util';
import { getDefaultFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/get-default-flat-field-metadata-from-create-field-input.util';
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
import { fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-with-flat-field-maps-to-flat-object-metadatas.util';
type FromCreateFieldInputToFlatObjectMetadataArgs = {
rawCreateFieldInput: Omit<CreateFieldInput, 'workspaceId'>;
existingFlatObjectMetadataMaps: FlatObjectMetadataMaps;
export type FromCreateFieldInputToFlatObjectMetadataArgs = {
createFieldInput: Omit<CreateFieldInput, 'workspaceId'>;
workspaceId: string;
};
} & Pick<AllFlatEntityMaps, 'flatObjectMetadataMaps'>;
export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
rawCreateFieldInput,
createFieldInput: rawCreateFieldInput,
workspaceId,
existingFlatObjectMetadataMaps,
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
}: FromCreateFieldInputToFlatObjectMetadataArgs): Promise<
FieldInputTranspilationResult<{
flatFieldMetadatas: FlatFieldMetadata[];
@@ -46,15 +44,16 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
},
};
}
const createFieldInput =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
rawCreateFieldInput,
['description', 'icon', 'label', 'name', 'objectMetadataId', 'type'],
);
const parentFlatObjectMetadataWithFlatFieldMaps =
const parentFlatObjectMetadata =
existingFlatObjectMetadataMaps.byId[createFieldInput.objectMetadataId];
if (!isDefined(parentFlatObjectMetadataWithFlatFieldMaps)) {
if (!isDefined(parentFlatObjectMetadata)) {
return {
status: 'fail',
error: {
@@ -65,11 +64,6 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
};
}
const parentFlatObjectMetadata =
fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata(
parentFlatObjectMetadataWithFlatFieldMaps,
);
const fieldMetadataId = v4();
const commonFlatFieldMetadata = getDefaultFlatFieldMetadata({
createFieldInput,
@@ -3,7 +3,9 @@ import {
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties,
} from 'twenty-shared/utils';
import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
import { type DeleteOneFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/delete-field.input';
import {
FieldMetadataException,
@@ -11,22 +13,22 @@ import {
} 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 { computeFlatFieldMetadataRelatedFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/compute-flat-field-metadata-related-flat-field-metadata.util';
import { findObjectFieldsInFlatFieldMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util';
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
import { findFlatFieldMetadataInFlatObjectMetadataMapsWithOnlyFieldId } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/find-flat-field-metadata-in-flat-object-metadata-maps-with-field-id-only.util';
import { findFlatObjectMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/find-flat-object-metadata-in-flat-object-metadata-maps-or-throw.util';
import { generateFlatIndexMetadataWithNameOrThrow } from 'src/engine/metadata-modules/index-metadata/utils/generate-flat-index.util';
type FromDeleteFieldInputToFlatFieldMetadatasToDeleteArgs = {
existingFlatObjectMetadataMaps: FlatObjectMetadataMaps;
existingFlatIndexMaps: FlatEntityMaps<FlatIndexMetadata>;
deleteOneFieldInput: DeleteOneFieldInput;
};
} & Pick<
AllFlatEntityMaps,
'flatFieldMetadataMaps' | 'flatIndexMaps' | 'flatObjectMetadataMaps'
>;
// TODO refactor as a side effect service
export const fromDeleteFieldInputToFlatFieldMetadatasToDelete = ({
existingFlatObjectMetadataMaps,
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
deleteOneFieldInput: rawDeleteOneInput,
existingFlatIndexMaps,
flatIndexMaps: existingFlatIndexMaps,
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
}: FromDeleteFieldInputToFlatFieldMetadatasToDeleteArgs): {
flatFieldMetadatasToDelete: FlatFieldMetadata[];
flatIndexesToUpdate: FlatIndexMetadata[];
@@ -38,11 +40,10 @@ export const fromDeleteFieldInputToFlatFieldMetadatasToDelete = ({
['id'],
);
const flatFieldMetadataToDelete =
findFlatFieldMetadataInFlatObjectMetadataMapsWithOnlyFieldId({
fieldMetadataId: fieldMetadataToDeleteId,
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
});
const flatFieldMetadataToDelete = findFlatEntityByIdInFlatEntityMaps({
flatEntityId: fieldMetadataToDeleteId,
flatEntityMaps: existingFlatFieldMetadataMaps,
});
if (!isDefined(flatFieldMetadataToDelete)) {
throw new FieldMetadataException(
@@ -51,10 +52,23 @@ export const fromDeleteFieldInputToFlatFieldMetadatasToDelete = ({
);
}
const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({
flatEntityId: flatFieldMetadataToDelete.objectMetadataId,
flatEntityMaps: existingFlatObjectMetadataMaps,
});
if (!isDefined(flatObjectMetadata)) {
throw new FieldMetadataException(
'Field to delete object metadata not found',
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
);
}
const relatedFlatFieldMetadataToDelete =
computeFlatFieldMetadataRelatedFlatFieldMetadata({
flatFieldMetadata: flatFieldMetadataToDelete,
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
flatObjectMetadata,
});
const flatFieldMetadatasToDelete = [
@@ -122,15 +136,20 @@ export const fromDeleteFieldInputToFlatFieldMetadatasToDelete = ({
};
}
const flatObjectMetadata =
findFlatObjectMetadataInFlatObjectMetadataMapsOrThrow({
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
objectMetadataId: flatIndex.objectMetadataId,
const flatObjectMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityMaps: existingFlatObjectMetadataMaps,
flatEntityId: flatIndex.objectMetadataId,
});
const { objectFlatFieldMetadatas } =
findObjectFieldsInFlatFieldMetadataMapsOrThrow({
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
flatObjectMetadata,
});
const newIndex = generateFlatIndexMetadataWithNameOrThrow({
flatObjectMetadata,
flatIndex,
objectFlatFieldMetadatas,
});
return {
@@ -1,95 +1,18 @@
import {
FieldMetadataType,
type RelationAndMorphRelationFieldMetadataType,
} from 'twenty-shared/types';
import { type FieldMetadataType } from 'twenty-shared/types';
import { removePropertiesFromRecord } from 'twenty-shared/utils';
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import {
FieldMetadataException,
FieldMetadataExceptionCode,
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
import {
type FieldMetadataEntityRelationProperties,
type FlatFieldMetadata,
fieldMetadataRelationProperties,
} 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';
import { isFieldMetadataEntityOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
import { fromObjectMetadataEntityToFlatObjectMetadataWithoutFields } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/utils/from-object-metadata-entity-to-flat-object-metadata-without-fields.util';
export const fromFieldMetadataEntityToFlatRelationTargetFieldMetadata = (
fieldMetadataEntity: FieldMetadataEntity<RelationAndMorphRelationFieldMetadataType>,
): FlatRelationTargetFieldMetadata => {
return {
universalIdentifier:
fieldMetadataEntity.standardId ?? fieldMetadataEntity.id,
...removePropertiesFromRecord(fieldMetadataEntity, [
'relationTargetObjectMetadata',
'relationTargetFieldMetadata',
]),
};
};
// TODO refactor this method should not be recursive but depth 1
export const fromFieldMetadataEntityToFlatFieldMetadata = <
T extends FieldMetadataType,
>(
fieldMetadataEntity: FieldMetadataEntity<T>,
// This is intended to be abstract
): FlatFieldMetadata => {
if (
isFieldMetadataEntityOfType(
fieldMetadataEntity,
FieldMetadataType.RELATION,
) ||
isFieldMetadataEntityOfType(
fieldMetadataEntity,
FieldMetadataType.MORPH_RELATION,
)
) {
const fieldMetadataWithoutRelations = removePropertiesFromRecord<
FieldMetadataEntity<
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
>,
FieldMetadataEntityRelationProperties
>(fieldMetadataEntity, fieldMetadataRelationProperties);
if (
!isFieldMetadataEntityOfType(
fieldMetadataEntity.relationTargetFieldMetadata,
FieldMetadataType.RELATION,
)
) {
throw new FieldMetadataException(
'Relation target field is not a field metadata type relation',
FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED,
);
}
const flatRelationTargetFieldMetadata =
fromFieldMetadataEntityToFlatRelationTargetFieldMetadata(
fieldMetadataEntity.relationTargetFieldMetadata,
);
const flatRelationTargetObjectMetadata =
fromObjectMetadataEntityToFlatObjectMetadataWithoutFields(
fieldMetadataEntity.relationTargetObjectMetadata,
);
return {
...fieldMetadataWithoutRelations,
universalIdentifier:
fieldMetadataWithoutRelations.standardId ??
fieldMetadataWithoutRelations.id,
flatRelationTargetFieldMetadata,
flatRelationTargetObjectMetadata,
type: fieldMetadataEntity.type,
} satisfies FlatFieldMetadata<
FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION
>;
}
const fieldMetadataWithoutRelations = removePropertiesFromRecord(
fieldMetadataEntity,
fieldMetadataRelationProperties,
@@ -100,7 +23,5 @@ export const fromFieldMetadataEntityToFlatFieldMetadata = <
universalIdentifier:
fieldMetadataWithoutRelations.standardId ??
fieldMetadataWithoutRelations.id,
flatRelationTargetFieldMetadata: null,
flatRelationTargetObjectMetadata: null,
};
};
@@ -1,9 +1,8 @@
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 | FlatRelationTargetFieldMetadata,
flatFieldMetadata: FlatFieldMetadata,
): FieldMetadataDTO => {
const {
createdAt,
@@ -1,42 +0,0 @@
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { type FlatObjectMetadataWithFlatFieldMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-with-flat-field-metadata-maps.type';
import { fromObjectMetadataItemWithFieldMapsToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-item-with-field-maps-to-flat-object-metadata.util';
import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { type ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
export type FromObjectMetadataItemWithFieldMapsToFlatObjectWithFlatFieldMetadataMapsArgs =
{
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps;
objectMetadataMaps: ObjectMetadataMaps;
};
export const fromObjectMetadataItemWithFieldMapsToFlatObjectWithFlatFieldMetadataMaps =
({
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
}: FromObjectMetadataItemWithFieldMapsToFlatObjectWithFlatFieldMetadataMapsArgs): FlatObjectMetadataWithFlatFieldMaps => {
const flatObjectMetadata =
fromObjectMetadataItemWithFieldMapsToFlatObjectMetadata({
objectMetadataItemWithFieldMaps,
objectMetadataMaps,
});
const initialAccumulator: Record<string, FlatFieldMetadata> = {};
const fieldsById = flatObjectMetadata.flatFieldMetadatas.reduce(
(acc, flatFieldMetadata) => ({
...acc,
[flatFieldMetadata.id]: flatFieldMetadata,
}),
initialAccumulator,
);
const { fieldIdByJoinColumnName, fieldIdByName } =
objectMetadataItemWithFieldMaps;
return {
...flatObjectMetadata,
fieldsById,
fieldIdByJoinColumnName,
fieldIdByName,
};
};
@@ -4,23 +4,29 @@ import { fromFlatFieldMetadataToFieldMetadataDto } from 'src/engine/metadata-mod
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,
}: {
type FromMorphOrRelationFlatFieldMetadataToRelationDtoArgs = {
sourceFlatObjectMetadata: FlatObjectMetadata;
flatFieldMetadata: FlatFieldMetadata<MorphOrRelationFieldMetadataType>;
}) => ({
type: flatFieldMetadata.settings.relationType,
targetFlatObjectMetadata: FlatObjectMetadata;
sourceFlatFieldMetadata: FlatFieldMetadata<MorphOrRelationFieldMetadataType>;
targetFlatFieldMetadata: FlatFieldMetadata<MorphOrRelationFieldMetadataType>;
};
export const fromMorphOrRelationFlatFieldMetadataToRelationDto = ({
sourceFlatFieldMetadata,
sourceFlatObjectMetadata,
targetFlatFieldMetadata,
targetFlatObjectMetadata,
}: FromMorphOrRelationFlatFieldMetadataToRelationDtoArgs) => ({
type: sourceFlatFieldMetadata.settings.relationType,
sourceObjectMetadata: fromFlatObjectMetadataToObjectMetadataDto(
sourceFlatObjectMetadata,
),
sourceFieldMetadata:
fromFlatFieldMetadataToFieldMetadataDto(flatFieldMetadata),
sourceFieldMetadata: fromFlatFieldMetadataToFieldMetadataDto(
sourceFlatFieldMetadata,
),
targetObjectMetadata: fromFlatObjectMetadataToObjectMetadataDto(
flatFieldMetadata.flatRelationTargetObjectMetadata,
targetFlatObjectMetadata,
),
targetFieldMetadata: fromFlatFieldMetadataToFieldMetadataDto(
flatFieldMetadata.flatRelationTargetFieldMetadata,
targetFlatFieldMetadata,
),
});
@@ -3,6 +3,7 @@ import { type FieldMetadataType } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
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 { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.util';
@@ -12,14 +13,13 @@ import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-m
import { generateMorphOrRelationFlatFieldMetadataPair } from 'src/engine/metadata-modules/flat-field-metadata/utils/generate-morph-or-relation-flat-field-metadata-pair.util';
import { validateMorphRelationCreationPayload } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-morph-relation-creation-payload.util';
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
import { type FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
type FromMorphRelationCreateFieldInputToFlatFieldMetadatasArgs = {
createFieldInput: Omit<CreateFieldInput, 'workspaceId'> & {
type: FieldMetadataType.MORPH_RELATION;
};
existingFlatObjectMetadataMaps: FlatObjectMetadataMaps;
existingFlatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
sourceFlatObjectMetadata: FlatObjectMetadata;
workspaceId: string;
};
@@ -2,6 +2,7 @@ import { t } from '@lingui/core/macro';
import { type FieldMetadataType } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
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 { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.util';
@@ -11,14 +12,13 @@ import {
type SourceTargetMorphOrRelationFlatFieldAndFlatIndex,
} from 'src/engine/metadata-modules/flat-field-metadata/utils/generate-morph-or-relation-flat-field-metadata-pair.util';
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';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
type FromRelationCreateFieldInputToFlatFieldMetadataArgs = {
createFieldInput: Omit<CreateFieldInput, 'workspaceId'> & {
type: FieldMetadataType.RELATION;
};
existingFlatObjectMetadataMaps: FlatObjectMetadataMaps;
existingFlatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
sourceFlatObjectMetadata: FlatObjectMetadata;
workspaceId: string;
};
@@ -6,9 +6,14 @@ import {
import { v4 } from 'uuid';
import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
import { FIELD_METADATA_STANDARD_OVERRIDES_PROPERTIES } from 'src/engine/metadata-modules/field-metadata/constants/field-metadata-standard-overrides-properties.constant';
import { type UpdateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/update-field.input';
import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
import {
FieldMetadataException,
FieldMetadataExceptionCode,
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
import { type FieldMetadataStandardOverridesProperties } from 'src/engine/metadata-modules/field-metadata/types/field-metadata-standard-overrides-properties.type';
import { FLAT_FIELD_METADATA_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-field-metadata/constants/flat-field-metadata-editable-properties.constant';
import { type FieldInputTranspilationResult } from 'src/engine/metadata-modules/flat-field-metadata/types/field-input-transpilation-result.type';
@@ -17,9 +22,6 @@ import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-m
import { computeFlatFieldMetadataRelatedFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/compute-flat-field-metadata-related-flat-field-metadata.util';
import { recomputeIndexOnFlatFieldMetadataNameUpdate } from 'src/engine/metadata-modules/flat-field-metadata/utils/recompute-index-on-flat-field-metadata-name-update.util';
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
import { findFlatFieldMetadataInFlatObjectMetadataMapsWithOnlyFieldId } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/find-flat-field-metadata-in-flat-object-metadata-maps-with-field-id-only.util';
import { findFlatObjectMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/find-flat-object-metadata-in-flat-object-metadata-maps-or-throw.util';
import { fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-with-flat-field-maps-to-flat-object-metadatas.util';
import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
type UpdatedFlatFieldMetadataAndIndexToUpdate = {
@@ -37,13 +39,17 @@ type SanitizedUpdateFieldInput = ReturnType<
type ApplyUpdatesToFlatFieldMetadataArgs = {
updatedEditableFieldProperties: SanitizedUpdateFieldInput;
fromFlatFieldMetadata: FlatFieldMetadata;
} & Pick<AllFlatEntityMaps, 'flatIndexMaps' | 'flatObjectMetadataMaps'>;
} & Pick<
AllFlatEntityMaps,
'flatIndexMaps' | 'flatObjectMetadataMaps' | 'flatFieldMetadataMaps'
>;
const applyUpdatesToFlatFieldMetadata = ({
updatedEditableFieldProperties,
fromFlatFieldMetadata,
flatObjectMetadataMaps,
flatIndexMaps,
flatFieldMetadataMaps,
}: ApplyUpdatesToFlatFieldMetadataArgs) => {
return FLAT_FIELD_METADATA_EDITABLE_PROPERTIES.reduce<UpdatedFlatFieldMetadataAndIndexToUpdate>(
({ flatFieldMetadata, flatIndexMetadataToUpdate }, property) => {
@@ -74,14 +80,14 @@ const applyUpdatesToFlatFieldMetadata = ({
let newFlatIndexMetadataToUpdate: FlatIndexMetadata[] = [];
if (property === 'name') {
const flatObjectMetadata =
findFlatObjectMetadataInFlatObjectMetadataMapsOrThrow({
flatObjectMetadataMaps,
objectMetadataId: flatFieldMetadata.objectMetadataId,
});
const flatObjectMetadata = findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityMaps: flatObjectMetadataMaps,
flatEntityId: flatFieldMetadata.objectMetadataId,
});
newFlatIndexMetadataToUpdate =
recomputeIndexOnFlatFieldMetadataNameUpdate({
flatFieldMetadataMaps,
flatObjectMetadata,
fromFlatFieldMetadata,
toFlatFieldMetadata: {
@@ -108,7 +114,10 @@ const applyUpdatesToFlatFieldMetadata = ({
type FromUpdateFieldInputToFlatFieldMetadataArgs = {
updateFieldInput: UpdateFieldInput;
} & Pick<AllFlatEntityMaps, 'flatObjectMetadataMaps' | 'flatIndexMaps'>;
} & Pick<
AllFlatEntityMaps,
'flatObjectMetadataMaps' | 'flatIndexMaps' | 'flatFieldMetadataMaps'
>;
type FlatFieldMetadataAndIndexToUpdate = {
flatFieldMetadatasToUpdate: FlatFieldMetadata[];
@@ -117,6 +126,7 @@ type FlatFieldMetadataAndIndexToUpdate = {
export const fromUpdateFieldInputToFlatFieldMetadata = ({
flatIndexMaps,
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
flatFieldMetadataMaps,
updateFieldInput: rawUpdateFieldInput,
}: FromUpdateFieldInputToFlatFieldMetadataArgs): FieldInputTranspilationResult<FlatFieldMetadataAndIndexToUpdate> => {
const updateFieldInputInformalProperties =
@@ -129,11 +139,10 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
FLAT_FIELD_METADATA_EDITABLE_PROPERTIES,
);
const existingFlatFieldMetadataToUpdate =
findFlatFieldMetadataInFlatObjectMetadataMapsWithOnlyFieldId({
fieldMetadataId: updateFieldInputInformalProperties.id,
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
});
const existingFlatFieldMetadataToUpdate = findFlatEntityByIdInFlatEntityMaps({
flatEntityId: updateFieldInputInformalProperties.id,
flatEntityMaps: flatFieldMetadataMaps,
});
if (!isDefined(existingFlatFieldMetadataToUpdate)) {
return {
@@ -146,37 +155,6 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
};
}
const flatObjectMetadataWithFlatFieldMaps =
existingFlatObjectMetadataMaps.byId[
existingFlatFieldMetadataToUpdate.objectMetadataId
];
if (!isDefined(flatObjectMetadataWithFlatFieldMaps)) {
return {
status: 'fail',
error: {
code: FieldMetadataExceptionCode.FIELD_METADATA_NOT_FOUND,
message: 'Field metadata to update object metadata not found',
userFriendlyMessage: t`Field metadata to update object metadata not found`,
},
};
}
const flatObjectMetadata =
fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata(
flatObjectMetadataWithFlatFieldMaps,
);
if (flatObjectMetadata.isRemote) {
return {
status: 'fail',
error: {
code: FieldMetadataExceptionCode.FIELD_MUTATION_NOT_ALLOWED,
message: 'Remote objects are read-only',
},
};
}
if (isStandardMetadata(existingFlatFieldMetadataToUpdate)) {
const invalidUpdatedProperties = Object.keys(
updatedEditableFieldProperties,
@@ -224,10 +202,23 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
};
}
const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({
flatEntityId: existingFlatFieldMetadataToUpdate.objectMetadataId,
flatEntityMaps: existingFlatObjectMetadataMaps,
});
if (!isDefined(flatObjectMetadata)) {
throw new FieldMetadataException(
'Field to update object metadata not found',
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
);
}
const relatedFlatFieldMetadatasToUpdate =
computeFlatFieldMetadataRelatedFlatFieldMetadata({
flatFieldMetadata: existingFlatFieldMetadataToUpdate,
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
flatFieldMetadataMaps,
flatObjectMetadata,
});
const flatFieldMetadatasToUpdate = [
@@ -242,6 +233,7 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
applyUpdatesToFlatFieldMetadata({
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
fromFlatFieldMetadata,
flatFieldMetadataMaps,
flatIndexMaps,
updatedEditableFieldProperties,
});
@@ -86,7 +86,6 @@ export const generateMorphOrRelationFlatFieldMetadataPair = ({
options: null,
relationTargetFieldMetadataId: targetRelationTargetFieldMetadataId,
relationTargetObjectMetadataId: targetFlatObjectMetadata.id,
flatRelationTargetObjectMetadata: targetFlatObjectMetadata,
};
const targetCreateFieldInput: CreateFieldInput = {
@@ -122,14 +121,16 @@ export const generateMorphOrRelationFlatFieldMetadataPair = ({
options: null,
relationTargetFieldMetadataId: sourceRelationTargetFieldMetadataId,
relationTargetObjectMetadataId: sourceFlatObjectMetadata.id,
flatRelationTargetFieldMetadata: sourceFlatFieldMetadata,
flatRelationTargetObjectMetadata: sourceFlatObjectMetadata,
};
const indexId = v4();
const createdAt = new Date();
const indexMetadata: FlatIndexMetadata =
generateFlatIndexMetadataWithNameOrThrow({
objectFlatFieldMetadatas:
relationCreationPayload.type === RelationType.MANY_TO_ONE
? [sourceFlatFieldMetadata]
: [targetFlatFieldMetadata],
flatIndex: {
createdAt,
flatIndexFieldMetadatas: [
@@ -158,32 +159,14 @@ export const generateMorphOrRelationFlatFieldMetadataPair = ({
updatedAt: createdAt,
workspaceId,
},
flatObjectMetadata: (relationCreationPayload.type ===
RelationType.MANY_TO_ONE
? {
...sourceFlatObjectMetadata,
flatFieldMetadatas: [
...sourceFlatObjectMetadata.flatFieldMetadatas,
sourceFlatFieldMetadata,
],
}
: {
...targetFlatObjectMetadata,
flatFieldMetadatas: [
...targetFlatObjectMetadata.flatFieldMetadatas,
targetFlatFieldMetadata,
],
}) as FlatObjectMetadata,
flatObjectMetadata:
relationCreationPayload.type === RelationType.MANY_TO_ONE
? sourceFlatObjectMetadata
: targetFlatObjectMetadata,
});
return {
flatFieldMetadatas: [
{
...sourceFlatFieldMetadata,
flatRelationTargetFieldMetadata: targetFlatFieldMetadata,
},
targetFlatFieldMetadata,
],
flatFieldMetadatas: [sourceFlatFieldMetadata, targetFlatFieldMetadata],
indexMetadatas: [indexMetadata],
};
};
@@ -46,8 +46,6 @@ export const getDefaultFlatFieldMetadata = ({
type: createFieldInput.type,
universalIdentifier: fieldMetadataId,
workspaceId,
flatRelationTargetFieldMetadata: null,
flatRelationTargetObjectMetadata: null,
options: null,
defaultValue: defaultValue ?? generateDefaultValue(createFieldInput.type),
settings: settings ?? null,
@@ -2,6 +2,7 @@ import { isDefined } from 'twenty-shared/utils';
import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { findObjectFieldsInFlatFieldMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-object-fields-in-flat-field-metadata-maps-or-throw.util';
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
import { generateFlatIndexMetadataWithNameOrThrow } from 'src/engine/metadata-modules/index-metadata/utils/generate-flat-index.util';
@@ -10,13 +11,14 @@ type RecomputeIndexOnFlatFieldMetadataNameUpdateArgs = {
flatObjectMetadata: FlatObjectMetadata;
fromFlatFieldMetadata: FlatFieldMetadata;
toFlatFieldMetadata: Pick<FlatFieldMetadata, 'name'>;
} & Pick<AllFlatEntityMaps, 'flatIndexMaps'>;
} & Pick<AllFlatEntityMaps, 'flatIndexMaps' | 'flatFieldMetadataMaps'>;
export const recomputeIndexOnFlatFieldMetadataNameUpdate = ({
fromFlatFieldMetadata,
toFlatFieldMetadata,
flatObjectMetadata,
flatIndexMaps,
flatFieldMetadataMaps,
}: RecomputeIndexOnFlatFieldMetadataNameUpdateArgs): FlatIndexMetadata[] => {
const relatedFlatIndexMetadata = Object.values(flatIndexMaps.byId).filter(
(flatIndexMetadata): flatIndexMetadata is FlatIndexMetadata =>
@@ -33,26 +35,29 @@ export const recomputeIndexOnFlatFieldMetadataNameUpdate = ({
return [];
}
const optimisticFlatObjectMetadata = {
...flatObjectMetadata,
flatFieldMetadatas: flatObjectMetadata.flatFieldMetadatas.map(
(flatFieldMetadata) => {
if (flatFieldMetadata.id === fromFlatFieldMetadata.id) {
return {
...flatFieldMetadata,
name: toFlatFieldMetadata.name,
};
}
const { objectFlatFieldMetadatas } =
findObjectFieldsInFlatFieldMetadataMapsOrThrow({
flatFieldMetadataMaps,
flatObjectMetadata,
});
const optimisticObjectFlatFieldMetadatas = objectFlatFieldMetadatas.map(
(flatFieldMetadata) => {
if (flatFieldMetadata.id === fromFlatFieldMetadata.id) {
return {
...flatFieldMetadata,
name: toFlatFieldMetadata.name,
};
}
return flatFieldMetadata;
},
),
};
return flatFieldMetadata;
},
);
return relatedFlatIndexMetadata.map<FlatIndexMetadata>((flatIndex) => {
const newIndex = generateFlatIndexMetadataWithNameOrThrow({
flatObjectMetadata: optimisticFlatObjectMetadata,
flatIndex,
flatObjectMetadata,
objectFlatFieldMetadatas: optimisticObjectFlatFieldMetadatas,
});
return newIndex;
@@ -24,6 +24,7 @@ export const throwOnFieldInputTranspilationsError: ThrowOnFieldInputTranspilatio
throw new WorkspaceMigrationBuilderExceptionV2(
{
report: {
fieldMetadata: [],
index: [],
view: [],
viewField: [],