Files
twenty/packages/twenty-server/src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util.ts
T
Paul Rastoin 29a4f4d685 CreateFieldInput transpilation to FlatFieldMetadata, FlatFieldMetadata validation (#13493)
# Introduction
Following https://github.com/twentyhq/twenty/pull/13420

What has been done:
- `CreateFieldInput` transpilation to `FlatFieldMetadata`
- `FlatFieldMetadata` validator service
- A lof of transpilation utils from `input` to `flatObject` or
`flatField`
- Created dedicated v2 api metadata services
- Introducing `inferDeletionFromMissingObjectFieldIndex` in the builder,
to avoid diffing every object and field of the current workspace we
allow only generating create/update migration operations, usefull when
passing by the api metadata


## We still need to in another PR:
- Implement a strong unit test coverage and critical functions and
services
- Finalize flat field metadata validation exception for `options`
`defaultValue` `settings` and `relations`
- Finalize `flatObjectMetadata` validation and v2 service refactor
- Plug the new service when feature flag is enabled
2025-07-30 15:08:11 +02:00

56 lines
1.3 KiB
TypeScript

import camelCase from 'lodash.camelcase';
import { slugify } from 'transliteration';
import { isDefined } from 'twenty-shared/utils';
import {
InvalidMetadataException,
InvalidMetadataExceptionCode,
} from 'src/engine/metadata-modules/utils/exceptions/invalid-metadata.exception';
export const validateNameAndLabelAreSyncOrThrow = ({
label,
name,
}: {
label: string;
name: string;
}) => {
const computedName = computeMetadataNameFromLabel(label);
if (name !== computedName) {
throw new InvalidMetadataException(
`Name is not synced with label. Expected name: "${computedName}", got ${name}`,
InvalidMetadataExceptionCode.NAME_NOT_SYNCED_WITH_LABEL,
);
}
};
export const computeMetadataNameFromLabel = (label: string): string => {
if (!isDefined(label)) {
throw new InvalidMetadataException(
'Label is required',
InvalidMetadataExceptionCode.LABEL_REQUIRED,
);
}
const prefixedLabel = /^\d/.test(label) ? `n${label}` : label;
if (prefixedLabel === '') {
return '';
}
const formattedString = slugify(prefixedLabel, {
trim: true,
separator: '_',
allowedChars: 'a-zA-Z0-9',
});
if (formattedString === '') {
throw new InvalidMetadataException(
`Invalid label: "${label}"`,
InvalidMetadataExceptionCode.INVALID_LABEL,
);
}
return camelCase(formattedString);
};