Fail slow + structured validator error response scoped by object and fields (#13980)
# Introduction
Example of returned response: ( snapshot copy don't mind jest expect any
values )
```json
{
"extensions": {
"code": "BAD_USER_INPUT",
"errors": {
"fieldMetadata": [
{
"errors": [
{
"code": "INVALID_FIELD_INPUT",
"message": "Name is too long",
"userFriendlyMessage": "Name is too long",
"value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
},
],
"id": Any<String>,
"name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"objectMetadataId": Any<String>,
"operation": "create_field",
},
{
"errors": [
{
"code": "INVALID_FIELD_INPUT",
"message": "Name is too long",
"userFriendlyMessage": "Name is too long",
"value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
},
],
"id": Any<String>,
"name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"objectMetadataId": Any<String>,
"operation": "create_field",
},
{
"errors": [
{
"code": "INVALID_FIELD_INPUT",
"message": "Name is too long",
"userFriendlyMessage": "Name is too long",
"value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
},
],
"id": Any<String>,
"name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"objectMetadataId": Any<String>,
"operation": "create_field",
},
{
"errors": [
{
"code": "INVALID_FIELD_INPUT",
"message": "Name is too long",
"userFriendlyMessage": "Name is too long",
"value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
},
],
"id": Any<String>,
"name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"objectMetadataId": Any<String>,
"operation": "create_field",
},
{
"errors": [
{
"code": "INVALID_FIELD_INPUT",
"message": "Name is too long",
"userFriendlyMessage": "Name is too long",
"value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
},
],
"id": Any<String>,
"name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"objectMetadataId": Any<String>,
"operation": "create_field",
},
],
"objectMetadata": [
{
"errors": [
{
"code": "INVALID_OBJECT_INPUT",
"message": "Name is too long",
"value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
},
],
"fields": [],
"id": Any<String>,
"namePlural": "listingas",
"nameSingular": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"operation": "create_object",
},
],
},
"message": "Validation failed for 1 object(s) and 5 field(s)",
"summary": {
"invalidFields": 5,
"invalidObjects": 1,
"totalErrors": 6,
},
"userFriendlyMessage": "Validation failed for 1 object(s) and 5 field(s)",
},
"message": "Multiple validation errors occurred while creating object",
"name": "GraphQLError",
}
```
## Note
We should put in place integrations tests on REST API too, in order to
ensure we receive the same response error
This commit is contained in:
+17
-13
@@ -1,5 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { isDefined } from 'class-validator';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
@@ -10,8 +11,8 @@ import {
|
||||
FieldMetadataExceptionCode,
|
||||
} 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 { type FlatFieldMetadataTypeValidator } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-type-validator.type';
|
||||
import { FlatFieldMetadataValidationError } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-validation-error.type';
|
||||
import { isEnumValidateOneFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-enum-validate-one-field-metadata-args.util';
|
||||
import { validateEnumSelectFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-enum-flat-field-metadata.util';
|
||||
import { validateRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-relation-flat-field-metadata.util';
|
||||
@@ -60,10 +61,11 @@ export class FlatFieldMetadataTypeValidatorService {
|
||||
|
||||
if (!isMorphRelationEnabled) {
|
||||
return [
|
||||
new FieldMetadataException(
|
||||
'Morph relation feature is disabled',
|
||||
FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED,
|
||||
),
|
||||
{
|
||||
code: FieldMetadataExceptionCode.UNCOVERED_FIELD_METADATA_TYPE_VALIDATION,
|
||||
message: 'Morph relation feature flag is disabled',
|
||||
userFriendlyMessage: t`Morph relation fields are disabled for your workspace`,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -72,7 +74,7 @@ export class FlatFieldMetadataTypeValidatorService {
|
||||
MULTI_SELECT: (args) => {
|
||||
if (!isEnumValidateOneFieldMetadata(args)) {
|
||||
throw new FieldMetadataException(
|
||||
'Should never occur, invaliad enum field metadata type',
|
||||
'Should never occur, invalid enum field metadata type',
|
||||
FieldMetadataExceptionCode.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
@@ -94,7 +96,7 @@ export class FlatFieldMetadataTypeValidatorService {
|
||||
RATING: (args) => {
|
||||
if (!isEnumValidateOneFieldMetadata(args)) {
|
||||
throw new FieldMetadataException(
|
||||
'Should never occur, invaliad enum field metadata type',
|
||||
'Should never occur, invalid enum field metadata type',
|
||||
FieldMetadataExceptionCode.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
@@ -114,7 +116,7 @@ export class FlatFieldMetadataTypeValidatorService {
|
||||
SELECT: (args) => {
|
||||
if (!isEnumValidateOneFieldMetadata(args)) {
|
||||
throw new FieldMetadataException(
|
||||
'Should never occur, invaliad enum field metadata type',
|
||||
'Should never occur, invalid enum field metadata type',
|
||||
FieldMetadataExceptionCode.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
@@ -140,7 +142,7 @@ export class FlatFieldMetadataTypeValidatorService {
|
||||
workspaceId,
|
||||
otherFlatObjectMetadataMapsToValidate,
|
||||
}: ValidateOneFieldMetadataArgs<T>): Promise<
|
||||
FailedFlatFieldMetadataValidationExceptions[]
|
||||
FlatFieldMetadataValidationError[]
|
||||
> {
|
||||
const fieldMetadataTypeValidator =
|
||||
this.FIELD_METADATA_TYPE_VALIDATOR_HASHMAP[
|
||||
@@ -149,10 +151,12 @@ export class FlatFieldMetadataTypeValidatorService {
|
||||
|
||||
if (!isDefined(fieldMetadataTypeValidator)) {
|
||||
return [
|
||||
new FieldMetadataException(
|
||||
'Unsupported field metadata type',
|
||||
FieldMetadataExceptionCode.UNCOVERED_FIELD_METADATA_TYPE_VALIDATION,
|
||||
),
|
||||
{
|
||||
code: FieldMetadataExceptionCode.UNCOVERED_FIELD_METADATA_TYPE_VALIDATION,
|
||||
message: `Unsupported field metadata type ${flatFieldMetadataToValidate.type}`,
|
||||
value: flatFieldMetadataToValidate.type,
|
||||
userFriendlyMessage: t`Unsupported field metadata type ${flatFieldMetadataToValidate.type}`,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
+118
-129
@@ -4,13 +4,10 @@ import { t } from '@lingui/core/macro';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FieldMetadataException,
|
||||
FieldMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
|
||||
import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
|
||||
import { FLAT_FIELD_METADATA_RELATION_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/flat-field-metadata/constants/flat-field-metadata-relation-properties-to-compare.constant';
|
||||
import { FlatFieldMetadataTypeValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service';
|
||||
import { type FailedFlatFieldMetadataValidationExceptions } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type';
|
||||
import { FailedFlatFieldMetadataValidation } from 'src/engine/metadata-modules/flat-field-metadata/types/failed-flat-field-metadata-validation.type';
|
||||
import { FlatFieldMetadataRelationPropertiesToCompare } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-relation-properties-to-compare.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { compareTwoFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/compare-two-flat-field-metadata.util';
|
||||
@@ -21,14 +18,6 @@ import { validateFlatFieldMetadataNameAvailability } from 'src/engine/metadata-m
|
||||
import { validateFlatFieldMetadataName } from 'src/engine/metadata-modules/flat-field-metadata/validators/utils/validate-flat-field-metadata-name.util';
|
||||
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';
|
||||
import {
|
||||
ObjectMetadataException,
|
||||
ObjectMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
|
||||
import {
|
||||
InvalidMetadataException,
|
||||
InvalidMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/utils/exceptions/invalid-metadata.exception';
|
||||
import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
|
||||
|
||||
export type ValidateOneFieldMetadataArgs<
|
||||
@@ -50,34 +39,41 @@ export class FlatFieldMetadataValidatorService {
|
||||
existingFlatObjectMetadataMaps,
|
||||
flatFieldMetadataToValidate: updatedFlatFieldMetadata,
|
||||
workspaceId,
|
||||
}: ValidateOneFieldMetadataArgs<T>): Promise<
|
||||
FailedFlatFieldMetadataValidationExceptions[]
|
||||
> {
|
||||
const errors: FailedFlatFieldMetadataValidationExceptions[] = [];
|
||||
}: ValidateOneFieldMetadataArgs<T>): Promise<FailedFlatFieldMetadataValidation> {
|
||||
const validationResult: FailedFlatFieldMetadataValidation = {
|
||||
type: 'update_field',
|
||||
errors: [],
|
||||
fieldMinimalInformation: {
|
||||
id: updatedFlatFieldMetadata.id,
|
||||
name: updatedFlatFieldMetadata.name,
|
||||
objectMetadataId: updatedFlatFieldMetadata.objectMetadataId,
|
||||
},
|
||||
};
|
||||
const flatObjectMetadataWithFlatFieldMaps =
|
||||
existingFlatObjectMetadataMaps.byId[
|
||||
updatedFlatFieldMetadata.objectMetadataId
|
||||
];
|
||||
|
||||
if (!isDefined(flatObjectMetadataWithFlatFieldMaps)) {
|
||||
return [
|
||||
new FieldMetadataException(
|
||||
'field metadata to update object metadata not found',
|
||||
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||
),
|
||||
];
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||
message: 'field metadata to update object metadata not found',
|
||||
userFriendlyMessage: t`Object related to field to update not found`,
|
||||
});
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
if (
|
||||
!isDefined(
|
||||
flatObjectMetadataWithFlatFieldMaps.labelIdentifierFieldMetadataId,
|
||||
)
|
||||
) {
|
||||
errors.push(
|
||||
new FieldMetadataException(
|
||||
'Label identifier field metadata id does not exist',
|
||||
FieldMetadataExceptionCode.LABEL_IDENTIFIER_FIELD_METADATA_ID_NOT_FOUND,
|
||||
),
|
||||
);
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.LABEL_IDENTIFIER_FIELD_METADATA_ID_NOT_FOUND,
|
||||
message: 'Label identifier field metadata id does not exist',
|
||||
userFriendlyMessage: t`Object related to updated field does not have a label identifier`,
|
||||
});
|
||||
}
|
||||
|
||||
const existingFlatFieldMetadataToUpdate =
|
||||
@@ -86,14 +82,13 @@ export class FlatFieldMetadataValidatorService {
|
||||
];
|
||||
|
||||
if (!isDefined(existingFlatFieldMetadataToUpdate)) {
|
||||
errors.push(
|
||||
new FieldMetadataException(
|
||||
'field metadata to update not found',
|
||||
FieldMetadataExceptionCode.FIELD_METADATA_NOT_FOUND,
|
||||
),
|
||||
);
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.FIELD_METADATA_NOT_FOUND,
|
||||
message: 'field metadata to update not found',
|
||||
userFriendlyMessage: t`Field to update not found`,
|
||||
});
|
||||
|
||||
return errors;
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
const updates = compareTwoFlatFieldMetadata({
|
||||
@@ -121,12 +116,11 @@ export class FlatFieldMetadataValidatorService {
|
||||
);
|
||||
|
||||
if (relationNonEditableUpdatedProperties.length > 0) {
|
||||
errors.push(
|
||||
new FieldMetadataException(
|
||||
`Forbidden updated properties for relation field metadata: ${relationNonEditableUpdatedProperties.join(', ')}`,
|
||||
FieldMetadataExceptionCode.FIELD_MUTATION_NOT_ALLOWED,
|
||||
),
|
||||
);
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.FIELD_MUTATION_NOT_ALLOWED,
|
||||
message: `Forbidden updated properties for relation field metadata: ${relationNonEditableUpdatedProperties.join(', ')}`,
|
||||
userFriendlyMessage: t`Forbidden updated properties for relation field metadata`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,31 +130,24 @@ export class FlatFieldMetadataValidatorService {
|
||||
);
|
||||
|
||||
if (updates.some((update) => update.property === 'name')) {
|
||||
errors.push(
|
||||
validationResult.errors.push(
|
||||
...validateFlatFieldMetadataName(updatedFlatFieldMetadata.name),
|
||||
);
|
||||
|
||||
const nameAvailabilityValidationError =
|
||||
validateFlatFieldMetadataNameAvailability({
|
||||
...validateFlatFieldMetadataNameAvailability({
|
||||
name: updatedFlatFieldMetadata.name,
|
||||
flatObjectMetadata: flatObjectMetadata,
|
||||
});
|
||||
|
||||
if (isDefined(nameAvailabilityValidationError)) {
|
||||
errors.push(nameAvailabilityValidationError);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
updatedFlatFieldMetadata.isLabelSyncedWithName &&
|
||||
!isFlatFieldMetadataNameSyncedWithLabel(updatedFlatFieldMetadata)
|
||||
) {
|
||||
errors.push(
|
||||
new InvalidMetadataException(
|
||||
t`Name is not synced with label.`,
|
||||
InvalidMetadataExceptionCode.NAME_NOT_SYNCED_WITH_LABEL,
|
||||
),
|
||||
);
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.FIELD_MUTATION_NOT_ALLOWED,
|
||||
message: `Name is not synced with label.`,
|
||||
userFriendlyMessage: t`Updated field name is not synced with label`,
|
||||
});
|
||||
}
|
||||
|
||||
const fieldMetadataTypeValidationErrors =
|
||||
@@ -173,10 +160,10 @@ export class FlatFieldMetadataValidatorService {
|
||||
);
|
||||
|
||||
if (fieldMetadataTypeValidationErrors.length > 0) {
|
||||
errors.push(...fieldMetadataTypeValidationErrors);
|
||||
validationResult.errors.push(...fieldMetadataTypeValidationErrors);
|
||||
}
|
||||
|
||||
return errors;
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
validateFlatFieldMetadataDeletion({
|
||||
@@ -185,8 +172,16 @@ export class FlatFieldMetadataValidatorService {
|
||||
}: {
|
||||
flatFieldMetadataToDelete: FlatFieldMetadata;
|
||||
existingFlatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
}): FailedFlatFieldMetadataValidationExceptions[] {
|
||||
const errors: FailedFlatFieldMetadataValidationExceptions[] = [];
|
||||
}): FailedFlatFieldMetadataValidation {
|
||||
const validationResult: FailedFlatFieldMetadataValidation = {
|
||||
type: 'delete_field',
|
||||
errors: [],
|
||||
fieldMinimalInformation: {
|
||||
id: flatFieldMetadataToDelete.id,
|
||||
name: flatFieldMetadataToDelete.name,
|
||||
objectMetadataId: flatFieldMetadataToDelete.objectMetadataId,
|
||||
},
|
||||
};
|
||||
|
||||
const flatObjectMetadataWithFieldMaps =
|
||||
existingFlatObjectMetadataMaps.byId[
|
||||
@@ -194,26 +189,22 @@ export class FlatFieldMetadataValidatorService {
|
||||
];
|
||||
|
||||
if (!isDefined(flatObjectMetadataWithFieldMaps)) {
|
||||
errors.push(
|
||||
new FieldMetadataException(
|
||||
'field to delete object metadata not found',
|
||||
FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||
),
|
||||
);
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||
message: 'field to delete object metadata not found',
|
||||
userFriendlyMessage: t`Object related to field to delete not found`,
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
flatObjectMetadataWithFieldMaps.labelIdentifierFieldMetadataId ===
|
||||
flatFieldMetadataToDelete.id
|
||||
) {
|
||||
errors.push(
|
||||
new FieldMetadataException(
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.FIELD_MUTATION_NOT_ALLOWED,
|
||||
message:
|
||||
'Cannot delete, please update the label identifier field first',
|
||||
FieldMetadataExceptionCode.FIELD_MUTATION_NOT_ALLOWED,
|
||||
{
|
||||
userFriendlyMessage: t`Cannot delete, please update the label identifier field first`,
|
||||
},
|
||||
),
|
||||
);
|
||||
userFriendlyMessage: t`Cannot delete, please update the label identifier field first`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,27 +220,25 @@ export class FlatFieldMetadataValidatorService {
|
||||
isStandardMetadata(flatFieldMetadataToDelete) &&
|
||||
!isRelationFieldAndRelationTargetObjectMetadataHasBeenDeleted
|
||||
) {
|
||||
errors.push(
|
||||
new FieldMetadataException(
|
||||
"Standard Fields can't be deleted",
|
||||
FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
|
||||
),
|
||||
);
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
|
||||
message: "Standard Fields can't be deleted",
|
||||
userFriendlyMessage: t`Standard fields cannot be deleted`,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
flatFieldMetadataToDelete.isActive &&
|
||||
!isRelationFieldAndRelationTargetObjectMetadataHasBeenDeleted
|
||||
) {
|
||||
errors.push(
|
||||
new FieldMetadataException(
|
||||
"Active fields can't be deleted",
|
||||
FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
|
||||
),
|
||||
);
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
|
||||
message: "Active fields can't be deleted",
|
||||
userFriendlyMessage: t`Active fields cannot be deleted`,
|
||||
});
|
||||
}
|
||||
|
||||
return errors;
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
async validateFlatFieldMetadataCreation<
|
||||
@@ -259,10 +248,16 @@ export class FlatFieldMetadataValidatorService {
|
||||
flatFieldMetadataToValidate,
|
||||
otherFlatObjectMetadataMapsToValidate,
|
||||
workspaceId,
|
||||
}: ValidateOneFieldMetadataArgs<T>): Promise<
|
||||
FailedFlatFieldMetadataValidationExceptions[]
|
||||
> {
|
||||
const errors: FailedFlatFieldMetadataValidationExceptions[] = [];
|
||||
}: ValidateOneFieldMetadataArgs<T>): Promise<FailedFlatFieldMetadataValidation> {
|
||||
const validationResult: FailedFlatFieldMetadataValidation = {
|
||||
errors: [],
|
||||
fieldMinimalInformation: {
|
||||
id: flatFieldMetadataToValidate.id,
|
||||
name: flatFieldMetadataToValidate.name,
|
||||
objectMetadataId: flatFieldMetadataToValidate.objectMetadataId,
|
||||
},
|
||||
type: 'create_field',
|
||||
};
|
||||
|
||||
const parentFlatObjectMetadata =
|
||||
otherFlatObjectMetadataMapsToValidate?.byId[
|
||||
@@ -273,65 +268,59 @@ export class FlatFieldMetadataValidatorService {
|
||||
];
|
||||
|
||||
if (!isDefined(parentFlatObjectMetadata)) {
|
||||
errors.push(
|
||||
new FieldMetadataException(
|
||||
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,
|
||||
),
|
||||
);
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND,
|
||||
message: isDefined(otherFlatObjectMetadataMapsToValidate)
|
||||
? 'Object metadata not found in both existing and about to be created object metadatas'
|
||||
: 'Object metadata not found',
|
||||
userFriendlyMessage: t`Field to create related object not found`,
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
isDefined(
|
||||
parentFlatObjectMetadata.fieldsById[flatFieldMetadataToValidate.id],
|
||||
)
|
||||
) {
|
||||
errors.push(
|
||||
new ObjectMetadataException(
|
||||
'Field with same id already exists in object',
|
||||
ObjectMetadataExceptionCode.OBJECT_MUTATION_NOT_ALLOWED,
|
||||
),
|
||||
);
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.FIELD_ALREADY_EXISTS,
|
||||
message: 'Field with same id already exists in object',
|
||||
userFriendlyMessage: t`Field already exists`,
|
||||
});
|
||||
}
|
||||
|
||||
if (parentFlatObjectMetadata.isRemote === true) {
|
||||
errors.push(
|
||||
new ObjectMetadataException(
|
||||
'Remote objects are read-only',
|
||||
ObjectMetadataExceptionCode.OBJECT_MUTATION_NOT_ALLOWED,
|
||||
),
|
||||
);
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.FIELD_MUTATION_NOT_ALLOWED,
|
||||
message: 'Remote objects are read-only',
|
||||
userFriendlyMessage: t`Remote objects are not production ready yet`,
|
||||
});
|
||||
}
|
||||
|
||||
const failedNameAvailabilityValidation =
|
||||
validateFlatFieldMetadataNameAvailability({
|
||||
validationResult.errors.push(
|
||||
...validateFlatFieldMetadataNameAvailability({
|
||||
name: flatFieldMetadataToValidate.name,
|
||||
flatObjectMetadata: parentFlatObjectMetadata,
|
||||
});
|
||||
|
||||
if (isDefined(failedNameAvailabilityValidation)) {
|
||||
errors.push(failedNameAvailabilityValidation);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
flatFieldMetadataToValidate.isLabelSyncedWithName &&
|
||||
!isFlatFieldMetadataNameSyncedWithLabel(flatFieldMetadataToValidate)
|
||||
) {
|
||||
errors.push(
|
||||
new InvalidMetadataException(
|
||||
t`Name is not synced with label.`,
|
||||
InvalidMetadataExceptionCode.NAME_NOT_SYNCED_WITH_LABEL,
|
||||
),
|
||||
);
|
||||
validationResult.errors.push({
|
||||
code: FieldMetadataExceptionCode.NAME_NOT_SYNCED_WITH_LABEL,
|
||||
message: `Name is not synced with label`,
|
||||
userFriendlyMessage: t`Field name is not synced with field label`,
|
||||
value: flatFieldMetadataToValidate.label,
|
||||
});
|
||||
}
|
||||
|
||||
errors.push(
|
||||
validationResult.errors.push(
|
||||
...validateFlatFieldMetadataName(flatFieldMetadataToValidate.name),
|
||||
);
|
||||
|
||||
errors.push(
|
||||
validationResult.errors.push(
|
||||
...(await this.flatFieldMetadataTypeValidatorService.validateFlatFieldMetadataTypeSpecificities(
|
||||
{
|
||||
existingFlatObjectMetadataMaps,
|
||||
@@ -342,6 +331,6 @@ export class FlatFieldMetadataValidatorService {
|
||||
)),
|
||||
);
|
||||
|
||||
return errors;
|
||||
return validationResult;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user