Refactor builder to embed Object validation create/delete/update (#13934)
# Introduction Moving validation directly in the builder that has the perfect granularity to do it. When importing we won't have to infer and dispatch on the operation nature ( update delete create ) and validate accordingly ## Objects Only migrated object validation for the moment even though create object involves a validate flat field metadata creation call too ## TODO - improve `otherFlatObjectMetadataMapsToValidate` naming too vague ## Next - handle fields validation within fields actions build - Unit test coverage validation issue on builder and validate - integration test plugging with new feature flag ## Manual tested - Update - Delete - Create TODO
This commit is contained in:
+10
-6
@@ -1,25 +1,29 @@
|
||||
import { ATTACHMENT_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/attachment-flat-object.mock';
|
||||
import { COMPANY_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/company-flat-object.mock';
|
||||
import { FAVORITE_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/favorite-flat-object.mock';
|
||||
import { FAVORITE_FOLDER_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/favorite-folder-flat-object.mock';
|
||||
import { NOTE_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/note-flat-object.mock';
|
||||
import { NOTETARGET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/notetarget-flat-object.mock';
|
||||
import { NOTE_TARGET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/note-target-flat-object.mock';
|
||||
import { OPPORTUNITY_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/opportunity-flat-object.mock';
|
||||
import { PERSON_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/person-flat-object.mock';
|
||||
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 { TASK_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/task-flat-object.mock';
|
||||
import { TASKTARGET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/tasktarget-flat-object.mock';
|
||||
import { TIMELINEACTIVITY_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/timelineactivity-flat-object.mock';
|
||||
import { TASK_TARGET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/task-target-flat-object.mock';
|
||||
import { TIMELINE_ACTIVITY_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/timeline-activity-flat-object.mock';
|
||||
|
||||
export const ALL_FLAT_OBJECT_METADATA_MOCKS = [
|
||||
TIMELINEACTIVITY_FLAT_OBJECT_MOCK,
|
||||
NOTETARGET_FLAT_OBJECT_MOCK,
|
||||
TIMELINE_ACTIVITY_FLAT_OBJECT_MOCK,
|
||||
NOTE_TARGET_FLAT_OBJECT_MOCK,
|
||||
OPPORTUNITY_FLAT_OBJECT_MOCK,
|
||||
PERSON_FLAT_OBJECT_MOCK,
|
||||
TASK_FLAT_OBJECT_MOCK,
|
||||
TASKTARGET_FLAT_OBJECT_MOCK,
|
||||
TASK_TARGET_FLAT_OBJECT_MOCK,
|
||||
PET_FLAT_OBJECT_MOCK,
|
||||
ROCKET_FLAT_OBJECT_MOCK,
|
||||
NOTE_FLAT_OBJECT_MOCK,
|
||||
COMPANY_FLAT_OBJECT_MOCK,
|
||||
ATTACHMENT_FLAT_OBJECT_MOCK,
|
||||
FAVORITE_FLAT_OBJECT_MOCK,
|
||||
FAVORITE_FOLDER_FLAT_OBJECT_MOCK,
|
||||
] as const;
|
||||
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
import { ATTACHMENT_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/attachment-flat-object.mock';
|
||||
import { COMPANY_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/company-flat-object.mock';
|
||||
import { NOTE_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/note-flat-object.mock';
|
||||
import { NOTETARGET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/notetarget-flat-object.mock';
|
||||
import { OPPORTUNITY_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/opportunity-flat-object.mock';
|
||||
import { PERSON_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/person-flat-object.mock';
|
||||
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 { TASK_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/task-flat-object.mock';
|
||||
import { TASKTARGET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/tasktarget-flat-object.mock';
|
||||
import { TIMELINEACTIVITY_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/timelineactivity-flat-object.mock';
|
||||
|
||||
export const ALL_FLAT_OBJECT_METADATA_MOCKS = [
|
||||
TIMELINEACTIVITY_FLAT_OBJECT_MOCK,
|
||||
NOTETARGET_FLAT_OBJECT_MOCK,
|
||||
OPPORTUNITY_FLAT_OBJECT_MOCK,
|
||||
PERSON_FLAT_OBJECT_MOCK,
|
||||
TASK_FLAT_OBJECT_MOCK,
|
||||
TASKTARGET_FLAT_OBJECT_MOCK,
|
||||
PET_FLAT_OBJECT_MOCK,
|
||||
ROCKET_FLAT_OBJECT_MOCK,
|
||||
NOTE_FLAT_OBJECT_MOCK,
|
||||
COMPANY_FLAT_OBJECT_MOCK,
|
||||
ATTACHMENT_FLAT_OBJECT_MOCK,
|
||||
] as const;
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import { FAVORITE_FLAT_FIELDS_MOCK } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/favorite-flat-fields.mock';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
|
||||
export const FAVORITE_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
|
||||
id: 'f4749ffb-dde8-44ff-8b01-d3fc82df0ba2',
|
||||
standardId: '20202020-ab56-4e05-92a3-e2414a499860',
|
||||
nameSingular: 'favorite',
|
||||
namePlural: 'favorites',
|
||||
labelSingular: 'Favorite',
|
||||
labelPlural: 'Favorites',
|
||||
description: 'A favorite that can be accessed from the left menu',
|
||||
icon: 'IconHeart',
|
||||
standardOverrides: null,
|
||||
targetTableName: 'DEPRECATED',
|
||||
isCustom: false,
|
||||
isRemote: false,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
isAuditLogged: true,
|
||||
isSearchable: false,
|
||||
shortcut: null,
|
||||
labelIdentifierFieldMetadataId: '49f58497-4e7c-49e6-b3bc-c91d4b8a8ddc',
|
||||
imageIdentifierFieldMetadataId: null,
|
||||
isLabelSyncedWithName: false,
|
||||
workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419',
|
||||
uniqueIdentifier: '20202020-ab56-4e05-92a3-e2414a499860',
|
||||
flatIndexMetadatas: [],
|
||||
flatFieldMetadatas: Object.values(FAVORITE_FLAT_FIELDS_MOCK),
|
||||
});
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import { FAVORITE_FOLDER_FLAT_FIELDS_MOCK } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/favorite-folder-flat-fields.mock';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
|
||||
export const FAVORITE_FOLDER_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
|
||||
id: '35763b74-1abe-4c4b-9eab-27693f0ee06d',
|
||||
standardId: '20202020-7cf8-401f-8211-a9587d27fd2d',
|
||||
nameSingular: 'favoriteFolder',
|
||||
namePlural: 'favoriteFolders',
|
||||
labelSingular: 'Favorite Folder',
|
||||
labelPlural: 'Favorite Folders',
|
||||
description: 'A Folder of favorites',
|
||||
icon: 'IconFolder',
|
||||
standardOverrides: null,
|
||||
targetTableName: 'DEPRECATED',
|
||||
isCustom: false,
|
||||
isRemote: false,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
isAuditLogged: true,
|
||||
isSearchable: false,
|
||||
shortcut: null,
|
||||
labelIdentifierFieldMetadataId: '85ab1864-0a92-4682-8583-82e8b696410b',
|
||||
imageIdentifierFieldMetadataId: null,
|
||||
isLabelSyncedWithName: false,
|
||||
workspaceId: '20202020-1c25-4d02-bf25-6aeccf7ea419',
|
||||
uniqueIdentifier: '20202020-7cf8-401f-8211-a9587d27fd2d',
|
||||
flatIndexMetadatas: [],
|
||||
flatFieldMetadatas: Object.values(FAVORITE_FOLDER_FLAT_FIELDS_MOCK),
|
||||
});
|
||||
+1
-1
@@ -9,7 +9,7 @@ type FlatObjectMetadataOverrides = Required<
|
||||
export const getFlatObjectMetadataMock = (
|
||||
overrides: FlatObjectMetadataOverrides,
|
||||
): FlatObjectMetadata => {
|
||||
const createdAt = new Date();
|
||||
const createdAt = '2024-01-01T00:00:00.000Z' as unknown as Date;
|
||||
|
||||
return {
|
||||
flatFieldMetadatas: [],
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { NOTETARGET_FLAT_FIELDS_MOCK } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/notetarget-flat-fields.mock';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
|
||||
export const NOTETARGET_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
|
||||
export const NOTE_TARGET_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
|
||||
id: '12e3cb51-c3de-4192-b0d5-965d48d001c0',
|
||||
standardId: '20202020-fff0-4b44-be82-bda313884400',
|
||||
nameSingular: 'noteTarget',
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import { ATTACHMENT_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/attachment-flat-object.mock';
|
||||
import { FAVORITE_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/favorite-flat-object.mock';
|
||||
import { FAVORITE_FOLDER_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/favorite-folder-flat-object.mock';
|
||||
import { NOTE_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/note-flat-object.mock';
|
||||
import { NOTE_TARGET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/note-target-flat-object.mock';
|
||||
import { TASK_TARGET_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/task-target-flat-object.mock';
|
||||
import { TIMELINE_ACTIVITY_FLAT_OBJECT_MOCK } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/timeline-activity-flat-object.mock';
|
||||
|
||||
export const STANDARD_RELATION_TARGET_FLAT_OBJECT_METADATA_MOCKS = [
|
||||
NOTE_FLAT_OBJECT_MOCK,
|
||||
TIMELINE_ACTIVITY_FLAT_OBJECT_MOCK,
|
||||
NOTE_TARGET_FLAT_OBJECT_MOCK,
|
||||
FAVORITE_FLAT_OBJECT_MOCK,
|
||||
ATTACHMENT_FLAT_OBJECT_MOCK,
|
||||
TASK_TARGET_FLAT_OBJECT_MOCK,
|
||||
FAVORITE_FOLDER_FLAT_OBJECT_MOCK,
|
||||
] as const;
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { TASKTARGET_FLAT_FIELDS_MOCK } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/tasktarget-flat-fields.mock';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
|
||||
export const TASKTARGET_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
|
||||
export const TASK_TARGET_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
|
||||
id: 'bb2b29b8-7f46-4106-a8ae-3a32df9c9166',
|
||||
standardId: '20202020-5a9a-44e8-95df-771cd06d0fb1',
|
||||
nameSingular: 'taskTarget',
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { TIMELINEACTIVITY_FLAT_FIELDS_MOCK } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/timelineactivity-flat-fields.mock';
|
||||
import { getFlatObjectMetadataMock } from 'src/engine/metadata-modules/flat-object-metadata/__mocks__/get-flat-object-metadata.mock';
|
||||
|
||||
export const TIMELINEACTIVITY_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
|
||||
export const TIMELINE_ACTIVITY_FLAT_OBJECT_MOCK = getFlatObjectMetadataMock({
|
||||
id: '3090f830-c4b1-41a1-8e18-815760830bec',
|
||||
standardId: '20202020-6736-4337-b5c4-8b39fae325a5',
|
||||
nameSingular: 'timelineActivity',
|
||||
+82
-20
@@ -1,13 +1,19 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
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 { findRelationFlatFieldMetadataTargetFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-relation-flat-field-metadatas-target-flat-field-metadata.util';
|
||||
import { isFlatFieldMetadataEntityOfType } 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 { addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util';
|
||||
import { addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-to-flat-object-metadata-maps-or-throw.util';
|
||||
import { findFlatObjectMetadataInFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/find-flat-object-metadata-in-flat-object-metadata-maps.util';
|
||||
import { getSubFlatObjectMetadataMapsOutOfFlatFieldMetadatas } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/get-sub-flat-object-metadata-maps-out-of-flat-field-metadatas.util';
|
||||
import { FailedFlatObjectMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-object-metadata/types/failed-flat-object-metadata-validation.type';
|
||||
import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { areFlatObjectMetadataNamesSyncedWithLabels } from 'src/engine/metadata-modules/flat-object-metadata/utils/are-flat-object-metadata-names-synced-with-labels.util';
|
||||
@@ -18,13 +24,44 @@ import {
|
||||
ObjectMetadataException,
|
||||
ObjectMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
|
||||
import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
|
||||
import { doesOtherObjectWithSameNameExists } from 'src/engine/metadata-modules/utils/validate-no-other-object-with-same-name-exists-or-throw.util';
|
||||
import { WorkspaceMigrationV2BuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.service';
|
||||
|
||||
export type ValidateOneFlatObjectMetadataArgs = {
|
||||
existingFlatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
flatObjectMetadataToValidate: FlatObjectMetadata;
|
||||
otherFlatObjectMetadataMapsToValidate?: FlatObjectMetadataMaps;
|
||||
workspaceId: string;
|
||||
const computeRelationTargetFlatObjectMetadataMapsForValidation = ({
|
||||
flatFieldMetadata,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
flatFieldMetadata: FlatFieldMetadata;
|
||||
flatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
}): FlatObjectMetadataMaps | undefined => {
|
||||
if (
|
||||
!isFlatFieldMetadataEntityOfType(
|
||||
flatFieldMetadata,
|
||||
FieldMetadataType.RELATION,
|
||||
) &&
|
||||
!isFlatFieldMetadataEntityOfType(
|
||||
flatFieldMetadata,
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const relationTargetFlatFieldMetadata =
|
||||
findRelationFlatFieldMetadataTargetFlatFieldMetadata({
|
||||
flatFieldMetadata,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(relationTargetFlatFieldMetadata)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return getSubFlatObjectMetadataMapsOutOfFlatFieldMetadatas({
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadatas: [relationTargetFlatFieldMetadata],
|
||||
});
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
@@ -70,9 +107,11 @@ export class FlatObjectMetadataValidatorService {
|
||||
public validateFlatObjectMetadataDeletion({
|
||||
existingFlatObjectMetadataMaps,
|
||||
objectMetadataToDeleteId,
|
||||
buildOptions,
|
||||
}: {
|
||||
existingFlatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
objectMetadataToDeleteId: string;
|
||||
buildOptions: WorkspaceMigrationV2BuilderOptions;
|
||||
}) {
|
||||
const errors: FailedFlatObjectMetadataValidationExceptions[] = [];
|
||||
|
||||
@@ -97,8 +136,8 @@ export class FlatObjectMetadataValidatorService {
|
||||
}
|
||||
|
||||
if (
|
||||
flatObjectMetadataToDelete.standardId !== null &&
|
||||
!flatObjectMetadataToDelete.isCustom
|
||||
!buildOptions.isSystemBuild &&
|
||||
isStandardMetadata(flatObjectMetadataToDelete)
|
||||
) {
|
||||
errors.push(
|
||||
new ObjectMetadataException(
|
||||
@@ -108,7 +147,7 @@ export class FlatObjectMetadataValidatorService {
|
||||
);
|
||||
}
|
||||
|
||||
if (flatObjectMetadataToDelete.isActive) {
|
||||
if (!buildOptions.isSystemBuild && flatObjectMetadataToDelete.isActive) {
|
||||
errors.push(
|
||||
new ObjectMetadataException(
|
||||
t`Active objects cannot be deleted`,
|
||||
@@ -124,10 +163,30 @@ export class FlatObjectMetadataValidatorService {
|
||||
public async validateFlatObjectMetadataCreation({
|
||||
existingFlatObjectMetadataMaps,
|
||||
flatObjectMetadataToValidate,
|
||||
workspaceId,
|
||||
}: ValidateOneFlatObjectMetadataArgs) {
|
||||
otherFlatObjectMetadataMapsToValidate,
|
||||
}: {
|
||||
existingFlatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
flatObjectMetadataToValidate: FlatObjectMetadata;
|
||||
otherFlatObjectMetadataMapsToValidate?: FlatObjectMetadataMaps;
|
||||
}) {
|
||||
const errors: FailedFlatObjectMetadataValidationExceptions[] = [];
|
||||
|
||||
if (
|
||||
isDefined(
|
||||
findFlatObjectMetadataInFlatObjectMetadataMaps({
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
objectMetadataId: flatObjectMetadataToValidate.id,
|
||||
}),
|
||||
)
|
||||
) {
|
||||
errors.push(
|
||||
new ObjectMetadataException(
|
||||
t`Object with same id already exists`,
|
||||
ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (flatObjectMetadataToValidate.isRemote) {
|
||||
errors.push(
|
||||
new ObjectMetadataException(
|
||||
@@ -146,7 +205,7 @@ export class FlatObjectMetadataValidatorService {
|
||||
|
||||
const allFlatFieldMetadatasValidationErrors: FailedFlatFieldMetadataValidationExceptions[] =
|
||||
[];
|
||||
let existingFlatObjectMetadataMapsWithFlatObjectMetadataToBeCreatedWithoutFields =
|
||||
let optimisticFlatObjectMetadataMaps =
|
||||
addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow({
|
||||
flatObjectMetadata: {
|
||||
...flatObjectMetadataToValidate,
|
||||
@@ -156,16 +215,20 @@ export class FlatObjectMetadataValidatorService {
|
||||
});
|
||||
|
||||
for (const flatFieldMetadataToValidate of flatObjectMetadataToValidate.flatFieldMetadatas) {
|
||||
const otherFlatObjectMetadataMapsToValidate = undefined; // TODO prastoin when implementing import
|
||||
|
||||
const flatFieldValidatorErrors =
|
||||
await this.flatFieldMetadataValidatorService.validateFlatFieldMetadataCreation(
|
||||
{
|
||||
existingFlatObjectMetadataMaps:
|
||||
existingFlatObjectMetadataMapsWithFlatObjectMetadataToBeCreatedWithoutFields,
|
||||
existingFlatObjectMetadataMaps: optimisticFlatObjectMetadataMaps,
|
||||
flatFieldMetadataToValidate,
|
||||
workspaceId,
|
||||
otherFlatObjectMetadataMapsToValidate,
|
||||
workspaceId: flatObjectMetadataToValidate.workspaceId,
|
||||
otherFlatObjectMetadataMapsToValidate: isDefined(
|
||||
otherFlatObjectMetadataMapsToValidate,
|
||||
)
|
||||
? computeRelationTargetFlatObjectMetadataMapsForValidation({
|
||||
flatFieldMetadata: flatFieldMetadataToValidate,
|
||||
flatObjectMetadataMaps: otherFlatObjectMetadataMapsToValidate,
|
||||
})
|
||||
: undefined,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -174,11 +237,10 @@ export class FlatObjectMetadataValidatorService {
|
||||
continue;
|
||||
}
|
||||
|
||||
existingFlatObjectMetadataMapsWithFlatObjectMetadataToBeCreatedWithoutFields =
|
||||
optimisticFlatObjectMetadataMaps =
|
||||
addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow({
|
||||
flatFieldMetadata: flatFieldMetadataToValidate,
|
||||
flatObjectMetadataMaps:
|
||||
existingFlatObjectMetadataMapsWithFlatObjectMetadataToBeCreatedWithoutFields,
|
||||
flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+8
-5
@@ -5,7 +5,7 @@ import {
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { getRelationFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/get-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 { isFlatFieldMetadataEntityOfType } 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 { findFlatObjectMetadataInFlatObjectMetadataMaps } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/find-flat-object-metadata-in-flat-object-metadata-maps.util';
|
||||
@@ -58,10 +58,13 @@ export const fromDeleteObjectInputToFlatFieldMetadatasToDelete = ({
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
)
|
||||
) {
|
||||
return getRelationFlatFieldMetadatasOrThrow({
|
||||
existingFlatObjectMetadataMaps,
|
||||
flatFieldMetadata,
|
||||
});
|
||||
const relationTargetFlatFieldMetadata =
|
||||
findRelationFlatFieldMetadataTargetFlatFieldMetadataOrThrow({
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatFieldMetadata,
|
||||
});
|
||||
|
||||
return [flatFieldMetadata, relationTargetFlatFieldMetadata];
|
||||
}
|
||||
|
||||
return flatFieldMetadata;
|
||||
|
||||
+3
-5
@@ -19,12 +19,12 @@ export const validateFlatObjectMetadataIdentifiers = (
|
||||
flatObjectMetadata;
|
||||
|
||||
if (isDefined(labelIdentifierFieldMetadataId)) {
|
||||
const relatedFlatFieldMetadata = flatObjectMetadata.flatFieldMetadatas.find(
|
||||
const flatFieldMetadata = flatObjectMetadata.flatFieldMetadatas.find(
|
||||
(flatFieldMetadata) =>
|
||||
flatFieldMetadata.id === labelIdentifierFieldMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(relatedFlatFieldMetadata)) {
|
||||
if (!isDefined(flatFieldMetadata)) {
|
||||
errors.push(
|
||||
new ObjectMetadataException(
|
||||
'labelIdentifierFieldMetadataId validation failed: related field metadata not found',
|
||||
@@ -34,9 +34,7 @@ export const validateFlatObjectMetadataIdentifiers = (
|
||||
},
|
||||
),
|
||||
);
|
||||
} else if (
|
||||
!isLabelIdentifierFieldMetadataTypes(relatedFlatFieldMetadata.type)
|
||||
) {
|
||||
} else if (!isLabelIdentifierFieldMetadataTypes(flatFieldMetadata.type)) {
|
||||
errors.push(
|
||||
new ObjectMetadataException(
|
||||
'labelIdentifierFieldMetadataId validation failed: field type not compatible',
|
||||
|
||||
Reference in New Issue
Block a user