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:
+119
-90
@@ -15,12 +15,15 @@ import {
|
||||
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
|
||||
import { FlatFieldMetadataValidatorService } 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 { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { fromCreateFieldInputToFlatFieldAndItsFlatObjectMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-and-its-flat-object-metadata.util';
|
||||
import { isFlatFieldMetadataEntityOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util';
|
||||
import { mergeFlatFieldMetadatasInFlatObjectMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/merge-flat-field-metadatas-in-flat-object-metadata.util';
|
||||
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { dispatchAndMergeFlatFieldMetadatasInFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/dispatch-and-merge-flat-field-metadatas-in-flat-object-metadatas.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 { 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 { 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 { fromFlatObjectMetadataMapsToFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-maps-to-flat-object-metadatas.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';
|
||||
@@ -53,6 +56,57 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
return createdFieldMetadata;
|
||||
}
|
||||
|
||||
private computeOtherFlatObjectMetadataMapsToValidate({
|
||||
flatFieldMetadataToCreate,
|
||||
flatFieldMetadatasToCreate,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
flatFieldMetadatasToCreate: FlatFieldMetadata[];
|
||||
flatFieldMetadataToCreate: FlatFieldMetadata;
|
||||
}): FlatObjectMetadataMaps | undefined {
|
||||
if (
|
||||
!isFlatFieldMetadataEntityOfType(
|
||||
flatFieldMetadataToCreate,
|
||||
FieldMetadataType.RELATION,
|
||||
) &&
|
||||
!isFlatFieldMetadataEntityOfType(
|
||||
flatFieldMetadataToCreate,
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
const relatedFlatFieldMetadataToCreate = flatFieldMetadatasToCreate.find(
|
||||
(relatedFlatFieldMetadata) =>
|
||||
isFlatFieldMetadataEntityOfType(
|
||||
relatedFlatFieldMetadata,
|
||||
FieldMetadataType.RELATION,
|
||||
) &&
|
||||
relatedFlatFieldMetadata.id ===
|
||||
flatFieldMetadataToCreate.relationTargetFieldMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(relatedFlatFieldMetadataToCreate)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const flatObjectMetadataMapsWithRelatedObjectMetadata =
|
||||
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps({
|
||||
flatObjectMetadataMaps,
|
||||
objectMetadataIds: [relatedFlatFieldMetadataToCreate.objectMetadataId],
|
||||
});
|
||||
|
||||
if (!isDefined(flatObjectMetadataMapsWithRelatedObjectMetadata)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return addFlatFieldMetadataInFlatObjectMetadataMaps({
|
||||
flatFieldMetadata: relatedFlatFieldMetadataToCreate,
|
||||
flatObjectMetadataMaps: flatObjectMetadataMapsWithRelatedObjectMetadata,
|
||||
});
|
||||
}
|
||||
|
||||
async createMany(
|
||||
fieldMetadataInputs: CreateFieldInput[],
|
||||
): Promise<FieldMetadataEntity[]> {
|
||||
@@ -79,86 +133,27 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
)
|
||||
).flat();
|
||||
|
||||
const existingFlatObjectMetadatas = Object.values(
|
||||
existingFlatObjectMetadataMaps.byId,
|
||||
).map(fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata);
|
||||
|
||||
const impactedObjectMetadataIds = Array.from(
|
||||
new Set(
|
||||
flatFieldMetadatasToCreate.map(
|
||||
(flatFieldMetadata) => flatFieldMetadata.objectMetadataId,
|
||||
),
|
||||
),
|
||||
);
|
||||
const filterFlatObjectMetadatasByImpactedIds = (
|
||||
flatObjectMetadatas: FlatObjectMetadata[],
|
||||
) =>
|
||||
flatObjectMetadatas.filter((flatObjectMetadata) =>
|
||||
impactedObjectMetadataIds.includes(flatObjectMetadata.id),
|
||||
);
|
||||
const impactedExistingFlatObjectMetadatas =
|
||||
filterFlatObjectMetadatasByImpactedIds(existingFlatObjectMetadatas);
|
||||
|
||||
const allValidationErrors: FailedFlatFieldMetadataValidationExceptions[] =
|
||||
[];
|
||||
let sequentiallyOptimisticallyRenderedFlatObjectMetadatas = structuredClone(
|
||||
existingFlatObjectMetadatas,
|
||||
let optimisticFlatObjectMetadataMaps = structuredClone(
|
||||
existingFlatObjectMetadataMaps,
|
||||
);
|
||||
|
||||
for (const flatFieldMetadataToCreate of flatFieldMetadatasToCreate) {
|
||||
let otherFlatObjectMetadataToValidate: FlatObjectMetadata | undefined =
|
||||
undefined;
|
||||
|
||||
if (
|
||||
isFlatFieldMetadataEntityOfType(
|
||||
const otherFlatObjectMetadataMapsToValidate =
|
||||
this.computeOtherFlatObjectMetadataMapsToValidate({
|
||||
flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps,
|
||||
flatFieldMetadatasToCreate,
|
||||
flatFieldMetadataToCreate,
|
||||
FieldMetadataType.RELATION,
|
||||
) ||
|
||||
isFlatFieldMetadataEntityOfType(
|
||||
flatFieldMetadataToCreate,
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
)
|
||||
) {
|
||||
const relatedFlatFieldMetadataToCreate =
|
||||
flatFieldMetadatasToCreate.find(
|
||||
(relatedFlatFieldMetadata) =>
|
||||
isFlatFieldMetadataEntityOfType(
|
||||
relatedFlatFieldMetadata,
|
||||
FieldMetadataType.RELATION,
|
||||
) &&
|
||||
relatedFlatFieldMetadata.id ===
|
||||
flatFieldMetadataToCreate.relationTargetFieldMetadataId,
|
||||
);
|
||||
const relatedFlatObjectMetadata = isDefined(
|
||||
relatedFlatFieldMetadataToCreate,
|
||||
)
|
||||
? existingFlatObjectMetadataMaps.byId[
|
||||
relatedFlatFieldMetadataToCreate.objectMetadataId
|
||||
]
|
||||
: undefined;
|
||||
|
||||
otherFlatObjectMetadataToValidate =
|
||||
isDefined(relatedFlatObjectMetadata) &&
|
||||
isDefined(relatedFlatFieldMetadataToCreate)
|
||||
? mergeFlatFieldMetadatasInFlatObjectMetadata({
|
||||
flatFieldMetadatas: [relatedFlatFieldMetadataToCreate],
|
||||
flatObjectMetadata: relatedFlatObjectMetadata,
|
||||
})
|
||||
: undefined;
|
||||
}
|
||||
});
|
||||
|
||||
const validationErrors =
|
||||
await this.flatFieldMetadataValidatorService.validateOneFlatFieldMetadata(
|
||||
{
|
||||
existingFlatObjectMetadatas:
|
||||
sequentiallyOptimisticallyRenderedFlatObjectMetadatas,
|
||||
existingFlatObjectMetadataMaps: optimisticFlatObjectMetadataMaps,
|
||||
flatFieldMetadataToValidate: flatFieldMetadataToCreate,
|
||||
workspaceId,
|
||||
othersFlatObjectMetadataToValidate: isDefined(
|
||||
otherFlatObjectMetadataToValidate,
|
||||
)
|
||||
? [otherFlatObjectMetadataToValidate]
|
||||
: undefined,
|
||||
otherFlatObjectMetadataMapsToValidate,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -167,12 +162,18 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
continue;
|
||||
}
|
||||
|
||||
sequentiallyOptimisticallyRenderedFlatObjectMetadatas =
|
||||
dispatchAndMergeFlatFieldMetadatasInFlatObjectMetadatas({
|
||||
flatFieldMetadatas: [flatFieldMetadataToCreate],
|
||||
flatObjectMetadatas:
|
||||
sequentiallyOptimisticallyRenderedFlatObjectMetadatas,
|
||||
});
|
||||
try {
|
||||
optimisticFlatObjectMetadataMaps =
|
||||
addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow({
|
||||
flatFieldMetadata: flatFieldMetadataToCreate,
|
||||
flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps,
|
||||
});
|
||||
} catch (e) {
|
||||
throw new FieldMetadataException(
|
||||
'Optimistic cache manipulation failed, should never occur',
|
||||
FieldMetadataExceptionCode.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (allValidationErrors.length > 0) {
|
||||
@@ -182,20 +183,48 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
);
|
||||
}
|
||||
|
||||
const workspaceMigration = this.workspaceMigrationBuilderV2.build({
|
||||
objectMetadataFromToInputs: {
|
||||
from: impactedExistingFlatObjectMetadatas,
|
||||
to: filterFlatObjectMetadatasByImpactedIds(
|
||||
sequentiallyOptimisticallyRenderedFlatObjectMetadatas,
|
||||
const impactedObjectMetadataIds = Array.from(
|
||||
new Set(
|
||||
flatFieldMetadatasToCreate.map(
|
||||
(flatFieldMetadata) => flatFieldMetadata.objectMetadataId,
|
||||
),
|
||||
},
|
||||
inferDeletionFromMissingObjectFieldIndex: false,
|
||||
workspaceId,
|
||||
});
|
||||
),
|
||||
);
|
||||
|
||||
await this.workspaceMigrationRunnerV2Service.run(workspaceMigration);
|
||||
try {
|
||||
const fromImpactedFlatObjectMetadataMaps =
|
||||
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
objectMetadataIds: impactedObjectMetadataIds,
|
||||
});
|
||||
const toImpactedFlatObjectMetadataMaps =
|
||||
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({
|
||||
flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps,
|
||||
objectMetadataIds: impactedObjectMetadataIds,
|
||||
});
|
||||
const workspaceMigration = this.workspaceMigrationBuilderV2.build({
|
||||
objectMetadataFromToInputs: {
|
||||
from: fromFlatObjectMetadataMapsToFlatObjectMetadatas(
|
||||
fromImpactedFlatObjectMetadataMaps,
|
||||
),
|
||||
to: fromFlatObjectMetadataMapsToFlatObjectMetadatas(
|
||||
toImpactedFlatObjectMetadataMaps,
|
||||
),
|
||||
},
|
||||
inferDeletionFromMissingObjectFieldIndex: false,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
// TODO refactor once the runner has been refactored to return created entities
|
||||
return [];
|
||||
await this.workspaceMigrationRunnerV2Service.run(workspaceMigration);
|
||||
|
||||
// TODO refactor once the runner has been refactored to return created entities
|
||||
return [];
|
||||
} catch {
|
||||
// TODO prastoin We should pass the internal error here
|
||||
throw new FieldMetadataException(
|
||||
'Workspace migration failed to run',
|
||||
FieldMetadataExceptionCode.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-21
@@ -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);
|
||||
|
||||
+13
-20
@@ -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,
|
||||
|
||||
+15
-7
@@ -15,9 +15,10 @@ export const expectFlatFieldMetadataToBeInFlatObjectMetadataMaps = ({
|
||||
flatObjectMetadataMaps,
|
||||
}: ExpectFlatFieldMetadataToBeInFlatObjectMetadataMapsArgs) => {
|
||||
const { objectMetadataId, id: flatFieldMetadataId } = flatFieldMetadata;
|
||||
const petObject = flatObjectMetadataMaps.byId[objectMetadataId];
|
||||
const matchingFlatObjectMetadata =
|
||||
flatObjectMetadataMaps.byId[objectMetadataId];
|
||||
|
||||
jestExpectToBeDefined(petObject);
|
||||
jestExpectToBeDefined(matchingFlatObjectMetadata);
|
||||
|
||||
if (
|
||||
isFlatFieldMetadataEntityOfType(
|
||||
@@ -27,15 +28,22 @@ export const expectFlatFieldMetadataToBeInFlatObjectMetadataMaps = ({
|
||||
isDefined(flatFieldMetadata.settings.joinColumnName)
|
||||
) {
|
||||
expect(
|
||||
petObject.fieldIdByJoinColumnName[
|
||||
matchingFlatObjectMetadata.fieldIdByJoinColumnName[
|
||||
flatFieldMetadata.settings.joinColumnName
|
||||
],
|
||||
).toEqual(flatFieldMetadataId);
|
||||
}
|
||||
|
||||
expect(petObject.fieldsById[flatFieldMetadataId]).toBeDefined();
|
||||
expect(petObject.fieldsById[flatFieldMetadataId]).toEqual(flatFieldMetadata);
|
||||
expect(petObject.fieldIdByName[flatFieldMetadata.name]).toEqual(
|
||||
flatFieldMetadataId,
|
||||
expect(
|
||||
matchingFlatObjectMetadata.fieldsById[flatFieldMetadataId],
|
||||
).toBeDefined();
|
||||
expect(matchingFlatObjectMetadata.fieldsById[flatFieldMetadataId]).toEqual(
|
||||
flatFieldMetadata,
|
||||
);
|
||||
expect(matchingFlatObjectMetadata.flatFieldMetadatas).toContain(
|
||||
flatFieldMetadata,
|
||||
);
|
||||
expect(
|
||||
matchingFlatObjectMetadata.fieldIdByName[flatFieldMetadata.name],
|
||||
).toEqual(flatFieldMetadataId);
|
||||
};
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
// 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"`;
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
import {
|
||||
EachTestingContext,
|
||||
eachTestingContextFilter,
|
||||
} from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
|
||||
import { PET_FLAT_FIELDS_MOCK } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/pet-flat-fields.mock';
|
||||
import { FLAT_OBJECT_METADATA_MAPS_MOCKS } from 'src/engine/metadata-modules/flat-object-metadata-maps/mocks/flat-object-metadata-maps.mock';
|
||||
import { AddFlatFieldMetadataInFlatObjectMetadataMapsOrThrowArgs } 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';
|
||||
|
||||
type AddFlatFieldMetadataInFlatObjectMetadataMapsArgsTestCase = {
|
||||
input: AddFlatFieldMetadataInFlatObjectMetadataMapsOrThrowArgs;
|
||||
};
|
||||
|
||||
describe('addFlatFieldMetadataInFlatObjectMetadataMaps', () => {
|
||||
const testCases: EachTestingContext<AddFlatFieldMetadataInFlatObjectMetadataMapsArgsTestCase>[] =
|
||||
[
|
||||
{
|
||||
title:
|
||||
'should return undefined when field metadata parent object metadata does not exist',
|
||||
context: {
|
||||
input: {
|
||||
flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS,
|
||||
flatFieldMetadata: getFlatFieldMetadataMock({
|
||||
objectMetadataId: 'non-existent',
|
||||
type: FieldMetadataType.TEXT,
|
||||
uniqueIdentifier: 'unique-id-1',
|
||||
id: 'unique-id-1',
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title:
|
||||
'should return undefined when field metadata to add already exist in object',
|
||||
context: {
|
||||
input: {
|
||||
flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS,
|
||||
flatFieldMetadata: PET_FLAT_FIELDS_MOCK.species,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const filteredTestCases = eachTestingContextFilter(testCases);
|
||||
|
||||
it.each(filteredTestCases)(
|
||||
'$title',
|
||||
({
|
||||
context: {
|
||||
input: { flatFieldMetadata, flatObjectMetadataMaps },
|
||||
},
|
||||
}) => {
|
||||
const updatedFlatObjectMetadataMaps =
|
||||
addFlatFieldMetadataInFlatObjectMetadataMaps({
|
||||
flatFieldMetadata,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
expect(updatedFlatObjectMetadataMaps).toBeUndefined();
|
||||
},
|
||||
);
|
||||
});
|
||||
+1
-1
@@ -78,7 +78,7 @@ describe('addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow', () => {
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
expect(updatedFlatObjectMetadataMaps).toEqual(expected);
|
||||
expect(updatedFlatObjectMetadataMaps).toStrictEqual(expected);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
import { jestExpectToBeDefined } from 'test/utils/expect-to-be-defined.util.test';
|
||||
import {
|
||||
EachTestingContext,
|
||||
eachTestingContextFilter,
|
||||
} 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 { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
import {
|
||||
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';
|
||||
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;
|
||||
shouldThrow?: true;
|
||||
expected?: FlatObjectMetadataMaps;
|
||||
};
|
||||
|
||||
describe('extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow', () => {
|
||||
const testCases: EachTestingContext<ExtractFlatObjectMetadataMapsTestCase>[] =
|
||||
[
|
||||
{
|
||||
title: 'should throw when object metadata id is not found',
|
||||
context: {
|
||||
input: {
|
||||
objectMetadataIds: ['non-existent-id'],
|
||||
flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS,
|
||||
},
|
||||
shouldThrow: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should throw when extracting twice the same object',
|
||||
context: {
|
||||
input: {
|
||||
objectMetadataIds: [
|
||||
PET_FLAT_OBJECT_MOCK.id,
|
||||
PET_FLAT_OBJECT_MOCK.id,
|
||||
],
|
||||
flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS,
|
||||
},
|
||||
shouldThrow: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should extract single object metadata from maps',
|
||||
context: {
|
||||
input: {
|
||||
objectMetadataIds: [PET_FLAT_OBJECT_MOCK.id],
|
||||
flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS,
|
||||
},
|
||||
expected: fromFlatObjectMetadatasToFlatObjectMetadataMaps([
|
||||
PET_FLAT_OBJECT_MOCK,
|
||||
]),
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should extract multiple object metadata from maps',
|
||||
context: {
|
||||
input: {
|
||||
objectMetadataIds: [
|
||||
PET_FLAT_OBJECT_MOCK.id,
|
||||
ROCKET_FLAT_OBJECT_MOCK.id,
|
||||
],
|
||||
flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS,
|
||||
},
|
||||
expected: fromFlatObjectMetadatasToFlatObjectMetadataMaps([
|
||||
PET_FLAT_OBJECT_MOCK,
|
||||
ROCKET_FLAT_OBJECT_MOCK,
|
||||
]),
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const filteredTestCases = eachTestingContextFilter(testCases);
|
||||
|
||||
it.each(filteredTestCases)(
|
||||
'$title',
|
||||
({
|
||||
context: {
|
||||
input: { objectMetadataIds, flatObjectMetadataMaps },
|
||||
shouldThrow = false,
|
||||
expected,
|
||||
},
|
||||
}) => {
|
||||
if (shouldThrow) {
|
||||
expect(() =>
|
||||
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({
|
||||
objectMetadataIds,
|
||||
flatObjectMetadataMaps,
|
||||
}),
|
||||
).toThrowErrorMatchingSnapshot();
|
||||
} else {
|
||||
jestExpectToBeDefined(expected);
|
||||
const result =
|
||||
extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrow({
|
||||
objectMetadataIds,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
import {
|
||||
EachTestingContext,
|
||||
eachTestingContextFilter,
|
||||
} 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 { 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 { PET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/pet-flat-object.mock';
|
||||
|
||||
type ExtractFlatObjectMetadataMapsTestCase = {
|
||||
input: ExtractFlatObjectMetadataMapsOutOfFlatObjectMetadataMapsOrThrowArgs;
|
||||
};
|
||||
|
||||
describe('extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps', () => {
|
||||
const testCases: EachTestingContext<ExtractFlatObjectMetadataMapsTestCase>[] =
|
||||
[
|
||||
{
|
||||
title: 'should throw when object metadata id is not found',
|
||||
context: {
|
||||
input: {
|
||||
objectMetadataIds: ['non-existent-id'],
|
||||
flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'should throw when extracting twice the same object',
|
||||
context: {
|
||||
input: {
|
||||
objectMetadataIds: [
|
||||
PET_FLAT_OBJECT_MOCK.id,
|
||||
PET_FLAT_OBJECT_MOCK.id,
|
||||
],
|
||||
flatObjectMetadataMaps: FLAT_OBJECT_METADATA_MAPS_MOCKS,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const filteredTestCases = eachTestingContextFilter(testCases);
|
||||
|
||||
it.each(filteredTestCases)(
|
||||
'$title',
|
||||
({
|
||||
context: {
|
||||
input: { objectMetadataIds, flatObjectMetadataMaps },
|
||||
},
|
||||
}) => {
|
||||
const result = extractFlatObjectMetadataMapsOutOfFlatObjectMetadataMaps({
|
||||
objectMetadataIds,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
},
|
||||
);
|
||||
});
|
||||
+4
@@ -55,6 +55,10 @@ describe('findFlatObjectMetadataInFlatObjectMetadataMaps', () => {
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
expect(result?.flatFieldMetadatas.length).toEqual(
|
||||
expected?.flatFieldMetadatas.length,
|
||||
);
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
},
|
||||
);
|
||||
|
||||
+1
-1
@@ -35,6 +35,6 @@ export const addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow = ({
|
||||
flatObjectMetadataWithFlatFieldMaps,
|
||||
}),
|
||||
},
|
||||
idByNameSingular: flatObjectMetadataMaps.idByNameSingular,
|
||||
idByNameSingular: { ...flatObjectMetadataMaps.idByNameSingular },
|
||||
};
|
||||
};
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
import {
|
||||
AddFlatFieldMetadataInFlatObjectMetadataMapsOrThrowArgs,
|
||||
addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow,
|
||||
} from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util';
|
||||
|
||||
export const addFlatFieldMetadataInFlatObjectMetadataMaps = (
|
||||
arg: AddFlatFieldMetadataInFlatObjectMetadataMapsOrThrowArgs,
|
||||
): FlatObjectMetadataMaps | undefined => {
|
||||
try {
|
||||
return addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow(arg);
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
+4
@@ -67,5 +67,9 @@ export const addFlatFieldMetadataToFlatObjectMetadataWithFlatFieldMapsOrThrow =
|
||||
...flatObjectMetadataWithFlatFieldMaps.fieldsById,
|
||||
[flatFieldMetadata.id]: flatFieldMetadata,
|
||||
},
|
||||
flatFieldMetadatas: [
|
||||
...flatObjectMetadataWithFlatFieldMaps.flatFieldMetadatas,
|
||||
flatFieldMetadata,
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatObjectMetadataMapsException,
|
||||
FlatObjectMetadataMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-object-metadata-maps/flat-object-metadata-maps.exception';
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
import { FlatObjectMetadataWithFlatFieldMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-with-flat-field-metadata-maps.type';
|
||||
|
||||
type AddFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrowArgs =
|
||||
{
|
||||
flatObjectMetadataWithFlatFieldMaps: FlatObjectMetadataWithFlatFieldMaps;
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
};
|
||||
export const addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow =
|
||||
({
|
||||
flatObjectMetadataWithFlatFieldMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}: AddFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrowArgs): FlatObjectMetadataMaps => {
|
||||
if (
|
||||
isDefined(
|
||||
flatObjectMetadataMaps.byId[flatObjectMetadataWithFlatFieldMaps.id],
|
||||
)
|
||||
) {
|
||||
throw new FlatObjectMetadataMapsException(
|
||||
'addFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadataMapsOrThrow: flat object metadata with fields maps to add already exists',
|
||||
FlatObjectMetadataMapsExceptionCode.OBJECT_METADATA_ALREADY_EXISTS,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
byId: {
|
||||
...flatObjectMetadataMaps.byId,
|
||||
[flatObjectMetadataWithFlatFieldMaps.id]:
|
||||
flatObjectMetadataWithFlatFieldMaps,
|
||||
},
|
||||
idByNameSingular: {
|
||||
...flatObjectMetadataMaps.idByNameSingular,
|
||||
[flatObjectMetadataWithFlatFieldMaps.nameSingular]:
|
||||
flatObjectMetadataWithFlatFieldMaps.id,
|
||||
},
|
||||
};
|
||||
};
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatObjectMetadataMapsException,
|
||||
FlatObjectMetadataMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-object-metadata-maps/flat-object-metadata-maps.exception';
|
||||
import { 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 => {
|
||||
const emptyFlatObjectMetadataMaps: FlatObjectMetadataMaps = {
|
||||
byId: {},
|
||||
idByNameSingular: {},
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
);
|
||||
},
|
||||
emptyFlatObjectMetadataMaps,
|
||||
);
|
||||
};
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
import {
|
||||
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;
|
||||
}
|
||||
};
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.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';
|
||||
|
||||
export const fromFlatObjectMetadataMapsToFlatObjectMetadatas = (
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps,
|
||||
): FlatObjectMetadata[] => {
|
||||
return Object.values(flatObjectMetadataMaps.byId)
|
||||
.filter(isDefined)
|
||||
.map(fromFlatObjectMetadataWithFlatFieldMapsToFlatObjectMetadata);
|
||||
};
|
||||
+2
@@ -8,6 +8,8 @@ export const fromFlatObjectMetadataToFlatObjectMetadataWithFlatFieldMaps = (
|
||||
const emptyFlatObjectMetadataWithFlatFieldMaps: FlatObjectMetadataWithFlatFieldMaps =
|
||||
{
|
||||
...flatObjectMetadata,
|
||||
flatIndexMetadatas: [],
|
||||
flatFieldMetadatas: [],
|
||||
fieldIdByJoinColumnName: {},
|
||||
fieldIdByName: {},
|
||||
fieldsById: {},
|
||||
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.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 { ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
|
||||
|
||||
export const fromObjectMetadataMapsToFlatObjectMetadatas = (
|
||||
objectMetadataMaps: ObjectMetadataMaps,
|
||||
): FlatObjectMetadata[] => {
|
||||
return Object.values(objectMetadataMaps.byId)
|
||||
.filter(isDefined)
|
||||
.map((objectMetadataItemWithFieldMaps) =>
|
||||
fromObjectMetadataItemWithFieldMapsToFlatObjectMetadata({
|
||||
objectMetadataItemWithFieldMaps,
|
||||
objectMetadataMaps,
|
||||
}),
|
||||
);
|
||||
};
|
||||
+12
-7
@@ -5,10 +5,11 @@ import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { fromCreateObjectInputToFlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-create-object-input-to-flat-object-metadata.util';
|
||||
import { fromObjectMetadataMapsToFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-object-metadata-maps-to-flat-object-metadatas.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';
|
||||
import { FlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/types/flat-object-metadata-maps.type';
|
||||
import { fromFlatObjectMetadataMapsToFlatObjectMetadatas } from 'src/engine/metadata-modules/flat-object-metadata/utils/from-flat-object-metadata-maps-to-flat-object-metadatas.util';
|
||||
|
||||
import { ObjectMetadataEntity } from './object-metadata.entity';
|
||||
|
||||
@@ -30,8 +31,8 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
override async createOne(
|
||||
objectMetadataInput: CreateObjectInput,
|
||||
): Promise<ObjectMetadataEntity> {
|
||||
const { objectMetadataMaps } =
|
||||
await this.workspaceMetadataCacheService.getExistingOrRecomputeMetadataMaps(
|
||||
const { flatObjectMetadataMaps } =
|
||||
await this.workspaceMetadataCacheService.getExistingOrRecomputeFlatObjectMetadataMaps(
|
||||
{
|
||||
workspaceId: objectMetadataInput.workspaceId,
|
||||
},
|
||||
@@ -39,19 +40,23 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
|
||||
const createdRawFlatObjectMetadata =
|
||||
fromCreateObjectInputToFlatObjectMetadata(objectMetadataInput);
|
||||
const existingFlatObjectMetadatas =
|
||||
fromObjectMetadataMapsToFlatObjectMetadatas(objectMetadataMaps);
|
||||
const existingFlatObjectMetadatas: FlatObjectMetadataMaps = {
|
||||
byId: {},
|
||||
idByNameSingular: {},
|
||||
};
|
||||
// @ts-expect-error TODO implement validateFlatObjectMetadata
|
||||
const createdFlatObjectMetadata = validateFlatObjectMetadata({
|
||||
existing:
|
||||
// Here we assume that EVERYTHING is in cache and up to date, this is very critical, also race condition prone :thinking:
|
||||
fromObjectMetadataMapsToFlatObjectMetadatas(objectMetadataMaps),
|
||||
fromFlatObjectMetadataMapsToFlatObjectMetadatas(flatObjectMetadataMaps),
|
||||
toValidate: [createdRawFlatObjectMetadata],
|
||||
});
|
||||
|
||||
const workspaceMigration = this.workspaceMigrationBuilderV2.build({
|
||||
objectMetadataFromToInputs: {
|
||||
from: existingFlatObjectMetadatas,
|
||||
from: fromFlatObjectMetadataMapsToFlatObjectMetadatas(
|
||||
existingFlatObjectMetadatas,
|
||||
),
|
||||
to: [createdFlatObjectMetadata],
|
||||
},
|
||||
inferDeletionFromMissingObjectFieldIndex: false,
|
||||
|
||||
Reference in New Issue
Block a user