1630 extensibility twenty cli ability to create edit and delete fields (#15501)

As title

- adds decorators in twenty-sdk
- update twenty-cli load-manifest to it gets @FieldMetadata infos +
testing
- update twenty-server so it CRUD fields properly, using
universalIdentifier
- Fix UI so we can update managed objects records
- move FieldMetadata items from twenty-server to twenty-shared
This commit is contained in:
martmull
2025-11-05 17:50:06 +01:00
committed by GitHub
parent 9fef0752a1
commit abde3c04ac
123 changed files with 1235 additions and 289 deletions
@@ -1,6 +1,5 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type';
@@ -8,13 +8,13 @@ import {
FieldMetadataType,
ObjectRecord,
RelationType,
FieldMetadataRelationSettings,
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { FindOptionsRelations, In, ObjectLiteral } from 'typeorm';
import { v4 as uuidv4 } from 'uuid';
import { WorkspaceAuthContext } from 'src/engine/api/common/interfaces/workspace-auth-context.interface';
import { FieldMetadataRelationSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { CommonBaseQueryRunnerService } from 'src/engine/api/common/common-query-runners/common-base-query-runner.service';
import {
@@ -14,14 +14,14 @@ import {
type GraphQLType,
} from 'graphql';
import GraphQLJSON from 'graphql-type-json';
import { FieldMetadataType } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
import {
FieldMetadataType,
type FieldMetadataSettings,
NumberDataType,
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
} from 'twenty-shared/types';
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { OrderByDirectionType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/enum';
@@ -1,6 +1,5 @@
import { type GraphQLInputObjectType } from 'graphql';
import { NumberDataType } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { NumberDataType } from 'twenty-shared/types';
import {
BigIntFilterType,
@@ -1,7 +1,6 @@
import { GraphQLInt, GraphQLFloat, type GraphQLScalarType } from 'graphql';
import { GraphQLBigInt } from 'graphql-scalars';
import { NumberDataType } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { NumberDataType } from 'twenty-shared/types';
export const getNumberScalarType = (
dataType: NumberDataType,
@@ -13,6 +13,7 @@ export class ApplicationExceptionFilter implements ExceptionFilter {
catch(exception: ApplicationException) {
switch (exception.code) {
case ApplicationExceptionCode.OBJECT_NOT_FOUND:
case ApplicationExceptionCode.FIELD_NOT_FOUND:
case ApplicationExceptionCode.ENTITY_NOT_FOUND:
case ApplicationExceptionCode.APPLICATION_NOT_FOUND:
case ApplicationExceptionCode.SERVERLESS_FUNCTION_NOT_FOUND:
@@ -13,12 +13,12 @@ import {
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { ApplicationInput } from 'src/engine/core-modules/application/dtos/application.input';
import {
FieldManifest,
ObjectManifest,
ServerlessFunctionManifest,
ServerlessFunctionTriggerManifest,
} from 'src/engine/core-modules/application/types/application.types';
import { ApplicationVariableEntityService } from 'src/engine/core-modules/applicationVariable/application-variable.service';
import { Sources } from 'src/engine/core-modules/file-storage/types/source.type';
import { CronTriggerV2Service } from 'src/engine/metadata-modules/cron-trigger/services/cron-trigger-v2.service';
import { FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
@@ -35,6 +35,11 @@ import { ServerlessFunctionLayerService } from 'src/engine/metadata-modules/serv
import { ServerlessFunctionV2Service } from 'src/engine/metadata-modules/serverless-function/services/serverless-function-v2.service';
import { FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service';
import { Sources } from 'src/engine/core-modules/file-storage/types/source.type';
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { FieldMetadataServiceV2 } from 'src/engine/metadata-modules/field-metadata/services/field-metadata.service-v2';
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util';
@Injectable()
export class ApplicationSyncService {
@@ -45,6 +50,7 @@ export class ApplicationSyncService {
private readonly applicationVariableService: ApplicationVariableEntityService,
private readonly serverlessFunctionLayerService: ServerlessFunctionLayerService,
private readonly objectMetadataServiceV2: ObjectMetadataServiceV2,
private readonly fieldMetadataServiceV2: FieldMetadataServiceV2,
private readonly serverlessFunctionV2Service: ServerlessFunctionV2Service,
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly dataSourceService: DataSourceService,
@@ -155,6 +161,131 @@ export class ApplicationSyncService {
return application;
}
private async syncFields({
objectId,
fieldsToSync,
workspaceId,
applicationId,
}: {
objectId: string;
workspaceId: string;
applicationId: string;
fieldsToSync?: FieldManifest[];
}) {
if (!isDefined(fieldsToSync)) {
return;
}
const { flatFieldMetadataMaps: existingFlatFieldMetadataMaps } =
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
{
workspaceId,
flatMapsKeys: ['flatFieldMetadataMaps'],
},
);
const existingFields = Object.values(
existingFlatFieldMetadataMaps.byId,
).filter(
(field) => isDefined(field) && field.objectMetadataId === objectId,
) as FlatFieldMetadata[];
const fieldsToSyncUniversalIds = fieldsToSync.map(
(field) => field.universalIdentifier,
);
const existingFieldsStandardIds = existingFields.map(
(field) => field.universalIdentifier,
);
const fieldsToDelete = existingFields.filter(
(field) =>
isDefined(field.universalIdentifier) &&
!fieldsToSyncUniversalIds.includes(field.universalIdentifier) &&
field.isCustom === true,
);
const fieldsToUpdate = existingFields.filter(
(field) =>
isDefined(field.universalIdentifier) &&
fieldsToSyncUniversalIds.includes(field.universalIdentifier),
);
const fieldsToCreate = fieldsToSync.filter(
(fieldToSync) =>
!existingFieldsStandardIds.includes(fieldToSync.universalIdentifier),
);
for (const fieldToDelete of fieldsToDelete) {
await this.fieldMetadataServiceV2.updateOne({
updateFieldInput: {
id: fieldToDelete.id,
isActive: false,
},
workspaceId,
});
await this.fieldMetadataServiceV2.deleteOneField({
deleteOneFieldInput: { id: fieldToDelete.id },
workspaceId,
});
}
for (const fieldToUpdate of fieldsToUpdate) {
const fieldToSync = fieldsToSync.find(
(field) =>
field.universalIdentifier === fieldToUpdate.universalIdentifier,
);
if (!fieldToSync) {
throw new ApplicationException(
`Failed to find field to sync with universalIdentifier ${fieldToUpdate.universalIdentifier}`,
ApplicationExceptionCode.FIELD_NOT_FOUND,
);
}
const updateFieldInput = {
id: fieldToUpdate.id,
label: fieldToSync.label,
description: fieldToSync.description ?? undefined,
icon: fieldToSync.icon ?? undefined,
defaultValue: fieldToSync.defaultValue ?? undefined,
options: fieldToSync.options ?? undefined,
settings: fieldToSync.settings ?? undefined,
isNullable: fieldToSync.isNullable ?? true,
};
await this.fieldMetadataServiceV2.updateOne({
updateFieldInput,
workspaceId,
});
}
for (const fieldToCreate of fieldsToCreate) {
const createFieldInput: CreateFieldInput = {
name: computeMetadataNameFromLabel(fieldToCreate.label),
type: fieldToCreate.type,
label: fieldToCreate.label,
description: fieldToCreate.description ?? undefined,
icon: fieldToCreate.icon ?? undefined,
defaultValue: fieldToCreate.defaultValue ?? undefined,
options: fieldToCreate.options ?? undefined,
settings: fieldToCreate.settings ?? undefined,
isNullable: fieldToCreate.isNullable ?? true,
objectMetadataId: objectId,
universalIdentifier: fieldToCreate.universalIdentifier,
standardId: fieldToCreate.universalIdentifier,
applicationId,
isCustom: true,
workspaceId,
};
await this.fieldMetadataServiceV2.createOne({
createFieldInput,
workspaceId,
});
}
}
private async syncObjects({
objectsToSync,
workspaceId,
@@ -243,6 +374,13 @@ export class ApplicationSyncService {
updateObjectInput,
workspaceId,
});
await this.syncFields({
fieldsToSync: objectToSync.fields,
objectId: objectToUpdate.id,
workspaceId,
applicationId,
});
}
const dataSourceMetadata =
@@ -264,10 +402,17 @@ export class ApplicationSyncService {
applicationId,
};
await this.objectMetadataServiceV2.createOne({
const createdObject = await this.objectMetadataServiceV2.createOne({
createObjectInput,
workspaceId,
});
await this.syncFields({
fieldsToSync: objectToCreate.fields,
objectId: createdObject.id,
workspaceId,
applicationId,
});
}
}
@@ -4,6 +4,7 @@ export class ApplicationException extends CustomException<ApplicationExceptionCo
export enum ApplicationExceptionCode {
OBJECT_NOT_FOUND = 'OBJECT_NOT_FOUND',
FIELD_NOT_FOUND = 'FIELD_NOT_FOUND',
SERVERLESS_FUNCTION_NOT_FOUND = 'SERVERLESS_FUNCTION_NOT_FOUND',
ENTITY_NOT_FOUND = 'ENTITY_NOT_FOUND',
APPLICATION_NOT_FOUND = 'APPLICATION_NOT_FOUND',
@@ -17,12 +17,14 @@ import { RouteTriggerModule } from 'src/engine/metadata-modules/route-trigger/ro
import { ServerlessFunctionLayerModule } from 'src/engine/metadata-modules/serverless-function-layer/serverless-function-layer.module';
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
@Module({
imports: [
TypeOrmModule.forFeature([ApplicationEntity, AgentEntity, WorkspaceEntity]),
WorkspaceManyOrAllFlatEntityMapsCacheModule,
ObjectMetadataModule,
FieldMetadataModule,
DataSourceModule,
ApplicationVariableEntityModule,
ServerlessFunctionLayerModule,
@@ -1,3 +1,5 @@
import { type FieldMetadataType } from 'twenty-shared/types';
import { type HTTPMethod } from 'src/engine/metadata-modules/route-trigger/route-trigger.entity';
export type PackageJson = {
@@ -66,6 +68,22 @@ export type ServerlessFunctionTriggerManifest = (
universalIdentifier: string;
};
export type FieldManifest = {
universalIdentifier: string;
type: FieldMetadataType;
label: string;
description?: string;
icon?: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
defaultValue?: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
options?: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
settings?: any;
isNullable?: boolean;
isFieldUiReadOnly?: boolean;
};
export type ObjectManifest = {
universalIdentifier: string;
nameSingular: string;
@@ -74,6 +92,7 @@ export type ObjectManifest = {
labelPlural: string;
description?: string;
icon?: string;
fields?: FieldManifest[];
};
interface AgentResponseFormat {
@@ -1,8 +1,6 @@
import { faker } from '@faker-js/faker';
import { type EachTestingContext } from 'twenty-shared/testing';
import { FieldMetadataType } from 'twenty-shared/types';
import { NumberDataType } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { FieldMetadataType, NumberDataType } from 'twenty-shared/types';
import { objectMetadataItemMock } from 'src/engine/api/__mocks__/object-metadata-item.mock';
import { computeSchemaComponents } from 'src/engine/core-modules/open-api/utils/components.utils';
@@ -1,14 +1,12 @@
import {
FieldMetadataType,
type RestrictedFieldsPermissions,
type FieldMetadataSettings,
NumberDataType,
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { z } from 'zod';
import {
type FieldMetadataSettings,
NumberDataType,
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@@ -1,4 +1,4 @@
import { Field, InputType, OmitType } from '@nestjs/graphql';
import { Field, HideField, InputType, OmitType } from '@nestjs/graphql';
import { Type } from 'class-transformer';
import { IsOptional, IsUUID, ValidateNested } from 'class-validator';
@@ -18,6 +18,15 @@ export class CreateFieldInput extends OmitType(
@Field(() => UUIDScalarType)
objectMetadataId: string;
@HideField()
universalIdentifier?: string;
@HideField()
standardId?: string;
@HideField()
applicationId?: string;
@Field(() => Boolean, { nullable: true })
@IsOptional()
isRemoteCreation?: boolean;
@@ -23,11 +23,13 @@ import {
IsUUID,
} from 'class-validator';
import { GraphQLJSON } from 'graphql-type-json';
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
FieldMetadataSettings,
FieldMetadataOptions,
} from 'twenty-shared/types';
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
import { FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { IsValidMetadataName } from 'src/engine/decorators/metadata/is-valid-metadata-name.decorator';
@@ -1,4 +1,8 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
FieldMetadataSettings,
FieldMetadataOptions,
} from 'twenty-shared/types';
import {
Check,
Column,
@@ -16,8 +20,6 @@ import {
} from 'typeorm';
import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
import { FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/syncable-entity.interface';
import { type FieldStandardOverridesDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-standard-overrides.dto';
@@ -1,6 +1,7 @@
import { type FieldMetadataType } from 'twenty-shared/types';
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
import {
type FieldMetadataType,
type FieldMetadataOptions,
} from 'twenty-shared/types';
export interface CompositeProperty<
Type extends FieldMetadataType = FieldMetadataType,
@@ -1,21 +0,0 @@
import { type FieldMetadataType, type IsExactly } from 'twenty-shared/types';
import {
type FieldMetadataComplexOption,
type FieldMetadataDefaultOption,
} from 'src/engine/metadata-modules/field-metadata/dtos/options.input';
type FieldMetadataOptionsMapping = {
[FieldMetadataType.RATING]: FieldMetadataDefaultOption[];
[FieldMetadataType.SELECT]: FieldMetadataComplexOption[];
[FieldMetadataType.MULTI_SELECT]: FieldMetadataComplexOption[];
};
export type FieldMetadataOptions<
T extends FieldMetadataType = FieldMetadataType,
> =
IsExactly<T, FieldMetadataType> extends true
? null | (FieldMetadataDefaultOption[] | FieldMetadataComplexOption[]) // Could be improved to be | unknown
: T extends keyof FieldMetadataOptionsMapping
? FieldMetadataOptionsMapping[T]
: never | null;
@@ -1,82 +0,0 @@
import {
type AllowedAddressSubField,
type FieldMetadataMultiItemSettings,
type FieldMetadataType,
type IsExactly,
} from 'twenty-shared/types';
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
import { type RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
export enum NumberDataType {
FLOAT = 'float',
INT = 'int',
BIGINT = 'bigint',
}
export enum DateDisplayFormat {
RELATIVE = 'RELATIVE',
USER_SETTINGS = 'USER_SETTINGS',
CUSTOM = 'CUSTOM',
}
export type FieldNumberVariant = 'number' | 'percentage';
export type FieldMetadataNumberSettings = {
dataType?: NumberDataType;
decimals?: number;
type?: FieldNumberVariant;
};
export type FieldMetadataTextSettings = {
displayedMaxRows?: number;
};
export type FieldMetadataDateSettings = {
displayFormat?: DateDisplayFormat;
};
export type FieldMetadataDateTimeSettings = {
displayFormat?: DateDisplayFormat;
};
export type FieldMetadataRelationSettings = {
relationType: RelationType;
onDelete?: RelationOnDeleteAction;
joinColumnName?: string | null;
};
export type FieldMetadataAddressSettings = {
subFields?: AllowedAddressSubField[];
};
export type FieldMetadataTsVectorSettings = {
asExpression?: string;
generatedType?: 'STORED' | 'VIRTUAL';
};
type FieldMetadataSettingsMapping = {
[FieldMetadataType.NUMBER]: FieldMetadataNumberSettings | null;
[FieldMetadataType.DATE]: FieldMetadataDateSettings | null;
[FieldMetadataType.DATE_TIME]: FieldMetadataDateTimeSettings | null;
[FieldMetadataType.TEXT]: FieldMetadataTextSettings | null;
[FieldMetadataType.RELATION]: FieldMetadataRelationSettings;
[FieldMetadataType.ADDRESS]: FieldMetadataAddressSettings | null;
[FieldMetadataType.MORPH_RELATION]: FieldMetadataRelationSettings;
[FieldMetadataType.TS_VECTOR]: FieldMetadataTsVectorSettings | null;
[FieldMetadataType.PHONES]: FieldMetadataMultiItemSettings | null;
[FieldMetadataType.EMAILS]: FieldMetadataMultiItemSettings | null;
[FieldMetadataType.LINKS]: FieldMetadataMultiItemSettings | null;
[FieldMetadataType.ARRAY]: FieldMetadataMultiItemSettings | null;
};
export type AllFieldMetadataSettings =
FieldMetadataSettingsMapping[keyof FieldMetadataSettingsMapping];
export type FieldMetadataSettings<
T extends FieldMetadataType = FieldMetadataType,
> =
IsExactly<T, FieldMetadataType> extends true
? null | AllFieldMetadataSettings // Could be improved to be | unknown
: T extends keyof FieldMetadataSettingsMapping
? FieldMetadataSettingsMapping[T]
: never | null;
@@ -1,6 +0,0 @@
export enum RelationOnDeleteAction {
CASCADE = 'CASCADE',
RESTRICT = 'RESTRICT',
SET_NULL = 'SET_NULL',
NO_ACTION = 'NO_ACTION',
}
@@ -6,12 +6,11 @@ import { isNonEmptyString } from '@sniptt/guards';
import {
type EnumFieldMetadataType,
FieldMetadataType,
type FieldMetadataOptions,
} from 'twenty-shared/types';
import { assertUnreachable, isDefined } from 'twenty-shared/utils';
import { z } from 'zod';
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
import {
type FieldMetadataComplexOption,
@@ -2,12 +2,15 @@ import { Injectable } from '@nestjs/common';
import { msg } from '@lingui/core/macro';
import { IsEnum, IsString, IsUUID } from 'class-validator';
import { FieldMetadataType } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import {
type FieldMetadataSettings,
FieldMetadataType,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { type Repository } from 'typeorm';
import { v4 } from 'uuid';
import { isDefined } from 'twenty-shared/utils';
import { type FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
@@ -20,7 +23,6 @@ import {
import { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.util';
import { prepareCustomFieldMetadataForCreation } from 'src/engine/metadata-modules/field-metadata/utils/prepare-field-metadata-for-creation.util';
import { validateRelationCreationPayloadOrThrow } from 'src/engine/metadata-modules/field-metadata/utils/validate-relation-creation-payload-or-throw.util';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { type ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
import { validateFieldNameAvailabilityOrThrow } from 'src/engine/metadata-modules/utils/validate-field-name-availability.utils';
@@ -17,11 +17,10 @@ import {
ALLOWED_ADDRESS_SUBFIELDS,
type AllowedAddressSubField,
FieldMetadataType,
type FieldMetadataSettings,
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { type FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
import { type UpdateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/update-field.input';
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@@ -57,9 +57,11 @@ export class FieldMetadataServiceV2 {
public async deleteOneField({
deleteOneFieldInput,
workspaceId,
isSystemBuild = false,
}: {
deleteOneFieldInput: DeleteOneFieldInput;
workspaceId: string;
isSystemBuild?: boolean;
}): Promise<FieldMetadataDTO> {
const {
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
@@ -94,7 +96,7 @@ export class FieldMetadataServiceV2 {
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
},
buildOptions: {
isSystemBuild: false,
isSystemBuild,
inferDeletionFromMissingEntities: {
fieldMetadata: true,
index: true,
@@ -134,7 +136,7 @@ export class FieldMetadataServiceV2 {
updateFieldInput,
workspaceId,
}: {
updateFieldInput: UpdateFieldInput;
updateFieldInput: Omit<UpdateFieldInput, 'workspaceId'>;
workspaceId: string;
}): Promise<FieldMetadataEntity> {
const {
@@ -164,7 +166,7 @@ export class FieldMetadataServiceV2 {
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
flatIndexMaps: existingFlatIndexMaps,
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
updateFieldInput,
updateFieldInput: { ...updateFieldInput, workspaceId },
flatViewFilterMaps: existingFlatViewFilterMaps,
flatViewGroupMaps: existingFlatViewGroupMaps,
flatViewMaps: existingFlatViewMaps,
@@ -3,6 +3,12 @@ import {
type FieldMetadataMultiItemSettings,
type FieldMetadataType,
type NullablePartial,
type AllFieldMetadataSettings,
type FieldMetadataDateSettings,
type FieldMetadataDateTimeSettings,
type FieldMetadataNumberSettings,
type FieldMetadataRelationSettings,
type FieldMetadataTextSettings,
} from 'twenty-shared/types';
import { type Relation as TypeOrmRelation } from 'typeorm';
@@ -10,14 +16,6 @@ import {
type FieldMetadataDefaultValueForAnyType,
type FieldMetadataDefaultValueForType,
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
import {
type AllFieldMetadataSettings,
type FieldMetadataDateSettings,
type FieldMetadataDateTimeSettings,
type FieldMetadataNumberSettings,
type FieldMetadataRelationSettings,
type FieldMetadataTextSettings,
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import {
type FieldMetadataComplexOption,
@@ -1,8 +1,9 @@
import { Test, type TestingModule } from '@nestjs/testing';
import { FieldMetadataType } from 'twenty-shared/types';
import { type FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import {
type FieldMetadataSettings,
FieldMetadataType,
} from 'twenty-shared/types';
import { FieldMetadataException } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
import { FieldMetadataEnumValidationService } from 'src/engine/metadata-modules/field-metadata/services/field-metadata-enum-validation.service';
@@ -1,8 +1,9 @@
import { plainToInstance } from 'class-transformer';
import { validateSync } from 'class-validator';
import { FieldMetadataType } from 'twenty-shared/types';
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
import {
FieldMetadataType,
type FieldMetadataOptions,
} from 'twenty-shared/types';
import {
FieldMetadataComplexOption,
@@ -2,11 +2,12 @@ import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { type ValidationArguments, ValidatorConstraint } from 'class-validator';
import { type FieldMetadataType } from 'twenty-shared/types';
import {
type FieldMetadataType,
type FieldMetadataOptions,
} from 'twenty-shared/types';
import { Repository } from 'typeorm';
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { validateOptionsForType } from 'src/engine/metadata-modules/field-metadata/utils/validate-options-for-type.util';
@@ -1,11 +1,13 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
DateDisplayFormat,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
export const ATTACHMENT_FLAT_FIELDS_MOCK = {
name: getFlatFieldMetadataMock({
@@ -1,11 +1,13 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
DateDisplayFormat,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
export const COMPANY_FLAT_FIELDS_MOCK = {
name: getFlatFieldMetadataMock({
@@ -1,11 +1,13 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
DateDisplayFormat,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
export const FAVORITE_FLAT_FIELDS_MOCK = {
position: getFlatFieldMetadataMock({
@@ -1,6 +1,5 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataType, DateDisplayFormat } from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
@@ -1,6 +1,5 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataType, DateDisplayFormat } from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
@@ -1,11 +1,13 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
DateDisplayFormat,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
export const NOTETARGET_FLAT_FIELDS_MOCK = {
id: getFlatFieldMetadataMock({
@@ -1,11 +1,13 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
DateDisplayFormat,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
export const OPPORTUNITY_FLAT_FIELDS_MOCK = {
name: getFlatFieldMetadataMock({
@@ -1,11 +1,13 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
DateDisplayFormat,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
export const PERSON_FLAT_FIELDS_MOCK = {
name: getFlatFieldMetadataMock({
@@ -1,11 +1,13 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
DateDisplayFormat,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
export const TASK_FLAT_FIELDS_MOCK = {
position: getFlatFieldMetadataMock({
@@ -1,11 +1,13 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
DateDisplayFormat,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
export const TASKTARGET_FLAT_FIELDS_MOCK = {
id: getFlatFieldMetadataMock({
@@ -1,11 +1,13 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
DateDisplayFormat,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock';
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
export const TIMELINEACTIVITY_FLAT_FIELDS_MOCK = {
happensAt: getFlatFieldMetadataMock({
@@ -1,5 +1,8 @@
import { msg } from '@lingui/core/macro';
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
type FieldMetadataOptions,
} from 'twenty-shared/types';
import {
assertUnreachable,
isDefined,
@@ -7,8 +10,6 @@ import {
} from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
import { FieldMetadataExceptionCode } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
import { generateRatingOptions } from 'src/engine/metadata-modules/field-metadata/utils/generate-rating-optionts.util';
@@ -1,4 +1,8 @@
import { FieldMetadataType, RelationType } from 'twenty-shared/types';
import {
FieldMetadataType,
RelationType,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { v4 } from 'uuid';
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
@@ -9,7 +13,6 @@ import { generateIndexForFlatFieldMetadata } from 'src/engine/metadata-modules/f
import { getDefaultFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/get-default-flat-field-metadata-from-create-field-input.util';
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util';
type ComputeFieldMetadataRelationSettingsForRelationTypeArgs = {
@@ -43,19 +43,20 @@ export const getDefaultFlatFieldMetadata = ({
objectMetadataId: createFieldInput.objectMetadataId,
relationTargetFieldMetadataId: null,
relationTargetObjectMetadataId: null,
standardId: null,
standardId: createFieldInput.standardId ?? null,
standardOverrides: null,
type: createFieldInput.type,
universalIdentifier: fieldMetadataId,
universalIdentifier:
createFieldInput.universalIdentifier ?? fieldMetadataId,
workspaceId,
options: null,
options: createFieldInput.options ?? null,
defaultValue: defaultValue ?? generateDefaultValue(createFieldInput.type),
settings: settings ?? null,
createdAt,
updatedAt: createdAt,
isUIReadOnly: createFieldInput.isUIReadOnly ?? false,
morphId: null,
applicationId: null,
applicationId: createFieldInput.applicationId ?? null,
viewFilterIds: [],
viewGroupIds: [],
kanbanAggregateOperationViewIds: [],
@@ -5,12 +5,11 @@ import {
FieldMetadataType,
type EnumFieldMetadataType,
type NonNullableRequired,
type FieldMetadataOptions,
} from 'twenty-shared/types';
import { assertUnreachable, isDefined } from 'twenty-shared/utils';
import { z } from 'zod';
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
import {
type FieldMetadataComplexOption,
type FieldMetadataDefaultOption,
@@ -3,9 +3,10 @@ import { Field, HideField, InputType } from '@nestjs/graphql';
import { BeforeCreateOne } from '@ptc-org/nestjs-query-graphql';
import { IsBoolean, IsNotEmpty, IsOptional, IsString } from 'class-validator';
import GraphQLJSON from 'graphql-type-json';
import { type FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import {
type FieldMetadataType,
type FieldMetadataSettings,
} from 'twenty-shared/types';
import { IsValidMetadataName } from 'src/engine/decorators/metadata/is-valid-metadata-name.decorator';
import { BeforeCreateOneObject } from 'src/engine/metadata-modules/object-metadata/hooks/before-create-one-object.hook';
@@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { msg } from '@lingui/core/macro';
import { FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { capitalize, isDefined } from 'twenty-shared/utils';
import { type QueryRunner, Repository } from 'typeorm';
import { v4 as uuidV4 } from 'uuid';
@@ -18,7 +18,6 @@ import {
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
import { buildDescriptionForRelationFieldMetadataOnFromField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-from-field.util';
import { buildDescriptionForRelationFieldMetadataOnToField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-to-field.util';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
import { type FieldMetadataMap } from 'src/engine/metadata-modules/types/field-metadata-map';
import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import { type ObjectMetadataMaps } from 'src/engine/metadata-modules/types/object-metadata-maps';
@@ -1,4 +1,4 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { capitalize, isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
@@ -15,7 +15,6 @@ import {
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
import { buildDescriptionForRelationFieldMetadataOnFromField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-from-field.util';
import { buildDescriptionForRelationFieldMetadataOnToField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-to-field.util';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
import {
CUSTOM_OBJECT_STANDARD_FIELD_IDS,
STANDARD_OBJECT_FIELD_IDS,
@@ -1,5 +1,6 @@
import { RelationOnDeleteAction } from 'twenty-shared/types';
import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
import {
WorkspaceMigrationColumnActionType,
@@ -1,6 +0,0 @@
export enum RelationOnDeleteAction {
CASCADE = 'CASCADE',
RESTRICT = 'RESTRICT',
SET_NULL = 'SET_NULL',
NO_ACTION = 'NO_ACTION',
}
@@ -1,12 +1,13 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { type FieldMetadataType } from 'twenty-shared/types';
import {
type FieldMetadataType,
type FieldMetadataSettings,
} from 'twenty-shared/types';
import { In, Repository } from 'typeorm';
import { isDefined } from 'twenty-shared/utils';
import { type FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { buildMigrationsToCreateRemoteTableRelations } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/utils/build-migrations-to-create-remote-table-relations.util';
@@ -1,9 +1,8 @@
import { FieldMetadataType } from 'twenty-shared/types';
import {
FieldMetadataType,
type FieldMetadataSettings,
NumberDataType,
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
} from 'twenty-shared/types';
export const mapUdtNameToFieldType = (udtName: string): FieldMetadataType => {
switch (udtName) {
@@ -4,9 +4,9 @@ import {
Entity,
PrimaryGeneratedColumn,
} from 'typeorm';
import { type RelationOnDeleteAction } from 'twenty-shared/types';
import { type IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
export enum WorkspaceMigrationColumnActionType {
CREATE = 'CREATE',
@@ -1,7 +1,5 @@
import { msg } from '@lingui/core/macro';
import { FieldMetadataType } from 'twenty-shared/types';
import { DateDisplayFormat } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { FieldMetadataType, DateDisplayFormat } from 'twenty-shared/types';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
@@ -1,7 +1,6 @@
import { msg } from '@lingui/core/macro';
import { FieldMetadataType } from 'twenty-shared/types';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/constants/search-vector-field.constants';
@@ -1,6 +1,6 @@
import { type ObjectType } from 'typeorm';
import { type RelationOnDeleteAction } from 'twenty-shared/types';
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
import { type RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { type WorkspaceDynamicRelationMetadataArgsFactory } from 'src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface';
@@ -1,9 +1,11 @@
import { type MessageDescriptor } from '@lingui/core';
import { type FieldMetadataType } from 'twenty-shared/types';
import {
type FieldMetadataType,
type FieldMetadataSettings,
type FieldMetadataOptions,
} from 'twenty-shared/types';
import { type FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
import { type FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { generateDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/generate-default-value';
import { computeMetadataNameFromLabel } from 'src/engine/metadata-modules/utils/validate-name-and-label-are-sync-or-throw.util';
@@ -2,8 +2,8 @@ import { type MessageDescriptor } from '@lingui/core';
import { isDefined, isUUID } from 'class-validator';
import { CustomError } from 'twenty-shared/utils';
import { type ObjectType } from 'typeorm';
import { type RelationOnDeleteAction } from 'twenty-shared/types';
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
import { type RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
@@ -1,6 +1,6 @@
import { type ObjectType } from 'typeorm';
import { type RelationOnDeleteAction } from 'twenty-shared/types';
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
import { type RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { type Gate } from 'src/engine/twenty-orm/interfaces/gate.interface';
@@ -1,8 +1,10 @@
import { type FieldMetadataType } from 'twenty-shared/types';
import {
type FieldMetadataType,
type FieldMetadataSettings,
type FieldMetadataOptions,
} from 'twenty-shared/types';
import { type FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface';
import { type FieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-options.interface';
import { type FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { type Gate } from 'src/engine/twenty-orm/interfaces/gate.interface';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
@@ -1,6 +1,6 @@
import { type ObjectType } from 'typeorm';
import { type RelationOnDeleteAction } from 'twenty-shared/types';
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-on-delete-action.interface';
import { type RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { type Gate } from 'src/engine/twenty-orm/interfaces/gate.interface';
@@ -1,8 +1,9 @@
import { RelationType } from 'twenty-shared/types';
import {
type FieldMetadataRelationSettings,
RelationType,
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { type FieldMetadataRelationSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
export const formatColumnNameForRelationField = (
fieldName: string,
fieldMetadataSettings: FieldMetadataRelationSettings,
@@ -1,5 +1,6 @@
import { type FieldMetadataRelationSettings } from 'twenty-shared/types';
import { type CompositeType } from 'src/engine/metadata-modules/field-metadata/interfaces/composite-type.interface';
import { type FieldMetadataRelationSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { extractGraphQLRelationFieldNames } from 'src/engine/api/graphql/workspace-schema-builder/utils/extract-graphql-relation-field-names.util';
@@ -1,10 +1,10 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import {
FieldMetadataType,
type FieldMetadataSettings,
NumberDataType,
} from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@@ -1,6 +1,4 @@
import { FieldMetadataType } from 'twenty-shared/types';
import { NumberDataType } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { FieldMetadataType, NumberDataType } from 'twenty-shared/types';
import { type FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
import { type FieldMetadataSeed } from 'src/engine/workspace-manager/dev-seeder/metadata/types/field-metadata-seed.type';
@@ -1,4 +1,4 @@
import { type RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
import { type RelationOnDeleteAction } from 'twenty-shared/types';
export const convertOnDeleteActionToOnDelete = (
onDeleteAction: RelationOnDeleteAction | undefined,
@@ -1,9 +1,11 @@
import { Injectable } from '@nestjs/common';
import diff, { type DifferenceChange, type DifferenceRemove } from 'microdiff';
import { type FieldMetadataType } from 'twenty-shared/types';
import {
type FieldMetadataType,
type FieldMetadataRelationSettings,
} from 'twenty-shared/types';
import { type FieldMetadataRelationSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import {
ComparatorAction,
type FieldRelationComparatorResult,