[Fix] Prevent fields name conflicts with composite subfields names (#6713)
At field creation we are checking the availability of the name by comparing it to the other fields' names' on the object; but for composite fields the fields' names' as indicated in the repository do not exactly match the column names' on the tables (e.g "createdBy" field is actually represented by columns createdByName, createdBySource etc.). In this PR we prevent the conflict with the standard composite fields' names. There is still room for errors with the custom composite fields: for example a custom composite field "address" of type address on a custom object "listing" will introduce the columns addressAddressStreet1, addressAddressStreet2 etc. while we won't prevent the user from later creating a custom field named "addressAddressStreet1". For now I decided not to tackle this as this seem extremely edgy + would impact performance on creation of all fields while never actually useful (I think).
This commit is contained in:
@ -2,6 +2,12 @@ import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/com
|
||||
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
|
||||
export const FIELD_LINKS_MOCK_NAME = 'fieldLinks';
|
||||
export const FIELD_CURRENCY_MOCK_NAME = 'fieldCurrency';
|
||||
export const FIELD_ADDRESS_MOCK_NAME = 'fieldAddress';
|
||||
export const FIELD_ACTOR_MOCK_NAME = 'fieldActor';
|
||||
export const FIELD_FULL_NAME_MOCK_NAME = 'fieldFullName';
|
||||
|
||||
export const fieldNumberMock = {
|
||||
name: 'fieldNumber',
|
||||
type: FieldMetadataType.NUMBER,
|
||||
@ -16,15 +22,8 @@ export const fieldTextMock = {
|
||||
defaultValue: null,
|
||||
};
|
||||
|
||||
export const fieldLinkMock = {
|
||||
name: 'fieldLink',
|
||||
type: FieldMetadataType.LINK,
|
||||
isNullable: false,
|
||||
defaultValue: { label: '', url: '' },
|
||||
};
|
||||
|
||||
export const fieldCurrencyMock = {
|
||||
name: 'fieldCurrency',
|
||||
name: FIELD_CURRENCY_MOCK_NAME,
|
||||
type: FieldMetadataType.CURRENCY,
|
||||
isNullable: true,
|
||||
defaultValue: { amountMicros: null, currencyCode: "''" },
|
||||
@ -89,7 +88,7 @@ export const fieldRelationMock = {
|
||||
};
|
||||
|
||||
const fieldLinksMock = {
|
||||
name: 'fieldLinks',
|
||||
name: FIELD_LINKS_MOCK_NAME,
|
||||
type: FieldMetadataType.LINKS,
|
||||
isNullable: false,
|
||||
defaultValue: [
|
||||
@ -147,7 +146,7 @@ const fieldNumericMock = {
|
||||
};
|
||||
|
||||
const fieldFullNameMock = {
|
||||
name: 'fieldFullName',
|
||||
name: FIELD_FULL_NAME_MOCK_NAME,
|
||||
type: FieldMetadataType.FULL_NAME,
|
||||
isNullable: true,
|
||||
defaultValue: { firstName: '', lastName: '' },
|
||||
@ -168,7 +167,7 @@ const fieldPositionMock = {
|
||||
};
|
||||
|
||||
const fieldAddressMock = {
|
||||
name: 'fieldAddress',
|
||||
name: FIELD_ADDRESS_MOCK_NAME,
|
||||
type: FieldMetadataType.ADDRESS,
|
||||
isNullable: true,
|
||||
defaultValue: {
|
||||
@ -198,7 +197,7 @@ const fieldRichTextMock = {
|
||||
};
|
||||
|
||||
const fieldActorMock = {
|
||||
name: 'fieldActor',
|
||||
name: FIELD_ACTOR_MOCK_NAME,
|
||||
type: FieldMetadataType.ACTOR,
|
||||
isNullable: true,
|
||||
defaultValue: {
|
||||
@ -217,7 +216,6 @@ export const fields = [
|
||||
fieldBooleanMock,
|
||||
fieldNumberMock,
|
||||
fieldNumericMock,
|
||||
fieldLinkMock,
|
||||
fieldLinksMock,
|
||||
fieldCurrencyMock,
|
||||
fieldFullNameMock,
|
||||
|
||||
@ -2,7 +2,7 @@ import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
|
||||
|
||||
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
|
||||
@ -52,7 +52,7 @@ export class ArgsAliasFactory {
|
||||
isCompositeFieldMetadataType(fieldMetadata.type)
|
||||
) {
|
||||
// Get composite type definition
|
||||
const compositeType = compositeTypeDefintions.get(fieldMetadata.type);
|
||||
const compositeType = compositeTypeDefinitions.get(fieldMetadata.type);
|
||||
|
||||
if (!compositeType) {
|
||||
this.logger.error(
|
||||
|
||||
@ -2,13 +2,13 @@ import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
|
||||
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { createCompositeFieldKey } from 'src/engine/api/graphql/workspace-query-builder/utils/composite-field-metadata.util';
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import {
|
||||
computeColumnName,
|
||||
computeCompositeColumnName,
|
||||
} from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
|
||||
@Injectable()
|
||||
export class FieldAliasFactory {
|
||||
@ -23,7 +23,7 @@ export class FieldAliasFactory {
|
||||
}
|
||||
|
||||
// If it's a composite field, we need to get the definition
|
||||
const compositeType = compositeTypeDefintions.get(fieldMetadata.type);
|
||||
const compositeType = compositeTypeDefinitions.get(fieldMetadata.type);
|
||||
|
||||
if (!compositeType) {
|
||||
this.logger.error(
|
||||
|
||||
@ -1,27 +1,27 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
|
||||
import { CompositeType } from 'src/engine/metadata-modules/field-metadata/interfaces/composite-type.interface';
|
||||
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
|
||||
|
||||
import { EnumTypeDefinitionFactory } from 'src/engine/api/graphql/workspace-schema-builder/factories/enum-type-definition.factory';
|
||||
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { CompositeObjectTypeDefinitionFactory } from 'src/engine/api/graphql/workspace-schema-builder/factories/composite-object-type-definition.factory';
|
||||
import { CompositeInputTypeDefinitionFactory } from 'src/engine/api/graphql/workspace-schema-builder/factories/composite-input-type-definition.factory';
|
||||
import { CompositeEnumTypeDefinitionFactory } from 'src/engine/api/graphql/workspace-schema-builder/factories/composite-enum-type-definition.factory';
|
||||
import { CompositeInputTypeDefinitionFactory } from 'src/engine/api/graphql/workspace-schema-builder/factories/composite-input-type-definition.factory';
|
||||
import { CompositeObjectTypeDefinitionFactory } from 'src/engine/api/graphql/workspace-schema-builder/factories/composite-object-type-definition.factory';
|
||||
import { EnumTypeDefinitionFactory } from 'src/engine/api/graphql/workspace-schema-builder/factories/enum-type-definition.factory';
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
|
||||
import { TypeDefinitionsStorage } from './storages/type-definitions.storage';
|
||||
import {
|
||||
ObjectTypeDefinitionFactory,
|
||||
ObjectTypeDefinitionKind,
|
||||
} from './factories/object-type-definition.factory';
|
||||
import { ConnectionTypeDefinitionFactory } from './factories/connection-type-definition.factory';
|
||||
import { EdgeTypeDefinitionFactory } from './factories/edge-type-definition.factory';
|
||||
import { ExtendObjectTypeDefinitionFactory } from './factories/extend-object-type-definition.factory';
|
||||
import {
|
||||
InputTypeDefinitionFactory,
|
||||
InputTypeDefinitionKind,
|
||||
} from './factories/input-type-definition.factory';
|
||||
import {
|
||||
ObjectTypeDefinitionFactory,
|
||||
ObjectTypeDefinitionKind,
|
||||
} from './factories/object-type-definition.factory';
|
||||
import { WorkspaceBuildSchemaOptions } from './interfaces/workspace-build-schema-optionts.interface';
|
||||
import { ConnectionTypeDefinitionFactory } from './factories/connection-type-definition.factory';
|
||||
import { EdgeTypeDefinitionFactory } from './factories/edge-type-definition.factory';
|
||||
import { ExtendObjectTypeDefinitionFactory } from './factories/extend-object-type-definition.factory';
|
||||
import { TypeDefinitionsStorage } from './storages/type-definitions.storage';
|
||||
import { objectContainsRelationField } from './utils/object-contains-relation-field';
|
||||
|
||||
@Injectable()
|
||||
@ -55,7 +55,7 @@ export class TypeDefinitionsGenerator {
|
||||
* GENERATE COMPOSITE TYPE OBJECTS
|
||||
*/
|
||||
private generateCompositeTypeDefs(options: WorkspaceBuildSchemaOptions) {
|
||||
const compositeTypeCollection = [...compositeTypeDefintions.values()];
|
||||
const compositeTypeCollection = [...compositeTypeDefinitions.values()];
|
||||
|
||||
this.logger.log(
|
||||
`Generating composite type objects: [${compositeTypeCollection
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import {
|
||||
fieldCurrencyMock,
|
||||
fieldLinkMock,
|
||||
fieldNumberMock,
|
||||
fieldTextMock,
|
||||
objectMetadataItemMock,
|
||||
@ -17,15 +16,6 @@ describe('mapFieldMetadataToGraphqlQuery', () => {
|
||||
expect(
|
||||
mapFieldMetadataToGraphqlQuery([objectMetadataItemMock], fieldTextMock),
|
||||
).toEqual('fieldText');
|
||||
expect(
|
||||
mapFieldMetadataToGraphqlQuery([objectMetadataItemMock], fieldLinkMock),
|
||||
).toEqual(`
|
||||
fieldLink
|
||||
{
|
||||
label
|
||||
url
|
||||
}
|
||||
`);
|
||||
expect(
|
||||
mapFieldMetadataToGraphqlQuery(
|
||||
[objectMetadataItemMock],
|
||||
|
||||
@ -2,7 +2,7 @@ import { BadRequestException } from '@nestjs/common';
|
||||
|
||||
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
|
||||
|
||||
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||
|
||||
@ -13,7 +13,7 @@ export const checkFields = (
|
||||
const fieldMetadataNames = objectMetadata.fields
|
||||
.map((field) => {
|
||||
if (isCompositeFieldMetadataType(field.type)) {
|
||||
const compositeType = compositeTypeDefintions.get(field.type);
|
||||
const compositeType = compositeTypeDefinitions.get(field.type);
|
||||
|
||||
if (!compositeType) {
|
||||
throw new BadRequestException(
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
|
||||
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
|
||||
import { Record } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface';
|
||||
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
|
||||
|
||||
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||
|
||||
@ -14,7 +14,7 @@ export const checkArrayFields = (
|
||||
const fieldMetadataNames = objectMetadata.fields
|
||||
.map((field) => {
|
||||
if (isCompositeFieldMetadataType(field.type)) {
|
||||
const compositeType = compositeTypeDefintions.get(field.type);
|
||||
const compositeType = compositeTypeDefinitions.get(field.type);
|
||||
|
||||
if (!compositeType) {
|
||||
throw new BadRequestException(
|
||||
|
||||
@ -54,7 +54,7 @@ describe('OrderByInputFactory', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handler complex fields', () => {
|
||||
it('should handle complex fields', () => {
|
||||
const request: any = {
|
||||
query: {
|
||||
order_by: 'fieldCurrency.amountMicros',
|
||||
@ -66,7 +66,7 @@ describe('OrderByInputFactory', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handler complex fields with direction', () => {
|
||||
it('should handle complex fields with direction', () => {
|
||||
const request: any = {
|
||||
query: {
|
||||
order_by: 'fieldCurrency.amountMicros[DescNullsLast]',
|
||||
@ -78,17 +78,17 @@ describe('OrderByInputFactory', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handler multiple complex fields with direction', () => {
|
||||
it('should handle multiple complex fields with direction', () => {
|
||||
const request: any = {
|
||||
query: {
|
||||
order_by:
|
||||
'fieldCurrency.amountMicros[DescNullsLast],fieldLink.label[AscNullsLast]',
|
||||
'fieldCurrency.amountMicros[DescNullsLast],fieldText.label[AscNullsLast]',
|
||||
},
|
||||
};
|
||||
|
||||
expect(service.create(request, objectMetadata)).toEqual([
|
||||
{ fieldCurrency: { amountMicros: OrderByDirection.DescNullsLast } },
|
||||
{ fieldLink: { label: OrderByDirection.AscNullsLast } },
|
||||
{ fieldText: { label: OrderByDirection.AscNullsLast } },
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@ -7,9 +7,11 @@ import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/fi
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
|
||||
describe('computeSchemaComponents', () => {
|
||||
it('should test all field types', () => {
|
||||
it('should test all non-deprecated field types', () => {
|
||||
expect(fields.map((field) => field.type)).toEqual(
|
||||
Object.keys(FieldMetadataType),
|
||||
Object.keys(FieldMetadataType).filter(
|
||||
(key) => key !== FieldMetadataType.LINK,
|
||||
),
|
||||
);
|
||||
});
|
||||
it('should compute schema components', () => {
|
||||
@ -55,13 +57,6 @@ describe('computeSchemaComponents', () => {
|
||||
fieldNumeric: {
|
||||
type: 'number',
|
||||
},
|
||||
fieldLink: {
|
||||
properties: {
|
||||
label: { type: 'string' },
|
||||
url: { type: 'string' },
|
||||
},
|
||||
type: 'object',
|
||||
},
|
||||
fieldLinks: {
|
||||
properties: {
|
||||
primaryLinkLabel: { type: 'string' },
|
||||
|
||||
@ -9,7 +9,7 @@ import {
|
||||
computeOrderByParameters,
|
||||
computeStartingAfterParameters,
|
||||
} from 'src/engine/core-modules/open-api/utils/parameters.utils';
|
||||
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { capitalize } from 'src/utils/capitalize';
|
||||
@ -74,7 +74,7 @@ const getSchemaComponentsProperties = (
|
||||
case FieldMetadataType.ACTOR:
|
||||
itemProperty = {
|
||||
type: 'object',
|
||||
properties: compositeTypeDefintions
|
||||
properties: compositeTypeDefinitions
|
||||
.get(field.type)
|
||||
?.properties?.reduce((properties, property) => {
|
||||
properties[property.name] = getFieldProperties(property.type);
|
||||
|
||||
@ -13,7 +13,7 @@ export type CompositeFieldsDefinitionFunction = (
|
||||
fieldMetadata?: FieldMetadataInterface,
|
||||
) => FieldMetadataInterface[];
|
||||
|
||||
export const compositeTypeDefintions = new Map<
|
||||
export const compositeTypeDefinitions = new Map<
|
||||
FieldMetadataType,
|
||||
CompositeType
|
||||
>([
|
||||
|
||||
@ -8,7 +8,7 @@ import { v4 as uuidV4 } from 'uuid';
|
||||
|
||||
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { DeleteOneFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/delete-field.input';
|
||||
import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
|
||||
@ -28,18 +28,19 @@ import {
|
||||
} from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { generateNullable } from 'src/engine/metadata-modules/field-metadata/utils/generate-nullable';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { assertMutationNotOnRemoteObject } from 'src/engine/metadata-modules/object-metadata/utils/assert-mutation-not-on-remote-object.util';
|
||||
import {
|
||||
RelationMetadataEntity,
|
||||
RelationMetadataType,
|
||||
} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { InvalidStringException } from 'src/engine/metadata-modules/utils/exceptions/invalid-string.exception';
|
||||
import { NameNotAvailableException } from 'src/engine/metadata-modules/utils/exceptions/name-not-available.exception';
|
||||
import { NameTooLongException } from 'src/engine/metadata-modules/utils/exceptions/name-too-long.exception';
|
||||
import { exceedsDatabaseIdentifierMaximumLength } from 'src/engine/metadata-modules/utils/validate-database-identifier-length.utils';
|
||||
import {
|
||||
InvalidStringException,
|
||||
NameTooLongException,
|
||||
validateMetadataNameOrThrow,
|
||||
} from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
|
||||
import { validateFieldNameAvailabilityOrThrow } from 'src/engine/metadata-modules/utils/validate-field-name-availability.utils';
|
||||
import { validateMetadataNameValidityOrThrow as validateFieldNameValidityOrThrow } from 'src/engine/metadata-modules/utils/validate-metadata-name-validity.utils';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||
import {
|
||||
@ -140,7 +141,10 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
);
|
||||
}
|
||||
|
||||
this.validateFieldMetadataInput<CreateFieldInput>(fieldMetadataInput);
|
||||
this.validateFieldMetadataInput<CreateFieldInput>(
|
||||
fieldMetadataInput,
|
||||
objectMetadata,
|
||||
);
|
||||
|
||||
const fieldAlreadyExists = await fieldMetadataRepository.findOne({
|
||||
where: {
|
||||
@ -355,7 +359,10 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
}
|
||||
}
|
||||
|
||||
this.validateFieldMetadataInput<UpdateFieldInput>(fieldMetadataInput);
|
||||
this.validateFieldMetadataInput<UpdateFieldInput>(
|
||||
fieldMetadataInput,
|
||||
objectMetadata,
|
||||
);
|
||||
|
||||
const updatableFieldInput =
|
||||
existingFieldMetadata.isCustom === false
|
||||
@ -485,7 +492,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
await fieldMetadataRepository.delete(fieldMetadata.id);
|
||||
|
||||
if (isCompositeFieldMetadataType(fieldMetadata.type)) {
|
||||
const compositeType = compositeTypeDefintions.get(fieldMetadata.type);
|
||||
const compositeType = compositeTypeDefinitions.get(fieldMetadata.type);
|
||||
|
||||
if (!compositeType) {
|
||||
throw new Error(
|
||||
@ -673,10 +680,14 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
|
||||
private validateFieldMetadataInput<
|
||||
T extends UpdateFieldInput | CreateFieldInput,
|
||||
>(fieldMetadataInput: T): T {
|
||||
>(fieldMetadataInput: T, objectMetadata: ObjectMetadataEntity): T {
|
||||
if (fieldMetadataInput.name) {
|
||||
try {
|
||||
validateMetadataNameOrThrow(fieldMetadataInput.name);
|
||||
validateFieldNameValidityOrThrow(fieldMetadataInput.name);
|
||||
validateFieldNameAvailabilityOrThrow(
|
||||
fieldMetadataInput.name,
|
||||
objectMetadata,
|
||||
);
|
||||
} catch (error) {
|
||||
if (error instanceof InvalidStringException) {
|
||||
throw new FieldMetadataException(
|
||||
@ -688,6 +699,11 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
`Name "${fieldMetadataInput.name}" exceeds 63 characters`,
|
||||
FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
|
||||
);
|
||||
} else if (error instanceof NameNotAvailableException) {
|
||||
throw new FieldMetadataException(
|
||||
`Name "${fieldMetadataInput.name}" is not available`,
|
||||
FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
|
||||
);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
|
||||
@ -4,11 +4,9 @@ import {
|
||||
ObjectMetadataException,
|
||||
ObjectMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
|
||||
import { InvalidStringException } from 'src/engine/metadata-modules/utils/exceptions/invalid-string.exception';
|
||||
import { exceedsDatabaseIdentifierMaximumLength } from 'src/engine/metadata-modules/utils/validate-database-identifier-length.utils';
|
||||
import {
|
||||
validateMetadataNameOrThrow,
|
||||
InvalidStringException,
|
||||
} from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
|
||||
import { validateMetadataNameValidityOrThrow } from 'src/engine/metadata-modules/utils/validate-metadata-name-validity.utils';
|
||||
import { camelCase } from 'src/utils/camel-case';
|
||||
|
||||
const coreObjectNames = [
|
||||
@ -96,7 +94,7 @@ const validateNameIsNotTooLongThrow = (name?: string) => {
|
||||
const validateNameCharactersOrThrow = (name?: string) => {
|
||||
try {
|
||||
if (name) {
|
||||
validateMetadataNameOrThrow(name);
|
||||
validateMetadataNameValidityOrThrow(name);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof InvalidStringException) {
|
||||
|
||||
@ -18,10 +18,9 @@ import {
|
||||
RelationMetadataException,
|
||||
RelationMetadataExceptionCode,
|
||||
} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.exception';
|
||||
import {
|
||||
InvalidStringException,
|
||||
validateMetadataNameOrThrow,
|
||||
} from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
|
||||
import { InvalidStringException } from 'src/engine/metadata-modules/utils/exceptions/invalid-string.exception';
|
||||
import { validateFieldNameAvailabilityOrThrow } from 'src/engine/metadata-modules/utils/validate-field-name-availability.utils';
|
||||
import { validateMetadataNameValidityOrThrow } from 'src/engine/metadata-modules/utils/validate-metadata-name-validity.utils';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||
import {
|
||||
@ -63,8 +62,8 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
||||
);
|
||||
|
||||
try {
|
||||
validateMetadataNameOrThrow(relationMetadataInput.fromName);
|
||||
validateMetadataNameOrThrow(relationMetadataInput.toName);
|
||||
validateMetadataNameValidityOrThrow(relationMetadataInput.fromName);
|
||||
validateMetadataNameValidityOrThrow(relationMetadataInput.toName);
|
||||
} catch (error) {
|
||||
if (error instanceof InvalidStringException) {
|
||||
throw new RelationMetadataException(
|
||||
@ -161,6 +160,15 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
||||
objectMetadataMap,
|
||||
'to',
|
||||
);
|
||||
|
||||
validateFieldNameAvailabilityOrThrow(
|
||||
relationMetadataInput.fromName,
|
||||
objectMetadataMap[relationMetadataInput.fromObjectMetadataId],
|
||||
);
|
||||
validateFieldNameAvailabilityOrThrow(
|
||||
relationMetadataInput.toName,
|
||||
objectMetadataMap[relationMetadataInput.toObjectMetadataId],
|
||||
);
|
||||
}
|
||||
|
||||
private async checkIfFieldMetadataRelationNameExists(
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
import {
|
||||
FIELD_ACTOR_MOCK_NAME,
|
||||
FIELD_ADDRESS_MOCK_NAME,
|
||||
FIELD_CURRENCY_MOCK_NAME,
|
||||
FIELD_FULL_NAME_MOCK_NAME,
|
||||
FIELD_LINKS_MOCK_NAME,
|
||||
objectMetadataItemMock,
|
||||
} from 'src/engine/api/__mocks__/object-metadata-item.mock';
|
||||
import { NameNotAvailableException } from 'src/engine/metadata-modules/utils/exceptions/name-not-available.exception';
|
||||
import { validateFieldNameAvailabilityOrThrow } from 'src/engine/metadata-modules/utils/validate-field-name-availability.utils';
|
||||
|
||||
describe('validateFieldNameAvailabilityOrThrow', () => {
|
||||
const objectMetadata = objectMetadataItemMock;
|
||||
|
||||
it('does not throw if name is not reserved', () => {
|
||||
const name = 'testName';
|
||||
|
||||
expect(() =>
|
||||
validateFieldNameAvailabilityOrThrow(name, objectMetadata),
|
||||
).not.toThrow();
|
||||
});
|
||||
|
||||
describe('error cases', () => {
|
||||
it('throws error with LINKS suffixes', () => {
|
||||
const name = `${FIELD_LINKS_MOCK_NAME}PrimaryLinkLabel`;
|
||||
|
||||
expect(() =>
|
||||
validateFieldNameAvailabilityOrThrow(name, objectMetadata),
|
||||
).toThrow(NameNotAvailableException);
|
||||
});
|
||||
it('throws error with CURRENCY suffixes', () => {
|
||||
const name = `${FIELD_CURRENCY_MOCK_NAME}AmountMicros`;
|
||||
|
||||
expect(() =>
|
||||
validateFieldNameAvailabilityOrThrow(name, objectMetadata),
|
||||
).toThrow(NameNotAvailableException);
|
||||
});
|
||||
it('throws error with FULL_NAME suffixes', () => {
|
||||
const name = `${FIELD_FULL_NAME_MOCK_NAME}FirstName`;
|
||||
|
||||
expect(() =>
|
||||
validateFieldNameAvailabilityOrThrow(name, objectMetadata),
|
||||
).toThrow(NameNotAvailableException);
|
||||
});
|
||||
it('throws error with ACTOR suffixes', () => {
|
||||
const name = `${FIELD_ACTOR_MOCK_NAME}Name`;
|
||||
|
||||
expect(() =>
|
||||
validateFieldNameAvailabilityOrThrow(name, objectMetadata),
|
||||
).toThrow(NameNotAvailableException);
|
||||
});
|
||||
it('throws error with ADDRESS suffixes', () => {
|
||||
const name = `${FIELD_ADDRESS_MOCK_NAME}AddressStreet1`;
|
||||
|
||||
expect(() =>
|
||||
validateFieldNameAvailabilityOrThrow(name, objectMetadata),
|
||||
).toThrow(NameNotAvailableException);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,26 +1,24 @@
|
||||
import {
|
||||
validateMetadataNameOrThrow,
|
||||
InvalidStringException,
|
||||
NameTooLongException,
|
||||
} from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
|
||||
import { InvalidStringException } from 'src/engine/metadata-modules/utils/exceptions/invalid-string.exception';
|
||||
import { NameTooLongException } from 'src/engine/metadata-modules/utils/exceptions/name-too-long.exception';
|
||||
import { validateMetadataNameValidityOrThrow } from 'src/engine/metadata-modules/utils/validate-metadata-name-validity.utils';
|
||||
|
||||
describe('validateMetadataNameOrThrow', () => {
|
||||
describe('validateMetadataNameValidityOrThrow', () => {
|
||||
it('does not throw if string is valid', () => {
|
||||
const input = 'testName';
|
||||
|
||||
expect(validateMetadataNameOrThrow(input)).not.toThrow;
|
||||
expect(validateMetadataNameValidityOrThrow(input)).not.toThrow;
|
||||
});
|
||||
it('throws error if string has spaces', () => {
|
||||
const input = 'name with spaces';
|
||||
|
||||
expect(() => validateMetadataNameOrThrow(input)).toThrow(
|
||||
expect(() => validateMetadataNameValidityOrThrow(input)).toThrow(
|
||||
InvalidStringException,
|
||||
);
|
||||
});
|
||||
it('throws error if string starts with capital letter', () => {
|
||||
const input = 'StringStartingWithCapitalLetter';
|
||||
|
||||
expect(() => validateMetadataNameOrThrow(input)).toThrow(
|
||||
expect(() => validateMetadataNameValidityOrThrow(input)).toThrow(
|
||||
InvalidStringException,
|
||||
);
|
||||
});
|
||||
@ -28,7 +26,7 @@ describe('validateMetadataNameOrThrow', () => {
|
||||
it('throws error if string has non latin characters', () => {
|
||||
const input = 'בְרִבְרִ';
|
||||
|
||||
expect(() => validateMetadataNameOrThrow(input)).toThrow(
|
||||
expect(() => validateMetadataNameValidityOrThrow(input)).toThrow(
|
||||
InvalidStringException,
|
||||
);
|
||||
});
|
||||
@ -36,7 +34,7 @@ describe('validateMetadataNameOrThrow', () => {
|
||||
it('throws error if starts with digits', () => {
|
||||
const input = '123string';
|
||||
|
||||
expect(() => validateMetadataNameOrThrow(input)).toThrow(
|
||||
expect(() => validateMetadataNameValidityOrThrow(input)).toThrow(
|
||||
InvalidStringException,
|
||||
);
|
||||
});
|
||||
@ -44,14 +42,15 @@ describe('validateMetadataNameOrThrow', () => {
|
||||
const inputWith63Characters =
|
||||
'thisIsAstringWithSixtyThreeCharacters11111111111111111111111111';
|
||||
|
||||
expect(validateMetadataNameOrThrow(inputWith63Characters)).not.toThrow;
|
||||
expect(validateMetadataNameValidityOrThrow(inputWith63Characters)).not
|
||||
.toThrow;
|
||||
});
|
||||
it('throws error if string is above 63 characters', () => {
|
||||
const inputWith64Characters =
|
||||
'thisIsAstringWithSixtyFourCharacters1111111111111111111111111111';
|
||||
|
||||
expect(() => validateMetadataNameOrThrow(inputWith64Characters)).toThrow(
|
||||
NameTooLongException,
|
||||
);
|
||||
expect(() =>
|
||||
validateMetadataNameValidityOrThrow(inputWith64Characters),
|
||||
).toThrow(NameTooLongException);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,7 @@
|
||||
export class InvalidStringException extends Error {
|
||||
constructor(string: string) {
|
||||
const message = `String "${string}" is not valid`;
|
||||
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
export class NameNotAvailableException extends Error {
|
||||
constructor(name: string) {
|
||||
const message = `Name "${name}" is not available`;
|
||||
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
export class NameTooLongException extends Error {
|
||||
constructor(string: string) {
|
||||
const message = `String "${string}" exceeds 63 characters limit`;
|
||||
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { NameNotAvailableException } from 'src/engine/metadata-modules/utils/exceptions/name-not-available.exception';
|
||||
|
||||
const getReservedCompositeFieldNames = (
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
) => {
|
||||
const reservedCompositeFieldsNames: string[] = [];
|
||||
|
||||
for (const field of objectMetadata.fields) {
|
||||
if (isCompositeFieldMetadataType(field.type)) {
|
||||
const base = field.name;
|
||||
const compositeType = compositeTypeDefinitions.get(field.type);
|
||||
|
||||
compositeType?.properties.map((property) =>
|
||||
reservedCompositeFieldsNames.push(
|
||||
computeCompositeColumnName(base, property),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return reservedCompositeFieldsNames;
|
||||
};
|
||||
|
||||
export const validateFieldNameAvailabilityOrThrow = (
|
||||
name: string,
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
) => {
|
||||
const reservedCompositeFieldsNames =
|
||||
getReservedCompositeFieldNames(objectMetadata);
|
||||
|
||||
if (reservedCompositeFieldsNames.includes(name)) {
|
||||
throw new NameNotAvailableException(name);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,14 @@
|
||||
import { InvalidStringException } from 'src/engine/metadata-modules/utils/exceptions/invalid-string.exception';
|
||||
import { NameTooLongException } from 'src/engine/metadata-modules/utils/exceptions/name-too-long.exception';
|
||||
import { exceedsDatabaseIdentifierMaximumLength } from 'src/engine/metadata-modules/utils/validate-database-identifier-length.utils';
|
||||
|
||||
const VALID_STRING_PATTERN = /^[a-z][a-zA-Z0-9]*$/;
|
||||
|
||||
export const validateMetadataNameValidityOrThrow = (name: string) => {
|
||||
if (!name.match(VALID_STRING_PATTERN)) {
|
||||
throw new InvalidStringException(name);
|
||||
}
|
||||
if (exceedsDatabaseIdentifierMaximumLength(name)) {
|
||||
throw new NameTooLongException(name);
|
||||
}
|
||||
};
|
||||
@ -1,28 +0,0 @@
|
||||
import { exceedsDatabaseIdentifierMaximumLength } from 'src/engine/metadata-modules/utils/validate-database-identifier-length.utils';
|
||||
|
||||
const VALID_STRING_PATTERN = /^[a-z][a-zA-Z0-9]*$/;
|
||||
|
||||
export const validateMetadataNameOrThrow = (name: string) => {
|
||||
if (!name.match(VALID_STRING_PATTERN)) {
|
||||
throw new InvalidStringException(name);
|
||||
}
|
||||
if (exceedsDatabaseIdentifierMaximumLength(name)) {
|
||||
throw new NameTooLongException(name);
|
||||
}
|
||||
};
|
||||
|
||||
export class InvalidStringException extends Error {
|
||||
constructor(string: string) {
|
||||
const message = `String "${string}" is not valid`;
|
||||
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
export class NameTooLongException extends Error {
|
||||
constructor(string: string) {
|
||||
const message = `String "${string}" exceeds 63 characters limit`;
|
||||
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@ -2,17 +2,17 @@ import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
|
||||
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { serializeDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/serialize-default-value';
|
||||
import { ColumnActionAbstractFactory } from 'src/engine/metadata-modules/workspace-migration/factories/column-action-abstract.factory';
|
||||
import { fieldMetadataTypeToColumnType } from 'src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util';
|
||||
import {
|
||||
WorkspaceMigrationColumnActionType,
|
||||
WorkspaceMigrationColumnAlter,
|
||||
WorkspaceMigrationColumnCreate,
|
||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { serializeDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/serialize-default-value';
|
||||
import { fieldMetadataTypeToColumnType } from 'src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util';
|
||||
import { ColumnActionAbstractFactory } from 'src/engine/metadata-modules/workspace-migration/factories/column-action-abstract.factory';
|
||||
import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import {
|
||||
WorkspaceMigrationException,
|
||||
WorkspaceMigrationExceptionCode,
|
||||
@ -32,7 +32,7 @@ export class CompositeColumnActionFactory extends ColumnActionAbstractFactory<Co
|
||||
protected handleCreateAction(
|
||||
fieldMetadata: FieldMetadataInterface<CompositeFieldMetadataType>,
|
||||
): WorkspaceMigrationColumnCreate[] {
|
||||
const compositeType = compositeTypeDefintions.get(fieldMetadata.type);
|
||||
const compositeType = compositeTypeDefinitions.get(fieldMetadata.type);
|
||||
|
||||
if (!compositeType) {
|
||||
this.logger.error(
|
||||
@ -80,10 +80,10 @@ export class CompositeColumnActionFactory extends ColumnActionAbstractFactory<Co
|
||||
currentFieldMetadata: FieldMetadataInterface<CompositeFieldMetadataType>,
|
||||
alteredFieldMetadata: FieldMetadataInterface<CompositeFieldMetadataType>,
|
||||
): WorkspaceMigrationColumnAlter[] {
|
||||
const currentCompositeType = compositeTypeDefintions.get(
|
||||
const currentCompositeType = compositeTypeDefinitions.get(
|
||||
currentFieldMetadata.type,
|
||||
);
|
||||
const alteredCompositeType = compositeTypeDefintions.get(
|
||||
const alteredCompositeType = compositeTypeDefinitions.get(
|
||||
alteredFieldMetadata.type,
|
||||
);
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ColumnType, EntitySchemaColumnOptions } from 'typeorm';
|
||||
|
||||
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import {
|
||||
FieldMetadataEntity,
|
||||
FieldMetadataType,
|
||||
@ -105,11 +105,11 @@ export class EntitySchemaColumnFactory {
|
||||
fieldMetadata: FieldMetadataEntity,
|
||||
): EntitySchemaColumnMap {
|
||||
const entitySchemaColumnMap: EntitySchemaColumnMap = {};
|
||||
const compositeType = compositeTypeDefintions.get(fieldMetadata.type);
|
||||
const compositeType = compositeTypeDefinitions.get(fieldMetadata.type);
|
||||
|
||||
if (!compositeType) {
|
||||
throw new Error(
|
||||
`Composite type ${fieldMetadata.type} is not defined in compositeTypeDefintions`,
|
||||
`Composite type ${fieldMetadata.type} is not defined in compositeTypeDefinitions`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ import { UpsertOptions } from 'typeorm/repository/UpsertOptions';
|
||||
|
||||
import { WorkspaceInternalContext } from 'src/engine/twenty-orm/interfaces/workspace-internal-context.interface';
|
||||
|
||||
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
@ -697,7 +697,7 @@ export class WorkspaceRepository<
|
||||
continue;
|
||||
}
|
||||
|
||||
const compositeType = compositeTypeDefintions.get(fieldMetadata.type);
|
||||
const compositeType = compositeTypeDefinitions.get(fieldMetadata.type);
|
||||
|
||||
if (!compositeType) {
|
||||
continue;
|
||||
@ -751,7 +751,7 @@ export class WorkspaceRepository<
|
||||
|
||||
const compositeFieldMetadataMap = new Map(
|
||||
compositeFieldMetadataCollection.flatMap((fieldMetadata) => {
|
||||
const compositeType = compositeTypeDefintions.get(fieldMetadata.type);
|
||||
const compositeType = compositeTypeDefinitions.get(fieldMetadata.type);
|
||||
|
||||
if (!compositeType) return [];
|
||||
|
||||
|
||||
@ -3,28 +3,28 @@ import { Injectable } from '@nestjs/common';
|
||||
import { ColumnType } from 'typeorm';
|
||||
import { ColumnMetadata } from 'typeorm/metadata/ColumnMetadata';
|
||||
|
||||
import {
|
||||
WorkspaceTableStructure,
|
||||
WorkspaceTableStructureResult,
|
||||
} from 'src/engine/workspace-manager/workspace-health/interfaces/workspace-table-definition.interface';
|
||||
import {
|
||||
FieldMetadataDefaultValue,
|
||||
FieldMetadataFunctionDefaultValue,
|
||||
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||
import {
|
||||
WorkspaceTableStructure,
|
||||
WorkspaceTableStructureResult,
|
||||
} from 'src/engine/workspace-manager/workspace-health/interfaces/workspace-table-definition.interface';
|
||||
|
||||
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { FieldMetadataDefaultValueFunctionNames } from 'src/engine/metadata-modules/field-metadata/dtos/default-value.input';
|
||||
import {
|
||||
FieldMetadataEntity,
|
||||
FieldMetadataType,
|
||||
} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { fieldMetadataTypeToColumnType } from 'src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util';
|
||||
import { serializeFunctionDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/serialize-function-default-value.util';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util';
|
||||
import { isFunctionDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/is-function-default-value.util';
|
||||
import { FieldMetadataDefaultValueFunctionNames } from 'src/engine/metadata-modules/field-metadata/dtos/default-value.input';
|
||||
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import { serializeFunctionDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/serialize-function-default-value.util';
|
||||
import { fieldMetadataTypeToColumnType } from 'src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util';
|
||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||
import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util';
|
||||
|
||||
@Injectable()
|
||||
export class DatabaseStructureService {
|
||||
@ -192,7 +192,7 @@ export class DatabaseStructureService {
|
||||
};
|
||||
|
||||
if (isCompositeFieldMetadataType(fieldMetadata.type)) {
|
||||
const compositeType = compositeTypeDefintions.get(fieldMetadata.type);
|
||||
const compositeType = compositeTypeDefinitions.get(fieldMetadata.type);
|
||||
|
||||
if (!compositeType) {
|
||||
throw new Error(
|
||||
@ -310,7 +310,7 @@ export class DatabaseStructureService {
|
||||
};
|
||||
|
||||
if (isCompositeFieldMetadataType(fieldMetadataType)) {
|
||||
const compositeType = compositeTypeDefintions.get(fieldMetadataType);
|
||||
const compositeType = compositeTypeDefinitions.get(fieldMetadataType);
|
||||
|
||||
if (!compositeType) {
|
||||
throw new Error(
|
||||
|
||||
@ -1,34 +1,34 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||
import {
|
||||
WorkspaceHealthIssue,
|
||||
WorkspaceHealthIssueType,
|
||||
} from 'src/engine/workspace-manager/workspace-health/interfaces/workspace-health-issue.interface';
|
||||
import { WorkspaceTableStructure } from 'src/engine/workspace-manager/workspace-health/interfaces/workspace-table-definition.interface';
|
||||
import { WorkspaceHealthOptions } from 'src/engine/workspace-manager/workspace-health/interfaces/workspace-health-options.interface';
|
||||
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
|
||||
import { WorkspaceTableStructure } from 'src/engine/workspace-manager/workspace-health/interfaces/workspace-table-definition.interface';
|
||||
|
||||
import { compositeTypeDefinitions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import {
|
||||
FieldMetadataEntity,
|
||||
FieldMetadataType,
|
||||
} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import { DatabaseStructureService } from 'src/engine/workspace-manager/workspace-health/services/database-structure.service';
|
||||
import { validName } from 'src/engine/workspace-manager/workspace-health/utils/valid-name.util';
|
||||
import { validateDefaultValueForType } from 'src/engine/metadata-modules/field-metadata/utils/validate-default-value-for-type.util';
|
||||
import {
|
||||
EnumFieldMetadataUnionType,
|
||||
isEnumFieldMetadataType,
|
||||
} from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
import { validateOptionsForType } from 'src/engine/metadata-modules/field-metadata/utils/validate-options-for-type.util';
|
||||
import { serializeDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/serialize-default-value';
|
||||
import { customNamePrefix } from 'src/engine/utils/compute-table-name.util';
|
||||
import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util';
|
||||
import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types';
|
||||
import {
|
||||
computeColumnName,
|
||||
computeCompositeColumnName,
|
||||
} from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
|
||||
import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util';
|
||||
import {
|
||||
EnumFieldMetadataUnionType,
|
||||
isEnumFieldMetadataType,
|
||||
} from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
import { serializeDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/serialize-default-value';
|
||||
import { validateDefaultValueForType } from 'src/engine/metadata-modules/field-metadata/utils/validate-default-value-for-type.util';
|
||||
import { validateOptionsForType } from 'src/engine/metadata-modules/field-metadata/utils/validate-options-for-type.util';
|
||||
import { customNamePrefix } from 'src/engine/utils/compute-table-name.util';
|
||||
import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util';
|
||||
import { DatabaseStructureService } from 'src/engine/workspace-manager/workspace-health/services/database-structure.service';
|
||||
import { validName } from 'src/engine/workspace-manager/workspace-health/utils/valid-name.util';
|
||||
|
||||
@Injectable()
|
||||
export class FieldMetadataHealthService {
|
||||
@ -101,7 +101,7 @@ export class FieldMetadataHealthService {
|
||||
let columnNames: string[] = [];
|
||||
|
||||
if (isCompositeFieldMetadataType(fieldMetadata.type)) {
|
||||
const compositeType = compositeTypeDefintions.get(fieldMetadata.type);
|
||||
const compositeType = compositeTypeDefinitions.get(fieldMetadata.type);
|
||||
|
||||
if (!compositeType) {
|
||||
throw new Error(`Composite type ${fieldMetadata.type} is not defined`);
|
||||
|
||||
Reference in New Issue
Block a user