diff --git a/packages/twenty-server/src/app.module.ts b/packages/twenty-server/src/app.module.ts index b076874c720..8a0f0e75446 100644 --- a/packages/twenty-server/src/app.module.ts +++ b/packages/twenty-server/src/app.module.ts @@ -7,7 +7,6 @@ import { import { ConfigModule } from '@nestjs/config'; import { ServeStaticModule } from '@nestjs/serve-static'; import { GraphQLModule } from '@nestjs/graphql'; -import { DevtoolsModule } from '@nestjs/devtools-integration'; import { existsSync } from 'fs'; import { join } from 'path'; @@ -20,7 +19,6 @@ import { CoreGraphQLApiModule } from 'src/engine/api/graphql/core-graphql-api.mo import { MetadataGraphQLApiModule } from 'src/engine/api/graphql/metadata-graphql-api.module'; import { GraphQLConfigModule } from 'src/engine/api/graphql/graphql-config/graphql-config.module'; import { GraphQLConfigService } from 'src/engine/api/graphql/graphql-config/graphql-config.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module'; import { GraphQLHydrateRequestFromTokenMiddleware } from 'src/engine/middlewares/graphql-hydrate-request-from-token.middleware'; @@ -30,13 +28,13 @@ import { IntegrationsModule } from './engine/integrations/integrations.module'; @Module({ imports: [ // Nest.js devtools, use devtools.nestjs.com to debug - DevtoolsModule.registerAsync({ - useFactory: (environmentService: EnvironmentService) => ({ - http: environmentService.get('DEBUG_MODE'), - port: environmentService.get('DEBUG_PORT'), - }), - inject: [EnvironmentService], - }), + // DevtoolsModule.registerAsync({ + // useFactory: (environmentService: EnvironmentService) => ({ + // http: environmentService.get('DEBUG_MODE'), + // port: environmentService.get('DEBUG_PORT'), + // }), + // inject: [EnvironmentService], + // }), ConfigModule.forRoot({ isGlobal: true, }), diff --git a/packages/twenty-server/src/engine/core-modules/core-engine.module.ts b/packages/twenty-server/src/engine/core-modules/core-engine.module.ts index a8a22022ac2..4fa8467538b 100644 --- a/packages/twenty-server/src/engine/core-modules/core-engine.module.ts +++ b/packages/twenty-server/src/engine/core-modules/core-engine.module.ts @@ -11,9 +11,9 @@ import { TimelineCalendarEventModule } from 'src/engine/core-modules/calendar/ti import { BillingModule } from 'src/engine/core-modules/billing/billing.module'; import { HealthModule } from 'src/engine/core-modules/health/health.module'; -import { ClientConfigModule } from './client-config/client-config.module'; -import { FileModule } from './file/file.module'; import { AnalyticsModule } from './analytics/analytics.module'; +import { FileModule } from './file/file.module'; +import { ClientConfigModule } from './client-config/client-config.module'; @Module({ imports: [ diff --git a/packages/twenty-server/src/engine/twenty-orm/workspace-object-tests/base.object-metadata.ts b/packages/twenty-server/src/engine/twenty-orm/base.workspace-entity.ts similarity index 95% rename from packages/twenty-server/src/engine/twenty-orm/workspace-object-tests/base.object-metadata.ts rename to packages/twenty-server/src/engine/twenty-orm/base.workspace-entity.ts index 00b9eba0584..ebfbfc430b3 100644 --- a/packages/twenty-server/src/engine/twenty-orm/workspace-object-tests/base.object-metadata.ts +++ b/packages/twenty-server/src/engine/twenty-orm/base.workspace-entity.ts @@ -4,7 +4,7 @@ import { WorkspaceIsPimaryField } from 'src/engine/twenty-orm/decorators/workspa import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { BASE_OBJECT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; -export abstract class BaseObjectMetadata { +export abstract class BaseWorkspaceEntity { @WorkspaceField({ standardId: BASE_OBJECT_STANDARD_FIELD_IDS.id, type: FieldMetadataType.UUID, @@ -25,7 +25,6 @@ export abstract class BaseObjectMetadata { icon: 'IconCalendar', defaultValue: 'now', }) - @WorkspaceIsSystem() createdAt: Date; @WorkspaceField({ diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/custom-objects/custom.object-metadata.ts b/packages/twenty-server/src/engine/twenty-orm/custom.workspace-entity.ts similarity index 68% rename from packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/custom-objects/custom.object-metadata.ts rename to packages/twenty-server/src/engine/twenty-orm/custom.workspace-entity.ts index 2b8b0917709..78774c4c372 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/custom-objects/custom.object-metadata.ts +++ b/packages/twenty-server/src/engine/twenty-orm/custom.workspace-entity.ts @@ -1,23 +1,23 @@ -import { BaseCustomObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/base-custom-object-metadata.decorator'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { RelationMetadataType, RelationOnDeleteAction, } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { ActivityTargetObjectMetadata } from 'src/modules/activity/standard-objects/activity-target.object-metadata'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; import { FavoriteObjectMetadata } from 'src/modules/favorite/standard-objects/favorite.object-metadata'; import { AttachmentObjectMetadata } from 'src/modules/attachment/standard-objects/attachment.object-metadata'; import { CUSTOM_OBJECT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { TimelineActivityObjectMetadata } from 'src/modules/timeline/standard-objects/timeline-activity.object-metadata'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { WorkspaceCustomObject } from 'src/engine/twenty-orm/decorators/workspace-custom-object.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; -@BaseCustomObjectMetadata() -export class CustomObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceCustomObject() +export class CustomWorkspaceEntity extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.name, label: 'Name', description: 'Name', @@ -27,81 +27,68 @@ export class CustomObjectMetadata extends BaseObjectMetadata { }) name: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.position, label: 'Position', description: 'Position', type: FieldMetadataType.POSITION, icon: 'IconHierarchy2', }) - @IsNullable() - @IsSystem() + @WorkspaceIsNullable() + @WorkspaceIsSystem() position: number; - @FieldMetadata({ + @WorkspaceRelation({ standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.activityTargets, - type: FieldMetadataType.RELATION, label: 'Activities', + type: RelationMetadataType.ONE_TO_MANY, description: (objectMetadata) => `Activities tied to the ${objectMetadata.labelSingular}`, icon: 'IconCheckbox', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => ActivityTargetObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() + @WorkspaceIsNullable() activityTargets: ActivityTargetObjectMetadata[]; - @FieldMetadata({ + @WorkspaceRelation({ standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.favorites, - type: FieldMetadataType.RELATION, label: 'Favorites', + type: RelationMetadataType.ONE_TO_MANY, description: (objectMetadata) => `Favorites tied to the ${objectMetadata.labelSingular}`, icon: 'IconHeart', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => FavoriteObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() - @IsSystem() + @WorkspaceIsNullable() + @WorkspaceIsSystem() favorites: FavoriteObjectMetadata[]; - @FieldMetadata({ + @WorkspaceRelation({ standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.attachments, - type: FieldMetadataType.RELATION, label: 'Attachments', + type: RelationMetadataType.ONE_TO_MANY, description: (objectMetadata) => `Attachments tied to the ${objectMetadata.labelSingular}`, icon: 'IconFileImport', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => AttachmentObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() + @WorkspaceIsNullable() attachments: AttachmentObjectMetadata[]; - @FieldMetadata({ + @WorkspaceRelation({ standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.timelineActivities, - type: FieldMetadataType.RELATION, label: 'Timeline Activities', + type: RelationMetadataType.ONE_TO_MANY, description: (objectMetadata) => `Timeline Activities tied to the ${objectMetadata.labelSingular}`, - icon: 'IconIconTimelineEvent', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => TimelineActivityObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() - @IsSystem() + @WorkspaceIsNullable() + @WorkspaceIsSystem() timelineActivities: TimelineActivityObjectMetadata[]; } diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-custom-object.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-custom-object.decorator.ts new file mode 100644 index 00000000000..17f6ef526b3 --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-custom-object.decorator.ts @@ -0,0 +1,16 @@ +import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; +import { TypedReflect } from 'src/utils/typed-reflect'; + +export function WorkspaceCustomObject(): ClassDecorator { + return (target) => { + const gate = TypedReflect.getMetadata( + 'workspace:gate-metadata-args', + target, + ); + + metadataArgsStorage.addExtendedEntities({ + target, + gate, + }); + }; +} diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator.ts new file mode 100644 index 00000000000..d7bdd9209b8 --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator.ts @@ -0,0 +1,49 @@ +import { ObjectType } from 'typeorm'; + +import { WorkspaceDynamicRelationMetadataArgsFactory } from 'src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface'; + +import { TypedReflect } from 'src/utils/typed-reflect'; +import { + RelationMetadataType, + RelationOnDeleteAction, +} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; + +interface WorkspaceBaseDynamicRelationOptions { + type: RelationMetadataType; + argsFactory: WorkspaceDynamicRelationMetadataArgsFactory; + inverseSideTarget: () => ObjectType; + inverseSideFieldKey?: keyof TClass; + onDelete?: RelationOnDeleteAction; +} + +export function WorkspaceDynamicRelation( + args: WorkspaceBaseDynamicRelationOptions, +): PropertyDecorator { + return (target, propertyKey) => { + const isSystem = + TypedReflect.getMetadata( + 'workspace:is-system-metadata-args', + target, + propertyKey.toString(), + ) ?? false; + const gate = TypedReflect.getMetadata( + 'workspace:gate-metadata-args', + target, + propertyKey.toString(), + ); + + metadataArgsStorage.addDynamicRelations({ + target: target.constructor, + argsFactory: args.argsFactory, + type: args.type, + inverseSideTarget: args.inverseSideTarget, + inverseSideFieldKey: args.inverseSideFieldKey as string | undefined, + onDelete: args.onDelete, + isSystem, + isNullable: true, + isPrimary: false, + gate, + }); + }; +} diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-field.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-field.decorator.ts index 1edc285653a..60a228d90d5 100644 --- a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-field.decorator.ts +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-field.decorator.ts @@ -5,6 +5,7 @@ import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/fi import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; import { TypedReflect } from 'src/utils/typed-reflect'; +import { generateDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/generate-default-value'; export interface WorkspaceFieldOptions< T extends FieldMetadataType | 'default', @@ -15,7 +16,6 @@ export interface WorkspaceFieldOptions< description?: string | ((objectMetadata: ObjectMetadataEntity) => string); icon?: string; defaultValue?: FieldMetadataDefaultValue; - joinColumn?: string; options?: FieldMetadataOptions; } @@ -23,28 +23,35 @@ export function WorkspaceField( options: WorkspaceFieldOptions, ): PropertyDecorator { return (object, propertyKey) => { - const isPrimary = TypedReflect.getMetadata( - 'workspace:is-primary-field-metadata-args', - object, - propertyKey.toString(), - ); - const isNullable = TypedReflect.getMetadata( - 'workspace:is-nullable-metadata-args', - object, - propertyKey.toString(), - ); - const isSystem = TypedReflect.getMetadata( - 'workspace:is-system-metadata-args', - object, - propertyKey.toString(), - ); + const isPrimary = + TypedReflect.getMetadata( + 'workspace:is-primary-field-metadata-args', + object, + propertyKey.toString(), + ) ?? false; + const isNullable = + TypedReflect.getMetadata( + 'workspace:is-nullable-metadata-args', + object, + propertyKey.toString(), + ) ?? false; + const isSystem = + TypedReflect.getMetadata( + 'workspace:is-system-metadata-args', + object, + propertyKey.toString(), + ) ?? false; const gate = TypedReflect.getMetadata( 'workspace:gate-metadata-args', object, propertyKey.toString(), ); + const defaultValue = (options.defaultValue ?? + generateDefaultValue( + options.type, + )) as FieldMetadataDefaultValue<'default'> | null; - metadataArgsStorage.fields.push({ + metadataArgsStorage.addFields({ target: object.constructor, standardId: options.standardId, name: propertyKey.toString(), @@ -52,7 +59,7 @@ export function WorkspaceField( type: options.type, description: options.description, icon: options.icon, - defaultValue: options.defaultValue, + defaultValue, options: options.options, isPrimary, isNullable, diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-object.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-object.decorator.ts index e57057f8859..a4b0170d0a6 100644 --- a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-object.decorator.ts +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-object.decorator.ts @@ -2,7 +2,7 @@ import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util'; import { TypedReflect } from 'src/utils/typed-reflect'; -interface WorkspaceObjectOptions { +interface WorkspaceEntityOptions { standardId: string; namePlural: string; labelSingular: string; @@ -11,8 +11,8 @@ interface WorkspaceObjectOptions { icon?: string; } -export function WorkspaceObject( - options: WorkspaceObjectOptions, +export function WorkspaceEntity( + options: WorkspaceEntityOptions, ): ClassDecorator { return (target) => { const isAuditLogged = @@ -20,17 +20,16 @@ export function WorkspaceObject( 'workspace:is-audit-logged-metadata-args', target, ) ?? true; - const isSystem = TypedReflect.getMetadata( - 'workspace:is-system-metadata-args', - target, - ); + const isSystem = + TypedReflect.getMetadata('workspace:is-system-metadata-args', target) ?? + false; const gate = TypedReflect.getMetadata( 'workspace:gate-metadata-args', target, ); const objectName = convertClassNameToObjectMetadataName(target.name); - metadataArgsStorage.objects.push({ + metadataArgsStorage.addEntities({ target, standardId: options.standardId, nameSingular: objectName, diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-relation.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-relation.decorator.ts index d583df0df16..e20877f00ea 100644 --- a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-relation.decorator.ts +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-relation.decorator.ts @@ -6,11 +6,12 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; import { TypedReflect } from 'src/utils/typed-reflect'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; interface WorkspaceBaseRelationOptions { standardId: string; - label: string; - description?: string; + label: string | ((objectMetadata: ObjectMetadataEntity) => string); + description?: string | ((objectMetadata: ObjectMetadataEntity) => string); icon?: string; type: TType; inverseSideTarget: () => ObjectType; @@ -38,21 +39,24 @@ export function WorkspaceRelation( | WorkspaceOtherRelationOptions, ): PropertyDecorator { return (object, propertyKey) => { - const isPrimary = TypedReflect.getMetadata( - 'workspace:is-primary-field-metadata-args', - object, - propertyKey.toString(), - ); - const isNullable = TypedReflect.getMetadata( - 'workspace:is-nullable-metadata-args', - object, - propertyKey.toString(), - ); - const isSystem = TypedReflect.getMetadata( - 'workspace:is-system-metadata-args', - object, - propertyKey.toString(), - ); + const isPrimary = + TypedReflect.getMetadata( + 'workspace:is-primary-field-metadata-args', + object, + propertyKey.toString(), + ) ?? false; + const isNullable = + TypedReflect.getMetadata( + 'workspace:is-nullable-metadata-args', + object, + propertyKey.toString(), + ) ?? false; + const isSystem = + TypedReflect.getMetadata( + 'workspace:is-system-metadata-args', + object, + propertyKey.toString(), + ) ?? false; const gate = TypedReflect.getMetadata( 'workspace:gate-metadata-args', object, @@ -67,7 +71,7 @@ export function WorkspaceRelation( : `${propertyKey.toString()}Id`; } - metadataArgsStorage.relations.push({ + metadataArgsStorage.addRelations({ target: object.constructor, standardId: options.standardId, name: propertyKey.toString(), diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema.factory.ts index 060f2a2241c..75bf72cbc30 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema.factory.ts @@ -15,10 +15,10 @@ export class EntitySchemaFactory { ) {} create(target: Type): EntitySchema { - const objectMetadataArgs = metadataArgsStorage.filterObjects(target); + const entityMetadataArgs = metadataArgsStorage.filterEntities(target); - if (!objectMetadataArgs) { - throw new Error('Object metadata args are missing on this target'); + if (!entityMetadataArgs) { + throw new Error('Entity metadata args are missing on this target'); } const fieldMetadataArgsCollection = @@ -35,8 +35,8 @@ export class EntitySchemaFactory { ); const entitySchema = new EntitySchema({ - name: objectMetadataArgs.nameSingular, - tableName: objectMetadataArgs.nameSingular, + name: entityMetadataArgs.nameSingular, + tableName: entityMetadataArgs.nameSingular, columns, relations, }); diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/flatten-composite-types.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/flatten-composite-types.interface.ts deleted file mode 100644 index 5d549c7ec16..00000000000 --- a/packages/twenty-server/src/engine/twenty-orm/interfaces/flatten-composite-types.interface.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { CompositeMetadataTypes } from 'src/engine/metadata-modules/field-metadata/composite-types'; - -// TODO: At the time the composite types are generating union of types instead of a single type for their keys -// We need to find a way to fix that -export type FlattenCompositeTypes = { - [P in keyof T as T[P] extends CompositeMetadataTypes - ? `${string & P}${Capitalize}` - : P]: T[P] extends CompositeMetadataTypes ? T[P][keyof T[P]] : T[P]; -}; diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/twenty-orm-options.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/twenty-orm-options.interface.ts index e9b2ab22477..dc14ceb2ab5 100644 --- a/packages/twenty-server/src/engine/twenty-orm/interfaces/twenty-orm-options.interface.ts +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/twenty-orm-options.interface.ts @@ -1,9 +1,9 @@ import { FactoryProvider, ModuleMetadata, Type } from '@nestjs/common'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; export interface TwentyORMOptions { - objects: Type[]; + workspaceEntities: Type[]; } export type TwentyORMModuleAsyncOptions = { diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface.ts new file mode 100644 index 00000000000..18533f00c84 --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface.ts @@ -0,0 +1,96 @@ +import { ObjectType } from 'typeorm'; + +import { Gate } from 'src/engine/twenty-orm/interfaces/gate.interface'; + +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { + RelationMetadataType, + RelationOnDeleteAction, +} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; + +export type WorkspaceDynamicRelationMetadataArgsFactory = ( + oppositeObjectMetadata: ObjectMetadataEntity, +) => { + /** + * Standard id. + */ + readonly standardId: string; + + /** + * Relation name. + */ + readonly name: string; + + /** + * Relation label. + */ + readonly label: string; + + /** + * Relation description. + */ + readonly description?: string; + + /** + * Relation icon. + */ + readonly icon?: string; + + /** + * Relation join column. + */ + readonly joinColumn?: string; +}; + +export interface WorkspaceDynamicRelationMetadataArgs { + /** + * Class to which relation is applied. + */ + // eslint-disable-next-line @typescript-eslint/ban-types + readonly target: Function; + + /** + * Factory function + */ + readonly argsFactory: WorkspaceDynamicRelationMetadataArgsFactory; + + /** + * Relation type. + */ + readonly type: RelationMetadataType; + + /** + * Relation inverse side target. + */ + readonly inverseSideTarget: () => ObjectType; + + /** + * Relation inverse side field key. + */ + readonly inverseSideFieldKey?: string; + + /** + * Relation on delete action. + */ + readonly onDelete?: RelationOnDeleteAction; + + /** + * Is primary field. + */ + readonly isPrimary: boolean; + + /** + * Is system field. + */ + readonly isSystem: boolean; + + /** + * Is nullable field. + */ + readonly isNullable: boolean; + + /** + * Field gate. + */ + readonly gate?: Gate; +} diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-object-metadata-args.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface.ts similarity index 77% rename from packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-object-metadata-args.interface.ts rename to packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface.ts index b7cf899b9bb..3d55fc2bb0b 100644 --- a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-object-metadata-args.interface.ts +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface.ts @@ -1,6 +1,6 @@ import { Gate } from 'src/engine/twenty-orm/interfaces/gate.interface'; -export interface WorkspaceObjectMetadataArgs { +export interface WorkspaceEntityMetadataArgs { /** * Standard id. */ @@ -12,27 +12,27 @@ export interface WorkspaceObjectMetadataArgs { * String target is a table defined in a json schema. */ // eslint-disable-next-line @typescript-eslint/ban-types - readonly target: Function | string; + readonly target: Function; /** - * Object name. + * Entity name. */ readonly nameSingular: string; readonly namePlural: string; /** - * Object label. + * Entity label. */ readonly labelSingular: string; readonly labelPlural: string; /** - * Object description. + * Entity description. */ readonly description?: string; /** - * Object icon. + * Entity icon. */ readonly icon?: string; @@ -44,10 +44,10 @@ export interface WorkspaceObjectMetadataArgs { /** * Is system object. */ - readonly isSystem?: boolean; + readonly isSystem: boolean; /** - * Object gate. + * Entity gate. */ readonly gate?: Gate; } diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface.ts new file mode 100644 index 00000000000..12706f00484 --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface.ts @@ -0,0 +1,16 @@ +import { Gate } from 'src/engine/twenty-orm/interfaces/gate.interface'; + +export interface WorkspaceExtendedEntityMetadataArgs { + /** + * Class to which table is applied. + * Function target is a table defined in the class. + * String target is a table defined in a json schema. + */ + // eslint-disable-next-line @typescript-eslint/ban-types + readonly target: Function; + + /** + * Entity gate. + */ + readonly gate?: Gate; +} diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface.ts index 08b8d909df4..cad77a674e5 100644 --- a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface.ts +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface.ts @@ -15,7 +15,7 @@ export interface WorkspaceFieldMetadataArgs { * Class to which field is applied. */ // eslint-disable-next-line @typescript-eslint/ban-types - readonly target: Function | string; + readonly target: Function; /** * Field name. @@ -57,17 +57,17 @@ export interface WorkspaceFieldMetadataArgs { /** * Is primary field. */ - readonly isPrimary?: boolean; + readonly isPrimary: boolean; /** * Is system field. */ - readonly isSystem?: boolean; + readonly isSystem: boolean; /** * Is nullable field. */ - readonly isNullable?: boolean; + readonly isNullable: boolean; /** * Field gate. diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface.ts index 5afe81883ed..911e9d78e8e 100644 --- a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface.ts +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface.ts @@ -18,7 +18,7 @@ export interface WorkspaceRelationMetadataArgs { * Class to which relation is applied. */ // eslint-disable-next-line @typescript-eslint/ban-types - readonly target: Function | string; + readonly target: Function; /** * Relation name. @@ -70,17 +70,17 @@ export interface WorkspaceRelationMetadataArgs { /** * Is primary field. */ - readonly isPrimary?: boolean; + readonly isPrimary: boolean; /** * Is system field. */ - readonly isSystem?: boolean; + readonly isSystem: boolean; /** * Is nullable field. */ - readonly isNullable?: boolean; + readonly isNullable: boolean; /** * Field gate. diff --git a/packages/twenty-server/src/engine/twenty-orm/storage/metadata-args.storage.ts b/packages/twenty-server/src/engine/twenty-orm/storage/metadata-args.storage.ts index f54da7ea4e7..9fb114be94f 100644 --- a/packages/twenty-server/src/engine/twenty-orm/storage/metadata-args.storage.ts +++ b/packages/twenty-server/src/engine/twenty-orm/storage/metadata-args.storage.ts @@ -1,24 +1,72 @@ /* eslint-disable @typescript-eslint/ban-types */ +import { WorkspaceDynamicRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface'; import { WorkspaceFieldMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface'; -import { WorkspaceObjectMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-object-metadata-args.interface'; +import { WorkspaceEntityMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface'; import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface'; +import { WorkspaceExtendedEntityMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-extended-entity-metadata-args.interface'; export class MetadataArgsStorage { - readonly objects: WorkspaceObjectMetadataArgs[] = []; - readonly fields: WorkspaceFieldMetadataArgs[] = []; - readonly relations: WorkspaceRelationMetadataArgs[] = []; + private readonly entities: WorkspaceEntityMetadataArgs[] = []; + private readonly extendedEntities: WorkspaceExtendedEntityMetadataArgs[] = []; + private readonly fields: WorkspaceFieldMetadataArgs[] = []; + private readonly relations: WorkspaceRelationMetadataArgs[] = []; + private readonly dynamicRelations: WorkspaceDynamicRelationMetadataArgs[] = + []; + + addEntities(...entities: WorkspaceEntityMetadataArgs[]): void { + this.entities.push(...entities); + } + + addExtendedEntities( + ...extendedEntities: WorkspaceExtendedEntityMetadataArgs[] + ): void { + this.extendedEntities.push(...extendedEntities); + } + + addFields(...fields: WorkspaceFieldMetadataArgs[]): void { + this.fields.push(...fields); + } + + addRelations(...relations: WorkspaceRelationMetadataArgs[]): void { + this.relations.push(...relations); + } - filterObjects( + addDynamicRelations( + ...dynamicRelations: WorkspaceDynamicRelationMetadataArgs[] + ): void { + this.dynamicRelations.push(...dynamicRelations); + } + + filterEntities( target: Function | string, - ): WorkspaceObjectMetadataArgs | undefined; + ): WorkspaceEntityMetadataArgs | undefined; - filterObjects(target: (Function | string)[]): WorkspaceObjectMetadataArgs[]; + filterEntities(target: (Function | string)[]): WorkspaceEntityMetadataArgs[]; - filterObjects( + filterEntities( target: (Function | string) | (Function | string)[], - ): WorkspaceObjectMetadataArgs | undefined | WorkspaceObjectMetadataArgs[] { - const objects = this.filterByTarget(this.objects, target); + ): WorkspaceEntityMetadataArgs | undefined | WorkspaceEntityMetadataArgs[] { + const objects = this.filterByTarget(this.entities, target); + + return Array.isArray(objects) ? objects[0] : objects; + } + + filterExtendedEntities( + target: Function | string, + ): WorkspaceExtendedEntityMetadataArgs | undefined; + + filterExtendedEntities( + target: (Function | string)[], + ): WorkspaceExtendedEntityMetadataArgs[]; + + filterExtendedEntities( + target: (Function | string) | (Function | string)[], + ): + | WorkspaceExtendedEntityMetadataArgs + | undefined + | WorkspaceExtendedEntityMetadataArgs[] { + const objects = this.filterByTarget(this.extendedEntities, target); return Array.isArray(objects) ? objects[0] : objects; } @@ -45,6 +93,20 @@ export class MetadataArgsStorage { return this.filterByTarget(this.relations, target); } + filterDynamicRelations( + target: Function | string, + ): WorkspaceDynamicRelationMetadataArgs[]; + + filterDynamicRelations( + target: (Function | string)[], + ): WorkspaceDynamicRelationMetadataArgs[]; + + filterDynamicRelations( + target: (Function | string) | (Function | string)[], + ): WorkspaceDynamicRelationMetadataArgs[] { + return this.filterByTarget(this.dynamicRelations, target); + } + protected filterByTarget( array: T[], target: (Function | string) | (Function | string)[], diff --git a/packages/twenty-server/src/engine/twenty-orm/twenty-orm-core.module.ts b/packages/twenty-server/src/engine/twenty-orm/twenty-orm-core.module.ts index 72c50e74719..a960c9a0fb4 100644 --- a/packages/twenty-server/src/engine/twenty-orm/twenty-orm-core.module.ts +++ b/packages/twenty-server/src/engine/twenty-orm/twenty-orm-core.module.ts @@ -45,7 +45,7 @@ export class TwentyORMCoreModule entitySchemaFactory: EntitySchemaFactory, scopedWorkspaceDatasourceFactory: ScopedWorkspaceDatasourceFactory, ) => { - const entities = options.objects.map((entityClass) => + const entities = options.workspaceEntities.map((entityClass) => entitySchemaFactory.create(entityClass), ); @@ -80,7 +80,7 @@ export class TwentyORMCoreModule scopedWorkspaceDatasourceFactory: ScopedWorkspaceDatasourceFactory, options: TwentyORMOptions, ) => { - const entities = options.objects.map((entityClass) => + const entities = options.workspaceEntities.map((entityClass) => entitySchemaFactory.create(entityClass), ); diff --git a/packages/twenty-server/src/engine/twenty-orm/workspace-object-tests/attachment.object-metadata.ts b/packages/twenty-server/src/engine/twenty-orm/workspace-object-tests/attachment.object-metadata.ts deleted file mode 100644 index cbe74744503..00000000000 --- a/packages/twenty-server/src/engine/twenty-orm/workspace-object-tests/attachment.object-metadata.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; - -import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { ATTACHMENT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; -import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { WorkspaceObject } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; -import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; -import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; -import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -import { BaseObjectMetadata } from 'src/engine/twenty-orm/workspace-object-tests/base.object-metadata'; -import { WorkspaceMemberObjectMetadata } from 'src/engine/twenty-orm/workspace-object-tests/workspace-member.object-metadata'; -import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; -import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; - -@WorkspaceObject({ - standardId: STANDARD_OBJECT_IDS.attachment, - namePlural: 'attachments', - labelSingular: 'Attachment', - labelPlural: 'Attachments', - description: 'An attachment', - icon: 'IconFileImport', -}) -@WorkspaceIsSystem() -@WorkspaceIsNotAuditLogged() -export class AttachmentObjectMetadata extends BaseObjectMetadata { - @WorkspaceField({ - standardId: ATTACHMENT_STANDARD_FIELD_IDS.name, - type: FieldMetadataType.TEXT, - label: 'Name', - description: 'Attachment name', - icon: 'IconFileUpload', - }) - name: string; - - @WorkspaceField({ - standardId: ATTACHMENT_STANDARD_FIELD_IDS.fullPath, - type: FieldMetadataType.TEXT, - label: 'Full path', - description: 'Attachment full path', - icon: 'IconLink', - }) - fullPath: string; - - @WorkspaceField({ - standardId: ATTACHMENT_STANDARD_FIELD_IDS.type, - type: FieldMetadataType.TEXT, - label: 'Type', - description: 'Attachment type', - icon: 'IconList', - }) - type: string; - - @WorkspaceRelation({ - standardId: ATTACHMENT_STANDARD_FIELD_IDS.author, - label: 'Author', - type: RelationMetadataType.MANY_TO_ONE, - inverseSideTarget: () => WorkspaceMemberObjectMetadata, - inverseSideFieldKey: 'authoredAttachments', - }) - author: Relation; -} diff --git a/packages/twenty-server/src/engine/twenty-orm/workspace-object-tests/company.object-metadata.ts b/packages/twenty-server/src/engine/twenty-orm/workspace-object-tests/company.object-metadata.ts deleted file mode 100644 index 1235c9207dd..00000000000 --- a/packages/twenty-server/src/engine/twenty-orm/workspace-object-tests/company.object-metadata.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { CurrencyMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/currency.composite-type'; -import { LinkMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/link.composite-type'; -import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { - RelationMetadataType, - RelationOnDeleteAction, -} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -import { COMPANY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; -import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { WorkspaceObject } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; -import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; -import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; -import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; -import { WorkspaceMemberObjectMetadata } from 'src/engine/twenty-orm/workspace-object-tests/workspace-member.object-metadata'; -import { BaseObjectMetadata } from 'src/engine/twenty-orm/workspace-object-tests/base.object-metadata'; -import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; - -@WorkspaceObject({ - standardId: STANDARD_OBJECT_IDS.company, - namePlural: 'companies', - labelSingular: 'Company', - labelPlural: 'Companies', - description: 'A company', - icon: 'IconBuildingSkyscraper', -}) -export class CompanyObjectMetadata extends BaseObjectMetadata { - @WorkspaceField({ - standardId: COMPANY_STANDARD_FIELD_IDS.name, - type: FieldMetadataType.TEXT, - label: 'Name', - description: 'The company name', - icon: 'IconBuildingSkyscraper', - }) - name: string; - - @WorkspaceField({ - standardId: COMPANY_STANDARD_FIELD_IDS.domainName, - type: FieldMetadataType.TEXT, - label: 'Domain Name', - description: - 'The company website URL. We use this url to fetch the company icon', - icon: 'IconLink', - }) - domainName?: string; - - @WorkspaceField({ - standardId: COMPANY_STANDARD_FIELD_IDS.address, - type: FieldMetadataType.TEXT, - label: 'Address', - description: 'The company address', - icon: 'IconMap', - }) - address: string; - - @WorkspaceField({ - standardId: COMPANY_STANDARD_FIELD_IDS.employees, - type: FieldMetadataType.NUMBER, - label: 'Employees', - description: 'Number of employees in the company', - icon: 'IconUsers', - }) - @WorkspaceIsNullable() - employees: number; - - @WorkspaceField({ - standardId: COMPANY_STANDARD_FIELD_IDS.linkedinLink, - type: FieldMetadataType.LINK, - label: 'Linkedin', - description: 'The company Linkedin account', - icon: 'IconBrandLinkedin', - }) - @WorkspaceIsNullable() - linkedinLink: LinkMetadata; - - @WorkspaceField({ - standardId: COMPANY_STANDARD_FIELD_IDS.xLink, - type: FieldMetadataType.LINK, - label: 'X', - description: 'The company Twitter/X account', - icon: 'IconBrandX', - }) - @WorkspaceIsNullable() - xLink: LinkMetadata; - - @WorkspaceField({ - standardId: COMPANY_STANDARD_FIELD_IDS.annualRecurringRevenue, - type: FieldMetadataType.CURRENCY, - label: 'ARR', - description: - 'Annual Recurring Revenue: The actual or estimated annual revenue of the company', - icon: 'IconMoneybag', - }) - @WorkspaceIsNullable() - annualRecurringRevenue: CurrencyMetadata; - - @WorkspaceField({ - standardId: COMPANY_STANDARD_FIELD_IDS.idealCustomerProfile, - type: FieldMetadataType.BOOLEAN, - label: 'ICP', - description: - 'Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you', - icon: 'IconTarget', - defaultValue: false, - }) - idealCustomerProfile: boolean; - - @WorkspaceField({ - standardId: COMPANY_STANDARD_FIELD_IDS.position, - type: FieldMetadataType.POSITION, - label: 'Position', - description: 'Company record position', - icon: 'IconHierarchy2', - }) - @WorkspaceIsSystem() - @WorkspaceIsNullable() - position: number; - - @WorkspaceRelation({ - standardId: COMPANY_STANDARD_FIELD_IDS.accountOwner, - label: 'Account Owner', - description: - 'Your team member responsible for managing the company account', - type: RelationMetadataType.MANY_TO_ONE, - inverseSideTarget: () => WorkspaceMemberObjectMetadata, - inverseSideFieldKey: 'accountOwnerForCompanies', - onDelete: RelationOnDeleteAction.SET_NULL, - }) - @WorkspaceIsNullable() - accountOwner: WorkspaceMemberObjectMetadata; -} diff --git a/packages/twenty-server/src/engine/twenty-orm/workspace-object-tests/workspace-member.object-metadata.ts b/packages/twenty-server/src/engine/twenty-orm/workspace-object-tests/workspace-member.object-metadata.ts deleted file mode 100644 index 291618d721e..00000000000 --- a/packages/twenty-server/src/engine/twenty-orm/workspace-object-tests/workspace-member.object-metadata.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; - -import { FullNameMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/full-name.composite-type'; -import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { - RelationMetadataType, - RelationOnDeleteAction, -} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -import { WORKSPACE_MEMBER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; -import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { AttachmentObjectMetadata } from 'src/modules/attachment/standard-objects/attachment.object-metadata'; -import { WorkspaceObject } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; -import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; -import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; -import { BaseObjectMetadata } from 'src/engine/twenty-orm/workspace-object-tests/base.object-metadata'; -import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; -import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; -import { CompanyObjectMetadata } from 'src/engine/twenty-orm/workspace-object-tests/company.object-metadata'; - -@WorkspaceObject({ - standardId: STANDARD_OBJECT_IDS.workspaceMember, - namePlural: 'workspaceMembers', - labelSingular: 'Workspace Member', - labelPlural: 'Workspace Members', - description: 'A workspace member', - icon: 'IconUserCircle', -}) -@WorkspaceIsSystem() -@WorkspaceIsNotAuditLogged() -export class WorkspaceMemberObjectMetadata extends BaseObjectMetadata { - @WorkspaceField({ - standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.name, - type: FieldMetadataType.FULL_NAME, - label: 'Name', - description: 'Workspace member name', - icon: 'IconCircleUser', - }) - name: FullNameMetadata; - - @WorkspaceField({ - standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.colorScheme, - type: FieldMetadataType.TEXT, - label: 'Color Scheme', - description: 'Preferred color scheme', - icon: 'IconColorSwatch', - defaultValue: "'Light'", - }) - colorScheme: string; - - @WorkspaceField({ - standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.locale, - type: FieldMetadataType.TEXT, - label: 'Language', - description: 'Preferred language', - icon: 'IconLanguage', - defaultValue: "'en'", - }) - locale: string; - - @WorkspaceField({ - standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.avatarUrl, - type: FieldMetadataType.TEXT, - label: 'Avatar Url', - description: 'Workspace member avatar', - icon: 'IconFileUpload', - }) - avatarUrl: string; - - @WorkspaceField({ - standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.userEmail, - type: FieldMetadataType.TEXT, - label: 'User Email', - description: 'Related user email address', - icon: 'IconMail', - }) - userEmail: string; - - @WorkspaceField({ - standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.userId, - type: FieldMetadataType.UUID, - label: 'User Id', - description: 'Associated User Id', - icon: 'IconCircleUsers', - }) - userId: string; - - @WorkspaceRelation({ - standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.authoredAttachments, - label: 'Authored attachments', - description: 'Attachments created by the workspace member', - icon: 'IconFileImport', - type: RelationMetadataType.ONE_TO_MANY, - inverseSideTarget: () => AttachmentObjectMetadata, - inverseSideFieldKey: 'author', - onDelete: RelationOnDeleteAction.SET_NULL, - }) - authoredAttachments: Relation; - - @WorkspaceRelation({ - standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.accountOwnerForCompanies, - label: 'Account Owner For Companies', - description: 'Account owner for companies', - icon: 'IconBriefcase', - type: RelationMetadataType.ONE_TO_MANY, - inverseSideTarget: () => CompanyObjectMetadata, - inverseSideFieldKey: 'accountOwner', - onDelete: RelationOnDeleteAction.SET_NULL, - }) - accountOwnerForCompanies: Relation; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts index 5959f5791fb..fe789c366ae 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts @@ -10,7 +10,7 @@ import { standardObjectMetadataDefinitions } from 'src/engine/workspace-manager/ import { StandardObjectFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory'; import { computeStandardObject } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util'; import { StandardFieldFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory'; -import { CustomObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/custom-objects/custom.object-metadata'; +import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity'; interface RunCommandOptions { workspaceId?: string; @@ -61,7 +61,7 @@ export class AddStandardIdCommand extends CommandRunner { }, ); const standardFieldMetadataCollection = this.standardFieldFactory.create( - CustomObjectMetadata, + CustomWorkspaceEntity, { workspaceId: '', dataSourceId: '', diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/base-custom-object-metadata.decorator.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/base-custom-object-metadata.decorator.ts deleted file mode 100644 index 34e821d6318..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/base-custom-object-metadata.decorator.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { BaseCustomObjectMetadataDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-custom-object-metadata.interface'; - -import { TypedReflect } from 'src/utils/typed-reflect'; - -export function BaseCustomObjectMetadata( - params?: BaseCustomObjectMetadataDecoratorParams, -): ClassDecorator { - return (target) => { - const gate = TypedReflect.getMetadata('gate', target); - - TypedReflect.defineMetadata( - 'extendObjectMetadata', - { - ...params, - gate, - }, - target, - ); - }; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/dynamic-field-metadata.interface.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/dynamic-field-metadata.interface.ts deleted file mode 100644 index 3d0b49ec375..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/dynamic-field-metadata.interface.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { DynamicRelationFieldMetadataDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-computed-relation-field-metadata.interface'; - -import { TypedReflect } from 'src/utils/typed-reflect'; -import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; - -export function DynamicRelationFieldMetadata( - params: DynamicRelationFieldMetadataDecoratorParams, -): PropertyDecorator { - return (target: object, fieldKey: string) => { - const isSystem = - TypedReflect.getMetadata('isSystem', target, fieldKey) ?? false; - const gate = TypedReflect.getMetadata('gate', target, fieldKey); - - TypedReflect.defineMetadata( - 'dynamicRelationFieldMetadataMap', - { - type: FieldMetadataType.RELATION, - paramsFactory: params, - isCustom: false, - isNullable: true, - isSystem, - gate, - }, - target.constructor, - ); - }; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator.ts deleted file mode 100644 index b5e57e0e3c6..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { - FieldMetadataDecoratorParams, - ReflectFieldMetadata, -} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-field-metadata.interface'; -import { GateDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.interface'; -import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface'; - -import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { generateDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/generate-default-value'; -import { TypedReflect } from 'src/utils/typed-reflect'; -import { createDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util'; - -export function FieldMetadata( - params: FieldMetadataDecoratorParams, -): PropertyDecorator { - return (target: object, fieldKey: string) => { - const existingFieldMetadata = - TypedReflect.getMetadata('fieldMetadataMap', target.constructor) ?? {}; - const isNullable = - TypedReflect.getMetadata('isNullable', target, fieldKey) ?? false; - const isSystem = - TypedReflect.getMetadata('isSystem', target, fieldKey) ?? false; - const gate = TypedReflect.getMetadata('gate', target, fieldKey); - const { joinColumn, standardId, ...restParams } = params; - - TypedReflect.defineMetadata( - 'fieldMetadataMap', - { - ...existingFieldMetadata, - [fieldKey]: generateFieldMetadata( - { - ...restParams, - standardId, - joinColumn, - }, - fieldKey, - isNullable, - isSystem, - gate, - ), - ...(joinColumn && restParams.type === FieldMetadataType.RELATION - ? { - [joinColumn]: generateFieldMetadata( - { - ...restParams, - standardId: createDeterministicUuid(standardId), - type: FieldMetadataType.UUID, - label: `${restParams.label} id (foreign key)`, - description: `${restParams.description} id foreign key`, - defaultValue: null, - options: undefined, - settings: undefined, - joinColumn, - }, - joinColumn, - isNullable, - true, - gate, - ), - } - : {}), - }, - target.constructor, - ); - }; -} - -function generateFieldMetadata( - params: FieldMetadataDecoratorParams, - fieldKey: string, - isNullable: boolean, - isSystem: boolean, - gate: GateDecoratorParams | undefined = undefined, -): ReflectFieldMetadata[string] { - const defaultValue = (params.defaultValue ?? - generateDefaultValue( - params.type, - )) as FieldMetadataDefaultValue<'default'> | null; - - return { - name: fieldKey, - ...params, - isNullable: params.type === FieldMetadataType.RELATION ? true : isNullable, - isSystem, - isCustom: false, - options: params.options, - description: params.description, - icon: params.icon, - defaultValue, - gate, - }; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/gate.decorator.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/gate.decorator.ts deleted file mode 100644 index c492e1b8a2f..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/gate.decorator.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { GateDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.interface'; - -import { TypedReflect } from 'src/utils/typed-reflect'; - -export function Gate(metadata: GateDecoratorParams) { - return function (target: object, fieldKey?: string) { - if (fieldKey) { - TypedReflect.defineMetadata('gate', metadata, target, fieldKey); - } else { - TypedReflect.defineMetadata('gate', metadata, target); - } - }; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator.ts deleted file mode 100644 index 394303d03fe..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { TypedReflect } from 'src/utils/typed-reflect'; - -export function IsNotAuditLogged() { - return function (target: object) { - TypedReflect.defineMetadata('isAuditLogged', false, target); - }; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator.ts deleted file mode 100644 index 3630d752ede..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { TypedReflect } from 'src/utils/typed-reflect'; - -export function IsNullable() { - return function (target: object, fieldKey: string) { - TypedReflect.defineMetadata('isNullable', true, target, fieldKey); - }; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator.ts deleted file mode 100644 index 8d21db2dec3..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { TypedReflect } from 'src/utils/typed-reflect'; - -export function IsSystem() { - return function (target: object, fieldKey?: string) { - if (fieldKey) { - TypedReflect.defineMetadata('isSystem', true, target, fieldKey); - } else { - TypedReflect.defineMetadata('isSystem', true, target); - } - }; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator.ts deleted file mode 100644 index 2d21189aa5d..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ObjectMetadataDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-object-metadata.interface'; - -import { TypedReflect } from 'src/utils/typed-reflect'; -import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util'; - -export function ObjectMetadata( - params: ObjectMetadataDecoratorParams, -): ClassDecorator { - return (target) => { - const isSystem = TypedReflect.getMetadata('isSystem', target) ?? false; - const isAuditLogged = - TypedReflect.getMetadata('isAuditLogged', target) ?? true; - const gate = TypedReflect.getMetadata('gate', target); - const objectName = convertClassNameToObjectMetadataName(target.name); - - TypedReflect.defineMetadata( - 'objectMetadata', - { - nameSingular: objectName, - ...params, - targetTableName: 'DEPRECATED', - isSystem, - isCustom: false, - isRemote: false, - isAuditLogged, - description: params.description, - icon: params.icon, - gate, - }, - target, - ); - }; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator.ts deleted file mode 100644 index 2981b4f9c90..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator.ts +++ /dev/null @@ -1,35 +0,0 @@ -import 'reflect-metadata'; - -import { - ReflectRelationMetadata, - RelationMetadataDecoratorParams, -} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-relation-metadata.interface'; - -import { TypedReflect } from 'src/utils/typed-reflect'; - -export function RelationMetadata( - params: RelationMetadataDecoratorParams, -): PropertyDecorator { - return (target: object, fieldKey: string) => { - const relationMetadataCollection = - TypedReflect.getMetadata( - 'reflectRelationMetadataCollection', - target.constructor, - ) ?? []; - const gate = TypedReflect.getMetadata('gate', target, fieldKey); - - TypedReflect.defineMetadata( - 'reflectRelationMetadataCollection', - [ - ...relationMetadataCollection, - { - target, - fieldKey, - ...params, - gate, - } satisfies ReflectRelationMetadata, - ], - target.constructor, - ); - }; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts index d665fa55627..07bb1ef059d 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory.ts @@ -6,97 +6,219 @@ import { PartialComputedFieldMetadata, PartialFieldMetadata, } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface'; -import { ReflectFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-field-metadata.interface'; -import { ReflectObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-object-metadata.interface'; -import { ReflectDynamicRelationFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-computed-relation-field-metadata.interface'; +import { WorkspaceEntityMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface'; +import { WorkspaceFieldMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface'; +import { WorkspaceDynamicRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface'; +import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface'; -import { TypedReflect } from 'src/utils/typed-reflect'; import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util'; +import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { createDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util'; @Injectable() export class StandardFieldFactory { create( - target: object, + target: typeof BaseWorkspaceEntity, context: WorkspaceSyncContext, workspaceFeatureFlagsMap: FeatureFlagMap, - ): (PartialFieldMetadata | PartialComputedFieldMetadata)[] { - const reflectObjectMetadata = TypedReflect.getMetadata( - 'objectMetadata', - target, - ); - const reflectFieldMetadataMap = - TypedReflect.getMetadata('fieldMetadataMap', target) ?? []; - const reflectDynamicRelationFieldMetadataMap = TypedReflect.getMetadata( - 'dynamicRelationFieldMetadataMap', - target, - ); - const partialFieldMetadataCollection: ( - | PartialFieldMetadata - | PartialComputedFieldMetadata - )[] = Object.values(reflectFieldMetadataMap) - .map((reflectFieldMetadata) => - this.createFieldMetadata( - reflectObjectMetadata, - reflectFieldMetadata, + ): Array { + const workspaceEntityMetadataArgs = + metadataArgsStorage.filterEntities(target); + const metadataCollections = this.collectMetadata(target); + + return [ + ...this.processMetadata( + workspaceEntityMetadataArgs, + metadataCollections.fields, + context, + workspaceFeatureFlagsMap, + this.createFieldMetadata, + ), + ...this.processMetadata( + workspaceEntityMetadataArgs, + metadataCollections.relations, + context, + workspaceFeatureFlagsMap, + this.createFieldRelationMetadata, + ), + ...this.processMetadata( + workspaceEntityMetadataArgs, + metadataCollections.dynamicRelations, + context, + workspaceFeatureFlagsMap, + this.createComputedFieldRelationMetadata, + ), + ]; + } + + private collectMetadata(target: typeof BaseWorkspaceEntity) { + return { + fields: metadataArgsStorage.filterFields(target), + relations: metadataArgsStorage.filterRelations(target), + dynamicRelations: metadataArgsStorage.filterDynamicRelations(target), + }; + } + + private processMetadata< + T, + U extends PartialFieldMetadata | PartialComputedFieldMetadata, + >( + workspaceEntityMetadataArgs: WorkspaceEntityMetadataArgs | undefined, + metadataArgs: T[], + context: WorkspaceSyncContext, + featureFlagsMap: FeatureFlagMap, + createMetadata: ( + workspaceEntityMetadataArgs: WorkspaceEntityMetadataArgs | undefined, + args: T, + context: WorkspaceSyncContext, + featureFlagsMap: FeatureFlagMap, + ) => U[], + ): U[] { + return metadataArgs + .flatMap((args) => + createMetadata( + workspaceEntityMetadataArgs, + args, context, - workspaceFeatureFlagsMap, + featureFlagsMap, ), ) - .filter((metadata): metadata is PartialFieldMetadata => !!metadata); - const partialComputedFieldMetadata = this.createComputedFieldMetadata( - reflectDynamicRelationFieldMetadataMap, - context, - workspaceFeatureFlagsMap, - ); + .filter(Boolean) as U[]; + } - if (partialComputedFieldMetadata) { - partialFieldMetadataCollection.push(partialComputedFieldMetadata); + /** + * Create field metadata + */ + private createFieldMetadata( + workspaceEntityMetadataArgs: WorkspaceEntityMetadataArgs | undefined, + workspaceFieldMetadataArgs: WorkspaceFieldMetadataArgs, + context: WorkspaceSyncContext, + workspaceFeatureFlagsMap: FeatureFlagMap, + ): PartialFieldMetadata[] { + if ( + isGatedAndNotEnabled( + workspaceFieldMetadataArgs.gate, + workspaceFeatureFlagsMap, + ) + ) { + return []; } - return partialFieldMetadataCollection; + return [ + { + type: workspaceFieldMetadataArgs.type, + standardId: workspaceFieldMetadataArgs.standardId, + name: workspaceFieldMetadataArgs.name, + icon: workspaceFieldMetadataArgs.icon, + label: workspaceFieldMetadataArgs.label, + description: workspaceFieldMetadataArgs.description, + defaultValue: workspaceFieldMetadataArgs.defaultValue, + options: workspaceFieldMetadataArgs.options, + workspaceId: context.workspaceId, + isNullable: workspaceFieldMetadataArgs.isNullable, + isCustom: false, + isSystem: + workspaceEntityMetadataArgs?.isSystem || + workspaceFieldMetadataArgs.isSystem, + }, + ]; } - private createFieldMetadata( - reflectObjectMetadata: ReflectObjectMetadata | undefined, - reflectFieldMetadata: ReflectFieldMetadata[string], + /** + * Create relation field metadata + */ + private createFieldRelationMetadata( + workspaceEntityMetadataArgs: WorkspaceEntityMetadataArgs | undefined, + workspaceRelationMetadataArgs: WorkspaceRelationMetadataArgs, context: WorkspaceSyncContext, workspaceFeatureFlagsMap: FeatureFlagMap, - ): PartialFieldMetadata | undefined { + ): PartialFieldMetadata[] { + const fieldMetadataCollection: PartialFieldMetadata[] = []; + const foreignKeyStandardId = createDeterministicUuid( + workspaceRelationMetadataArgs.standardId, + ); + if ( - isGatedAndNotEnabled(reflectFieldMetadata.gate, workspaceFeatureFlagsMap) + isGatedAndNotEnabled( + workspaceRelationMetadataArgs.gate, + workspaceFeatureFlagsMap, + ) ) { - return undefined; + return []; } - return { - ...reflectFieldMetadata, + if (workspaceRelationMetadataArgs.joinColumn) { + fieldMetadataCollection.push({ + type: FieldMetadataType.UUID, + standardId: foreignKeyStandardId, + name: workspaceRelationMetadataArgs.joinColumn, + label: `${workspaceRelationMetadataArgs.label} id (foreign key)`, + description: `${workspaceRelationMetadataArgs.description} id foreign key`, + icon: workspaceRelationMetadataArgs.icon, + defaultValue: null, + options: undefined, + settings: undefined, + workspaceId: context.workspaceId, + isCustom: false, + isSystem: true, + isNullable: workspaceRelationMetadataArgs.isNullable, + }); + } + + fieldMetadataCollection.push({ + type: FieldMetadataType.RELATION, + standardId: workspaceRelationMetadataArgs.standardId, + name: workspaceRelationMetadataArgs.name, + label: workspaceRelationMetadataArgs.label, + description: workspaceRelationMetadataArgs.description, + icon: workspaceRelationMetadataArgs.icon, + defaultValue: null, workspaceId: context.workspaceId, + isCustom: false, isSystem: - reflectObjectMetadata?.isSystem || reflectFieldMetadata.isSystem, - }; + workspaceEntityMetadataArgs?.isSystem || + workspaceRelationMetadataArgs.isSystem, + isNullable: true, + }); + + return fieldMetadataCollection; } - private createComputedFieldMetadata( - reflectDynamicRelationFieldMetadata: - | ReflectDynamicRelationFieldMetadata + /** + * Create computed field relation metadata + */ + private createComputedFieldRelationMetadata( + workspaceEntityMetadataArgs: WorkspaceEntityMetadataArgs | undefined, + workspaceDynamicRelationMetadataArgs: + | WorkspaceDynamicRelationMetadataArgs | undefined, context: WorkspaceSyncContext, workspaceFeatureFlagsMap: FeatureFlagMap, - ): PartialComputedFieldMetadata | undefined { + ): PartialComputedFieldMetadata[] { if ( - !reflectDynamicRelationFieldMetadata || + !workspaceDynamicRelationMetadataArgs || isGatedAndNotEnabled( - reflectDynamicRelationFieldMetadata.gate, + workspaceDynamicRelationMetadataArgs.gate, workspaceFeatureFlagsMap, ) ) { - return undefined; + return []; } - return { - ...reflectDynamicRelationFieldMetadata, - workspaceId: context.workspaceId, - isSystem: reflectDynamicRelationFieldMetadata.isSystem, - }; + return [ + // Foreign key will be computed in compute-standard-object.util.ts, because we need to know the custom object + { + type: FieldMetadataType.RELATION, + argsFactory: workspaceDynamicRelationMetadataArgs.argsFactory, + workspaceId: context.workspaceId, + isCustom: false, + isSystem: + workspaceEntityMetadataArgs?.isSystem || + workspaceDynamicRelationMetadataArgs.isSystem, + isNullable: workspaceDynamicRelationMetadataArgs.isNullable, + }, + ]; } } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts index c58e6c749bf..26f58ba80b2 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-object.factory.ts @@ -4,9 +4,9 @@ import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-syn import { PartialObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface'; import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; -import { TypedReflect } from 'src/utils/typed-reflect'; import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; import { StandardFieldFactory } from './standard-field.factory'; @@ -15,7 +15,7 @@ export class StandardObjectFactory { constructor(private readonly standardFieldFactory: StandardFieldFactory) {} create( - standardObjectMetadataDefinitions: (typeof BaseObjectMetadata)[], + standardObjectMetadataDefinitions: (typeof BaseWorkspaceEntity)[], context: WorkspaceSyncContext, workspaceFeatureFlagsMap: FeatureFlagMap, ): PartialObjectMetadata[] { @@ -27,32 +27,43 @@ export class StandardObjectFactory { } private createObjectMetadata( - metadata: typeof BaseObjectMetadata, + target: typeof BaseWorkspaceEntity, context: WorkspaceSyncContext, workspaceFeatureFlagsMap: FeatureFlagMap, ): PartialObjectMetadata | undefined { - const objectMetadata = TypedReflect.getMetadata('objectMetadata', metadata); + const workspaceEntityMetadataArgs = + metadataArgsStorage.filterEntities(target); - if (!objectMetadata) { + if (!workspaceEntityMetadataArgs) { throw new Error( - `Object metadata decorator not found, can't parse ${metadata.name}`, + `Object metadata decorator not found, can't parse ${target.name}`, ); } - if (isGatedAndNotEnabled(objectMetadata.gate, workspaceFeatureFlagsMap)) { + if ( + isGatedAndNotEnabled( + workspaceEntityMetadataArgs.gate, + workspaceFeatureFlagsMap, + ) + ) { return undefined; } const fields = this.standardFieldFactory.create( - metadata, + target, context, workspaceFeatureFlagsMap, ); return { - ...objectMetadata, + ...workspaceEntityMetadataArgs, + // TODO: Remove targetTableName when we remove the old metadata + targetTableName: 'DEPRECATED', workspaceId: context.workspaceId, dataSourceId: context.dataSourceId, + isCustom: false, + isRemote: false, + isSystem: workspaceEntityMetadataArgs.isSystem ?? false, fields, }; } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-relation.factory.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-relation.factory.ts index a20a7d752f8..f77d74f59ff 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-relation.factory.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/factories/standard-relation.factory.ts @@ -3,17 +3,20 @@ import { Injectable } from '@nestjs/common'; import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface'; import { FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; -import { TypedReflect } from 'src/utils/typed-reflect'; import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util'; import { assert } from 'src/utils/assert'; -import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { + RelationMetadataEntity, + RelationMetadataType, +} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; interface CustomRelationFactory { object: ObjectMetadataEntity; - metadata: typeof BaseObjectMetadata; + metadata: typeof BaseWorkspaceEntity; } @Injectable() @@ -26,7 +29,7 @@ export class StandardRelationFactory { ): Partial[]; create( - standardObjectMetadataDefinitions: (typeof BaseObjectMetadata)[], + standardObjectMetadataDefinitions: (typeof BaseWorkspaceEntity)[], context: WorkspaceSyncContext, originalObjectMetadataMap: Record, workspaceFeatureFlagsMap: FeatureFlagMap, @@ -34,10 +37,10 @@ export class StandardRelationFactory { create( standardObjectMetadataDefinitionsOrCustomObjectFactories: - | (typeof BaseObjectMetadata)[] + | (typeof BaseWorkspaceEntity)[] | { object: ObjectMetadataEntity; - metadata: typeof BaseObjectMetadata; + metadata: typeof BaseWorkspaceEntity; }[], context: WorkspaceSyncContext, originalObjectMetadataMap: Record, @@ -46,7 +49,7 @@ export class StandardRelationFactory { return standardObjectMetadataDefinitionsOrCustomObjectFactories.flatMap( ( standardObjectMetadata: - | typeof BaseObjectMetadata + | typeof BaseWorkspaceEntity | CustomRelationFactory, ) => this.createRelationMetadata( @@ -59,64 +62,68 @@ export class StandardRelationFactory { } private createRelationMetadata( - standardObjectMetadataOrCustomRelationFactory: - | typeof BaseObjectMetadata + workspaceEntityOrCustomRelationFactory: + | typeof BaseWorkspaceEntity | CustomRelationFactory, context: WorkspaceSyncContext, originalObjectMetadataMap: Record, workspaceFeatureFlagsMap: FeatureFlagMap, ): Partial[] { - const standardObjectMetadata = - 'metadata' in standardObjectMetadataOrCustomRelationFactory - ? standardObjectMetadataOrCustomRelationFactory.metadata - : standardObjectMetadataOrCustomRelationFactory; - const objectMetadata = TypedReflect.getMetadata( - 'metadata' in standardObjectMetadataOrCustomRelationFactory - ? 'extendObjectMetadata' - : 'objectMetadata', - standardObjectMetadata, - ); - const reflectRelationMetadataCollection = TypedReflect.getMetadata( - 'reflectRelationMetadataCollection', - standardObjectMetadata, - ); - - if (!objectMetadata) { + const target = + 'metadata' in workspaceEntityOrCustomRelationFactory + ? workspaceEntityOrCustomRelationFactory.metadata + : workspaceEntityOrCustomRelationFactory; + const workspaceEntity = + 'metadata' in workspaceEntityOrCustomRelationFactory + ? metadataArgsStorage.filterExtendedEntities(target) + : metadataArgsStorage.filterEntities(target); + const workspaceRelationMetadataArgsCollection = + metadataArgsStorage.filterRelations(target); + + if (!workspaceEntity) { throw new Error( - `Object metadata decorator not found, can't parse ${standardObjectMetadata.name}`, + `Object metadata decorator not found, can't parse ${target.name}`, ); } if ( - !reflectRelationMetadataCollection || - isGatedAndNotEnabled(objectMetadata?.gate, workspaceFeatureFlagsMap) + !workspaceRelationMetadataArgsCollection || + isGatedAndNotEnabled(workspaceEntity?.gate, workspaceFeatureFlagsMap) ) { return []; } - return reflectRelationMetadataCollection - .filter( - (reflectRelationMetadata) => - !isGatedAndNotEnabled( - reflectRelationMetadata.gate, - workspaceFeatureFlagsMap, - ), - ) - .map((reflectRelationMetadata) => { + return workspaceRelationMetadataArgsCollection + .filter((workspaceRelationMetadataArgs) => { + // We're not storing many-to-one relations in the DB for the moment + if ( + workspaceRelationMetadataArgs.type === + RelationMetadataType.MANY_TO_ONE + ) { + return false; + } + + return !isGatedAndNotEnabled( + workspaceRelationMetadataArgs.gate, + workspaceFeatureFlagsMap, + ); + }) + .map((workspaceRelationMetadataArgs) => { // Compute reflect relation metadata const fromObjectNameSingular = - 'object' in standardObjectMetadataOrCustomRelationFactory - ? standardObjectMetadataOrCustomRelationFactory.object.nameSingular + 'object' in workspaceEntityOrCustomRelationFactory + ? workspaceEntityOrCustomRelationFactory.object.nameSingular : convertClassNameToObjectMetadataName( - reflectRelationMetadata.target.constructor.name, + workspaceRelationMetadataArgs.target.name, ); const toObjectNameSingular = convertClassNameToObjectMetadataName( - reflectRelationMetadata.inverseSideTarget().name, + workspaceRelationMetadataArgs.inverseSideTarget().name, ); - const fromFieldMetadataName = reflectRelationMetadata.fieldKey; + const fromFieldMetadataName = workspaceRelationMetadataArgs.name; const toFieldMetadataName = - (reflectRelationMetadata.inverseSideFieldKey as string | undefined) ?? - fromObjectNameSingular; + (workspaceRelationMetadataArgs.inverseSideFieldKey as + | string + | undefined) ?? fromObjectNameSingular; const fromObjectMetadata = originalObjectMetadataMap[fromObjectNameSingular]; @@ -156,13 +163,13 @@ export class StandardRelationFactory { ); return { - relationType: reflectRelationMetadata.type, + relationType: workspaceRelationMetadataArgs.type, fromObjectMetadataId: fromObjectMetadata?.id, toObjectMetadataId: toObjectMetadata?.id, fromFieldMetadataId: fromFieldMetadata?.id, toFieldMetadataId: toFieldMetadata?.id, workspaceId: context.workspaceId, - onDeleteAction: reflectRelationMetadata.onDelete, + onDeleteAction: workspaceRelationMetadataArgs.onDelete, }; }); } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.interface.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.interface.ts deleted file mode 100644 index badb9b8fb64..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.interface.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface GateDecoratorParams { - featureFlag: string; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface.ts index c8698c37532..c36e2da750b 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface.ts @@ -1,19 +1,31 @@ -import { ReflectDynamicRelationFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-computed-relation-field-metadata.interface'; -import { ReflectFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-field-metadata.interface'; +import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; +import { WorkspaceDynamicRelationMetadataArgsFactory } from 'src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface'; + +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 type PartialFieldMetadata = Omit< - ReflectFieldMetadata[string], - 'joinColumn' + FieldMetadataInterface, + 'id' | 'label' | 'description' | 'objectMetadataId' > & { + standardId: string; + label: string | ((objectMetadata: ObjectMetadataEntity) => string); + description?: string | ((objectMetadata: ObjectMetadataEntity) => string); + icon?: string; + isSystem?: boolean; workspaceId: string; objectMetadataId?: string; }; -export type PartialComputedFieldMetadata = - ReflectDynamicRelationFieldMetadata & { - workspaceId: string; - objectMetadataId?: string; - }; +export type PartialComputedFieldMetadata = { + type: FieldMetadataType.RELATION; + argsFactory: WorkspaceDynamicRelationMetadataArgsFactory; + isNullable?: boolean; + isSystem?: boolean; + isCustom: boolean; + workspaceId: string; + objectMetadataId?: string; +}; export type ComputedPartialFieldMetadata = { [K in keyof PartialFieldMetadata]: ExcludeFunctions; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface.ts index 747cae43eb2..897fc635aa9 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface.ts @@ -3,10 +3,14 @@ import { PartialComputedFieldMetadata, PartialFieldMetadata, } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface'; -import { ReflectObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-object-metadata.interface'; +import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; -export type PartialObjectMetadata = ReflectObjectMetadata & { - id?: string; +export type PartialObjectMetadata = Omit< + ObjectMetadataInterface, + 'id' | 'standardId' | 'fromRelations' | 'toRelations' | 'fields' | 'isActive' +> & { + standardId: string; + icon?: string; workspaceId: string; dataSourceId: string; fields: (PartialFieldMetadata | PartialComputedFieldMetadata)[]; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-relation-metadata.interface.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-relation-metadata.interface.ts deleted file mode 100644 index d4286277e9a..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-relation-metadata.interface.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ReflectRelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-relation-metadata.interface'; - -export type PartialRelationMetadata = ReflectRelationMetadata & { - id: string; - workspaceId: string; - fromObjectMetadataId: string; - toObjectMetadataId: string; - fromFieldMetadataId: string; - toFieldMetadataId: string; -}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-computed-relation-field-metadata.interface.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-computed-relation-field-metadata.interface.ts deleted file mode 100644 index 01b2fd3c01b..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-computed-relation-field-metadata.interface.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { GateDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.interface'; - -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 type DynamicRelationFieldMetadataDecoratorParams = ( - oppositeObjectMetadata: ObjectMetadataEntity, -) => { - standardId: string; - name: string; - label: string; - joinColumn: string; - description?: string; - icon?: string; -}; - -export interface ReflectDynamicRelationFieldMetadata { - type: FieldMetadataType.RELATION; - paramsFactory: DynamicRelationFieldMetadataDecoratorParams; - isNullable: boolean; - isSystem: boolean; - isCustom: boolean; - gate?: GateDecoratorParams; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-custom-object-metadata.interface.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-custom-object-metadata.interface.ts deleted file mode 100644 index cb009ca652c..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-custom-object-metadata.interface.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { GateDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.interface'; - -export type BaseCustomObjectMetadataDecoratorParams = - | { allowObjectNameList?: string[] } - | { denyObjectNameList?: string[] }; - -export type ReflectBaseCustomObjectMetadata = - BaseCustomObjectMetadataDecoratorParams & { - gate?: GateDecoratorParams; - }; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-field-metadata.interface.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-field-metadata.interface.ts deleted file mode 100644 index 474f632b2c3..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-field-metadata.interface.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { FieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-default-value.interface'; -import { GateDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.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 { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; - -export interface FieldMetadataDecoratorParams< - T extends FieldMetadataType | 'default', -> { - standardId: string; - type: T; - label: string | ((objectMetadata: ObjectMetadataEntity) => string); - description?: string | ((objectMetadata: ObjectMetadataEntity) => string); - icon?: string; - defaultValue?: FieldMetadataDefaultValue; - joinColumn?: string; - options?: FieldMetadataOptions; - settings?: FieldMetadataSettings; -} - -export interface ReflectFieldMetadata { - [key: string]: Omit< - FieldMetadataDecoratorParams<'default'>, - 'defaultValue' | 'type' | 'options' | 'settings' - > & { - name: string; - type: FieldMetadataType; - isNullable: boolean; - isSystem: boolean; - isCustom: boolean; - defaultValue: FieldMetadataDefaultValue<'default'> | null; - gate?: GateDecoratorParams; - options?: FieldMetadataOptions<'default'> | null; - settings?: FieldMetadataSettings<'default'> | null; - }; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-object-metadata.interface.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-object-metadata.interface.ts deleted file mode 100644 index 95d371389b6..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-object-metadata.interface.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { GateDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.interface'; - -export interface ObjectMetadataDecoratorParams { - standardId: string; - namePlural: string; - labelSingular: string; - labelPlural: string; - description?: string; - icon?: string; -} - -export interface ReflectObjectMetadata extends ObjectMetadataDecoratorParams { - nameSingular: string; - targetTableName: string; - isSystem: boolean; - isCustom: boolean; - isRemote: boolean; - isAuditLogged: boolean; - gate?: GateDecoratorParams; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-relation-metadata.interface.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-relation-metadata.interface.ts deleted file mode 100644 index 13f8c1a0d74..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-relation-metadata.interface.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ObjectType } from 'typeorm'; - -import { GateDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.interface'; - -import { - RelationOnDeleteAction, - RelationMetadataType, -} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; - -export interface RelationMetadataDecoratorParams { - type: RelationMetadataType; - inverseSideTarget: () => ObjectType; - inverseSideFieldKey?: keyof T; - onDelete: RelationOnDeleteAction; -} - -export interface ReflectRelationMetadata - extends RelationMetadataDecoratorParams { - target: object; - fieldKey: string; - gate?: GateDecoratorParams; - onDelete: RelationOnDeleteAction; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service.ts index 049e8c68938..4fe25b628ce 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service.ts @@ -14,7 +14,7 @@ import { WorkspaceMetadataUpdaterService } from 'src/engine/workspace-manager/wo import { WorkspaceSyncStorage } from 'src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage'; import { WorkspaceMigrationFieldFactory } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-field.factory'; import { StandardFieldFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-field.factory'; -import { CustomObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/custom-objects/custom.object-metadata'; +import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity'; import { computeStandardObject } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util'; @Injectable() @@ -56,7 +56,7 @@ export class WorkspaceSyncFieldMetadataService { // Create standard field metadata collection const standardFieldMetadataCollection = this.standardFieldFactory.create( - CustomObjectMetadata, + CustomWorkspaceEntity, context, workspaceFeatureFlagsMap, ); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-relation-metadata.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-relation-metadata.service.ts index 9f89d19498a..86d46f01a85 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-relation-metadata.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-relation-metadata.service.ts @@ -17,7 +17,7 @@ import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace- import { WorkspaceSyncStorage } from 'src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage'; import { WorkspaceMigrationRelationFactory } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-relation.factory'; import { standardObjectMetadataDefinitions } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects'; -import { CustomObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/custom-objects/custom.object-metadata'; +import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity'; @Injectable() export class WorkspaceSyncRelationMetadataService { @@ -88,7 +88,7 @@ export class WorkspaceSyncRelationMetadataService { this.standardRelationFactory.create( customObjectMetadataCollection.map((objectMetadata) => ({ object: objectMetadata, - metadata: CustomObjectMetadata, + metadata: CustomWorkspaceEntity, })), context, originalObjectMetadataMap, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata.ts deleted file mode 100644 index 423addf8091..00000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { BASE_OBJECT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; - -export abstract class BaseObjectMetadata { - @FieldMetadata({ - standardId: BASE_OBJECT_STANDARD_FIELD_IDS.id, - type: FieldMetadataType.UUID, - label: 'Id', - description: 'Id', - defaultValue: 'uuid', - icon: 'Icon123', - }) - @IsSystem() - id: string; - - @FieldMetadata({ - standardId: BASE_OBJECT_STANDARD_FIELD_IDS.createdAt, - type: FieldMetadataType.DATE_TIME, - label: 'Creation date', - description: 'Creation date', - icon: 'IconCalendar', - defaultValue: 'now', - }) - createdAt: Date; - - @FieldMetadata({ - standardId: BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt, - type: FieldMetadataType.DATE_TIME, - label: 'Update date', - description: 'Update date', - icon: 'IconCalendar', - defaultValue: 'now', - }) - @IsSystem() - updatedAt: Date; -} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage.ts index 4aa5c5a0869..539da1bf60d 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage.ts @@ -1,6 +1,5 @@ import { ComputedPartialObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-object-metadata.interface'; import { ComputedPartialFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-field-metadata.interface'; -import { PartialRelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/partial-relation-metadata.interface'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; @@ -28,7 +27,7 @@ export class WorkspaceSyncStorage { []; private readonly _relationMetadataDeleteCollection: RelationMetadataEntity[] = []; - private readonly _relationMetadataUpdateCollection: Partial[] = + private readonly _relationMetadataUpdateCollection: Partial[] = []; constructor() {} @@ -101,7 +100,7 @@ export class WorkspaceSyncStorage { this._relationMetadataCreateCollection.push(relation); } - addUpdateRelationMetadata(relation: Partial) { + addUpdateRelationMetadata(relation: Partial) { this._relationMetadataUpdateCollection.push(relation); } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/types/object-record.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/types/object-record.ts index f99f0e08023..81d63c22647 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/types/object-record.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/types/object-record.ts @@ -1,9 +1,9 @@ -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; -export type ObjectRecord = { - [K in keyof T as T[K] extends BaseObjectMetadata +export type ObjectRecord = { + [K in keyof T as T[K] extends BaseWorkspaceEntity ? `${Extract}Id` - : K]: T[K] extends BaseObjectMetadata ? string : T[K]; + : K]: T[K] extends BaseWorkspaceEntity ? string : T[K]; } & { - [K in keyof T]: T[K] extends BaseObjectMetadata ? ObjectRecord : T[K]; + [K in keyof T]: T[K] extends BaseWorkspaceEntity ? ObjectRecord : T[K]; }; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util.ts index 69dcbfbb3e4..31b7671cc51 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/compute-standard-object.util.ts @@ -21,11 +21,11 @@ export const computeStandardObject = ( const fields: ComputedPartialFieldMetadata[] = []; for (const partialFieldMetadata of standardObjectMetadata.fields) { - if ('paramsFactory' in partialFieldMetadata) { + if ('argsFactory' in partialFieldMetadata) { // Compute standard fields of custom object for (const customObjectMetadata of customObjectMetadataCollection) { - const { paramsFactory, ...rest } = partialFieldMetadata; - const { joinColumn, ...data } = paramsFactory(customObjectMetadata); + const { argsFactory, ...rest } = partialFieldMetadata; + const { joinColumn, ...data } = argsFactory(customObjectMetadata); const relationStandardId = createRelationDeterministicUuid({ objectId: customObjectMetadata.id, standardId: data.standardId, @@ -35,6 +35,12 @@ export const computeStandardObject = ( standardId: data.standardId, }); + if (!joinColumn) { + throw new Error( + `Missing joinColumn for field ${data.name} in object ${customObjectMetadata.nameSingular}`, + ); + } + // Relation fields.push({ ...data, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util.ts index adff20533dc..fa6912031f4 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util.ts @@ -1,7 +1,7 @@ -import { GateDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.interface'; +import { Gate } from 'src/engine/twenty-orm/interfaces/gate.interface'; export const isGatedAndNotEnabled = ( - gate: GateDecoratorParams | undefined, + gate: Gate | undefined, workspaceFeatureFlagsMap: Record, ): boolean => { const featureFlagValue = diff --git a/packages/twenty-server/src/modules/activity/standard-objects/activity-target.object-metadata.ts b/packages/twenty-server/src/modules/activity/standard-objects/activity-target.object-metadata.ts index 28c1827ccac..a9321dec2a7 100644 --- a/packages/twenty-server/src/modules/activity/standard-objects/activity-target.object-metadata.ts +++ b/packages/twenty-server/src/modules/activity/standard-objects/activity-target.object-metadata.ts @@ -1,22 +1,22 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; -import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { ACTIVITY_TARGET_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { CustomObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/custom-objects/custom.object-metadata'; -import { DynamicRelationFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/dynamic-field-metadata.interface'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; +import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity'; import { ActivityObjectMetadata } from 'src/modules/activity/standard-objects/activity.object-metadata'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { CompanyObjectMetadata } from 'src/modules/company/standard-objects/company.object-metadata'; import { OpportunityObjectMetadata } from 'src/modules/opportunity/standard-objects/opportunity.object-metadata'; import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.activityTarget, namePlural: 'activityTargets', labelSingular: 'Activity Target', @@ -24,60 +24,73 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'An activity target', icon: 'IconCheckbox', }) -@IsSystem() -@IsNotAuditLogged() -export class ActivityTargetObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsSystem() +@WorkspaceIsNotAuditLogged() +export class ActivityTargetObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceRelation({ standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.activity, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Activity', description: 'ActivityTarget activity', icon: 'IconNotes', joinColumn: 'activityId', + inverseSideTarget: () => ActivityObjectMetadata, + inverseSideFieldKey: 'activityTargets', }) - @IsNullable() + @WorkspaceIsNullable() activity: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.person, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Person', description: 'ActivityTarget person', icon: 'IconUser', joinColumn: 'personId', + inverseSideTarget: () => PersonObjectMetadata, + inverseSideFieldKey: 'activityTargets', }) - @IsNullable() + @WorkspaceIsNullable() person: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.company, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'ActivityTarget company', icon: 'IconBuildingSkyscraper', joinColumn: 'companyId', + inverseSideTarget: () => CompanyObjectMetadata, + inverseSideFieldKey: 'activityTargets', }) - @IsNullable() + @WorkspaceIsNullable() company: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.opportunity, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Opportunity', description: 'ActivityTarget opportunity', icon: 'IconTargetArrow', joinColumn: 'opportunityId', + inverseSideTarget: () => OpportunityObjectMetadata, + inverseSideFieldKey: 'activityTargets', }) - @IsNullable() + @WorkspaceIsNullable() opportunity: Relation; - @DynamicRelationFieldMetadata((oppositeObjectMetadata) => ({ - standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.custom, - name: oppositeObjectMetadata.nameSingular, - label: oppositeObjectMetadata.labelSingular, - description: `ActivityTarget ${oppositeObjectMetadata.labelSingular}`, - joinColumn: `${oppositeObjectMetadata.nameSingular}Id`, - icon: 'IconBuildingSkyscraper', - })) - custom: Relation; + @WorkspaceDynamicRelation({ + type: RelationMetadataType.MANY_TO_ONE, + argsFactory: (oppositeObjectMetadata) => ({ + standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.custom, + name: oppositeObjectMetadata.nameSingular, + label: oppositeObjectMetadata.labelSingular, + description: `ActivityTarget ${oppositeObjectMetadata.labelSingular}`, + joinColumn: `${oppositeObjectMetadata.nameSingular}Id`, + icon: 'IconBuildingSkyscraper', + }), + inverseSideTarget: () => CustomWorkspaceEntity, + inverseSideFieldKey: 'activityTargets', + }) + custom: Relation; } diff --git a/packages/twenty-server/src/modules/activity/standard-objects/activity.object-metadata.ts b/packages/twenty-server/src/modules/activity/standard-objects/activity.object-metadata.ts index 7dbad1edef7..4b44af02c68 100644 --- a/packages/twenty-server/src/modules/activity/standard-objects/activity.object-metadata.ts +++ b/packages/twenty-server/src/modules/activity/standard-objects/activity.object-metadata.ts @@ -7,19 +7,19 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { ACTIVITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; import { ActivityTargetObjectMetadata } from 'src/modules/activity/standard-objects/activity-target.object-metadata'; import { AttachmentObjectMetadata } from 'src/modules/attachment/standard-objects/attachment.object-metadata'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { CommentObjectMetadata } from 'src/modules/activity/standard-objects/comment.object-metadata'; import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.activity, namePlural: 'activities', labelSingular: 'Activity', @@ -27,10 +27,10 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'An activity', icon: 'IconCheckbox', }) -@IsNotAuditLogged() -@IsSystem() -export class ActivityObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +@WorkspaceIsSystem() +export class ActivityObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: ACTIVITY_STANDARD_FIELD_IDS.title, type: FieldMetadataType.TEXT, label: 'Title', @@ -39,7 +39,7 @@ export class ActivityObjectMetadata extends BaseObjectMetadata { }) title: string; - @FieldMetadata({ + @WorkspaceField({ standardId: ACTIVITY_STANDARD_FIELD_IDS.body, type: FieldMetadataType.TEXT, label: 'Body', @@ -48,7 +48,7 @@ export class ActivityObjectMetadata extends BaseObjectMetadata { }) body: string; - @FieldMetadata({ + @WorkspaceField({ standardId: ACTIVITY_STANDARD_FIELD_IDS.type, type: FieldMetadataType.TEXT, label: 'Type', @@ -58,100 +58,97 @@ export class ActivityObjectMetadata extends BaseObjectMetadata { }) type: string; - @FieldMetadata({ + @WorkspaceField({ standardId: ACTIVITY_STANDARD_FIELD_IDS.reminderAt, type: FieldMetadataType.DATE_TIME, label: 'Reminder Date', description: 'Activity reminder date', icon: 'IconCalendarEvent', }) - @IsNullable() + @WorkspaceIsNullable() reminderAt: Date; - @FieldMetadata({ + @WorkspaceField({ standardId: ACTIVITY_STANDARD_FIELD_IDS.dueAt, type: FieldMetadataType.DATE_TIME, label: 'Due Date', description: 'Activity due date', icon: 'IconCalendarEvent', }) - @IsNullable() + @WorkspaceIsNullable() dueAt: Date; - @FieldMetadata({ + @WorkspaceField({ standardId: ACTIVITY_STANDARD_FIELD_IDS.completedAt, type: FieldMetadataType.DATE_TIME, label: 'Completion Date', description: 'Activity completion date', icon: 'IconCheck', }) - @IsNullable() + @WorkspaceIsNullable() completedAt: Date; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ACTIVITY_STANDARD_FIELD_IDS.activityTargets, - type: FieldMetadataType.RELATION, label: 'Targets', description: 'Activity targets', icon: 'IconCheckbox', - }) - @RelationMetadata({ type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => ActivityTargetObjectMetadata, onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsNullable() + @WorkspaceIsNullable() activityTargets: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ACTIVITY_STANDARD_FIELD_IDS.attachments, - type: FieldMetadataType.RELATION, label: 'Attachments', description: 'Activity attachments', icon: 'IconFileImport', - }) - @RelationMetadata({ type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => AttachmentObjectMetadata, onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsNullable() + @WorkspaceIsNullable() attachments: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ACTIVITY_STANDARD_FIELD_IDS.comments, - type: FieldMetadataType.RELATION, label: 'Comments', description: 'Activity comments', icon: 'IconComment', - }) - @RelationMetadata({ type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => CommentObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() + @WorkspaceIsNullable() comments: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ACTIVITY_STANDARD_FIELD_IDS.author, - type: FieldMetadataType.RELATION, label: 'Author', description: 'Activity author', icon: 'IconUserCircle', + type: RelationMetadataType.MANY_TO_ONE, + inverseSideTarget: () => WorkspaceMemberObjectMetadata, + inverseSideFieldKey: 'authoredActivities', + onDelete: RelationOnDeleteAction.SET_NULL, joinColumn: 'authorId', }) - @IsNullable() + @WorkspaceIsNullable() author: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ACTIVITY_STANDARD_FIELD_IDS.assignee, - type: FieldMetadataType.RELATION, label: 'Assignee', description: 'Activity assignee', icon: 'IconUserCircle', + type: RelationMetadataType.MANY_TO_ONE, + inverseSideTarget: () => WorkspaceMemberObjectMetadata, + inverseSideFieldKey: 'assignedActivities', + onDelete: RelationOnDeleteAction.SET_NULL, joinColumn: 'assigneeId', }) - @IsNullable() + @WorkspaceIsNullable() assignee: Relation; } diff --git a/packages/twenty-server/src/modules/activity/standard-objects/comment.object-metadata.ts b/packages/twenty-server/src/modules/activity/standard-objects/comment.object-metadata.ts index 1d389122ec7..b9b15a3c4e9 100644 --- a/packages/twenty-server/src/modules/activity/standard-objects/comment.object-metadata.ts +++ b/packages/twenty-server/src/modules/activity/standard-objects/comment.object-metadata.ts @@ -3,15 +3,17 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { COMMENT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; import { ActivityObjectMetadata } from 'src/modules/activity/standard-objects/activity.object-metadata'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.comment, namePlural: 'comments', labelSingular: 'Comment', @@ -19,10 +21,10 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'A comment', icon: 'IconMessageCircle', }) -@IsSystem() -@IsNotAuditLogged() -export class CommentObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsSystem() +@WorkspaceIsNotAuditLogged() +export class CommentObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: COMMENT_STANDARD_FIELD_IDS.body, type: FieldMetadataType.TEXT, label: 'Body', @@ -31,23 +33,27 @@ export class CommentObjectMetadata extends BaseObjectMetadata { }) body: string; - @FieldMetadata({ + @WorkspaceRelation({ standardId: COMMENT_STANDARD_FIELD_IDS.author, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Author', description: 'Comment author', icon: 'IconCircleUser', joinColumn: 'authorId', + inverseSideTarget: () => WorkspaceMemberObjectMetadata, + inverseSideFieldKey: 'authoredComments', }) author: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: COMMENT_STANDARD_FIELD_IDS.activity, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Activity', description: 'Comment activity', icon: 'IconNotes', joinColumn: 'activityId', + inverseSideTarget: () => ActivityObjectMetadata, + inverseSideFieldKey: 'comments', }) activity: Relation; } diff --git a/packages/twenty-server/src/modules/api-key/standard-objects/api-key.object-metadata.ts b/packages/twenty-server/src/modules/api-key/standard-objects/api-key.object-metadata.ts index 51e77a0e3e6..fcf194da743 100644 --- a/packages/twenty-server/src/modules/api-key/standard-objects/api-key.object-metadata.ts +++ b/packages/twenty-server/src/modules/api-key/standard-objects/api-key.object-metadata.ts @@ -1,14 +1,14 @@ import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; import { API_KEY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.apiKey, namePlural: 'apiKeys', labelSingular: 'Api Key', @@ -16,10 +16,10 @@ import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync- description: 'An api key', icon: 'IconRobot', }) -@IsSystem() -@IsNotAuditLogged() -export class ApiKeyObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsSystem() +@WorkspaceIsNotAuditLogged() +export class ApiKeyObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: API_KEY_STANDARD_FIELD_IDS.name, type: FieldMetadataType.TEXT, label: 'Name', @@ -28,7 +28,7 @@ export class ApiKeyObjectMetadata extends BaseObjectMetadata { }) name: string; - @FieldMetadata({ + @WorkspaceField({ standardId: API_KEY_STANDARD_FIELD_IDS.expiresAt, type: FieldMetadataType.DATE_TIME, label: 'Expiration date', @@ -37,13 +37,13 @@ export class ApiKeyObjectMetadata extends BaseObjectMetadata { }) expiresAt: Date; - @FieldMetadata({ + @WorkspaceField({ standardId: API_KEY_STANDARD_FIELD_IDS.revokedAt, type: FieldMetadataType.DATE_TIME, label: 'Revocation date', description: 'ApiKey revocation date', icon: 'IconCalendar', }) - @IsNullable() + @WorkspaceIsNullable() revokedAt?: Date; } diff --git a/packages/twenty-server/src/modules/attachment/standard-objects/attachment.object-metadata.ts b/packages/twenty-server/src/modules/attachment/standard-objects/attachment.object-metadata.ts index f9b5fb9ffe0..68d06c8627b 100644 --- a/packages/twenty-server/src/modules/attachment/standard-objects/attachment.object-metadata.ts +++ b/packages/twenty-server/src/modules/attachment/standard-objects/attachment.object-metadata.ts @@ -3,21 +3,23 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { ATTACHMENT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { CustomObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/custom-objects/custom.object-metadata'; -import { DynamicRelationFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/dynamic-field-metadata.interface'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; +import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity'; import { ActivityObjectMetadata } from 'src/modules/activity/standard-objects/activity.object-metadata'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { CompanyObjectMetadata } from 'src/modules/company/standard-objects/company.object-metadata'; import { OpportunityObjectMetadata } from 'src/modules/opportunity/standard-objects/opportunity.object-metadata'; import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata'; import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.attachment, namePlural: 'attachments', labelSingular: 'Attachment', @@ -25,10 +27,10 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'An attachment', icon: 'IconFileImport', }) -@IsSystem() -@IsNotAuditLogged() -export class AttachmentObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsSystem() +@WorkspaceIsNotAuditLogged() +export class AttachmentObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: ATTACHMENT_STANDARD_FIELD_IDS.name, type: FieldMetadataType.TEXT, label: 'Name', @@ -37,7 +39,7 @@ export class AttachmentObjectMetadata extends BaseObjectMetadata { }) name: string; - @FieldMetadata({ + @WorkspaceField({ standardId: ATTACHMENT_STANDARD_FIELD_IDS.fullPath, type: FieldMetadataType.TEXT, label: 'Full path', @@ -46,7 +48,7 @@ export class AttachmentObjectMetadata extends BaseObjectMetadata { }) fullPath: string; - @FieldMetadata({ + @WorkspaceField({ standardId: ATTACHMENT_STANDARD_FIELD_IDS.type, type: FieldMetadataType.TEXT, label: 'Type', @@ -55,67 +57,82 @@ export class AttachmentObjectMetadata extends BaseObjectMetadata { }) type: string; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ATTACHMENT_STANDARD_FIELD_IDS.author, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Author', description: 'Attachment author', icon: 'IconCircleUser', joinColumn: 'authorId', + inverseSideTarget: () => WorkspaceMemberObjectMetadata, + inverseSideFieldKey: 'authoredAttachments', }) author: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ATTACHMENT_STANDARD_FIELD_IDS.activity, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Activity', description: 'Attachment activity', icon: 'IconNotes', joinColumn: 'activityId', + inverseSideTarget: () => ActivityObjectMetadata, + inverseSideFieldKey: 'attachments', }) - @IsNullable() + @WorkspaceIsNullable() activity: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ATTACHMENT_STANDARD_FIELD_IDS.person, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Person', description: 'Attachment person', icon: 'IconUser', joinColumn: 'personId', + inverseSideTarget: () => PersonObjectMetadata, + inverseSideFieldKey: 'attachments', }) - @IsNullable() + @WorkspaceIsNullable() person: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ATTACHMENT_STANDARD_FIELD_IDS.company, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'Attachment company', icon: 'IconBuildingSkyscraper', joinColumn: 'companyId', + inverseSideTarget: () => CompanyObjectMetadata, + inverseSideFieldKey: 'attachments', }) - @IsNullable() + @WorkspaceIsNullable() company: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: ATTACHMENT_STANDARD_FIELD_IDS.opportunity, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Opportunity', description: 'Attachment opportunity', icon: 'IconBuildingSkyscraper', joinColumn: 'opportunityId', + inverseSideTarget: () => OpportunityObjectMetadata, + inverseSideFieldKey: 'attachments', }) - @IsNullable() + @WorkspaceIsNullable() opportunity: Relation; - @DynamicRelationFieldMetadata((oppositeObjectMetadata) => ({ - standardId: ATTACHMENT_STANDARD_FIELD_IDS.custom, - name: oppositeObjectMetadata.nameSingular, - label: oppositeObjectMetadata.labelSingular, - description: `Attachment ${oppositeObjectMetadata.labelSingular}`, - joinColumn: `${oppositeObjectMetadata.nameSingular}Id`, - icon: 'IconBuildingSkyscraper', - })) - custom: Relation; + @WorkspaceDynamicRelation({ + type: RelationMetadataType.MANY_TO_ONE, + argsFactory: (oppositeObjectMetadata) => ({ + standardId: ATTACHMENT_STANDARD_FIELD_IDS.custom, + name: oppositeObjectMetadata.nameSingular, + label: oppositeObjectMetadata.labelSingular, + description: `Attachment ${oppositeObjectMetadata.labelSingular}`, + joinColumn: `${oppositeObjectMetadata.nameSingular}Id`, + icon: 'IconBuildingSkyscraper', + }), + inverseSideTarget: () => CustomWorkspaceEntity, + inverseSideFieldKey: 'attachments', + }) + custom: Relation; } diff --git a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata.ts b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata.ts index 93637b1d2bf..67c7181ea69 100644 --- a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata.ts +++ b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata.ts @@ -3,14 +3,17 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { CalendarEventObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.calendarChannelEventAssociation, namePlural: 'calendarChannelEventAssociations', labelSingular: 'Calendar Channel Event Association', @@ -18,38 +21,42 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'Calendar Channel Event Associations', icon: 'IconCalendar', }) -@IsSystem() -@IsNotAuditLogged() -export class CalendarChannelEventAssociationObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsSystem() +@WorkspaceIsNotAuditLogged() +export class CalendarChannelEventAssociationObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ + standardId: + CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS.eventExternalId, + type: FieldMetadataType.TEXT, + label: 'Event external ID', + description: 'Event external ID', + icon: 'IconCalendar', + }) + eventExternalId: string; + + @WorkspaceRelation({ standardId: CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS.calendarChannel, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Channel ID', description: 'Channel ID', icon: 'IconCalendar', joinColumn: 'calendarChannelId', + inverseSideTarget: () => CalendarEventObjectMetadata, + inverseSideFieldKey: 'calendarChannelEventAssociations', }) calendarChannel: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS.calendarEvent, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Event ID', description: 'Event ID', icon: 'IconCalendar', joinColumn: 'calendarEventId', + inverseSideTarget: () => CalendarEventObjectMetadata, + inverseSideFieldKey: 'calendarChannelEventAssociations', }) calendarEvent: Relation; - - @FieldMetadata({ - standardId: - CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS.eventExternalId, - type: FieldMetadataType.TEXT, - label: 'Event external ID', - description: 'Event external ID', - icon: 'IconCalendar', - }) - eventExternalId: string; } diff --git a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel.object-metadata.ts b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel.object-metadata.ts index 637e10c7043..63dcb0f3f14 100644 --- a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel.object-metadata.ts +++ b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel.object-metadata.ts @@ -7,21 +7,21 @@ import { import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { CALENDAR_CHANNEL_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata'; import { CalendarChannelEventAssociationObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; export enum CalendarChannelVisibility { METADATA = 'METADATA', SHARE_EVERYTHING = 'SHARE_EVERYTHING', } -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.calendarChannel, namePlural: 'calendarChannels', labelSingular: 'Calendar Channel', @@ -29,20 +29,10 @@ export enum CalendarChannelVisibility { description: 'Calendar Channels', icon: 'IconCalendar', }) -@IsSystem() -@IsNotAuditLogged() -export class CalendarChannelObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ - standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.connectedAccount, - type: FieldMetadataType.RELATION, - label: 'Connected Account', - description: 'Connected Account', - icon: 'IconUserCircle', - joinColumn: 'connectedAccountId', - }) - connectedAccount: Relation; - - @FieldMetadata({ +@WorkspaceIsSystem() +@WorkspaceIsNotAuditLogged() +export class CalendarChannelObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.handle, type: FieldMetadataType.TEXT, label: 'Handle', @@ -51,7 +41,7 @@ export class CalendarChannelObjectMetadata extends BaseObjectMetadata { }) handle: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.visibility, type: FieldMetadataType.SELECT, label: 'Visibility', @@ -75,7 +65,7 @@ export class CalendarChannelObjectMetadata extends BaseObjectMetadata { }) visibility: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.isContactAutoCreationEnabled, type: FieldMetadataType.BOOLEAN, @@ -86,7 +76,7 @@ export class CalendarChannelObjectMetadata extends BaseObjectMetadata { }) isContactAutoCreationEnabled: boolean; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.isSyncEnabled, type: FieldMetadataType.BOOLEAN, label: 'Is Sync Enabled', @@ -96,7 +86,7 @@ export class CalendarChannelObjectMetadata extends BaseObjectMetadata { }) isSyncEnabled: boolean; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.syncCursor, type: FieldMetadataType.TEXT, label: 'Sync Cursor', @@ -106,16 +96,25 @@ export class CalendarChannelObjectMetadata extends BaseObjectMetadata { }) syncCursor: string; - @FieldMetadata({ + @WorkspaceRelation({ + standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.connectedAccount, + type: RelationMetadataType.MANY_TO_ONE, + label: 'Connected Account', + description: 'Connected Account', + icon: 'IconUserCircle', + joinColumn: 'connectedAccountId', + inverseSideTarget: () => ConnectedAccountObjectMetadata, + inverseSideFieldKey: 'calendarChannels', + }) + connectedAccount: Relation; + + @WorkspaceRelation({ standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.calendarChannelEventAssociations, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Calendar Channel Event Associations', description: 'Calendar Channel Event Associations', icon: 'IconCalendar', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => CalendarChannelEventAssociationObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) diff --git a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-event-participant.object-metadata.ts b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-event-participant.object-metadata.ts index f4cbb06bdee..a8750f3803e 100644 --- a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-event-participant.object-metadata.ts +++ b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-event-participant.object-metadata.ts @@ -3,15 +3,17 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { CalendarEventObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event.object-metadata'; import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata'; import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; export enum CalendarEventParticipantResponseStatus { NEEDS_ACTION = 'NEEDS_ACTION', @@ -20,7 +22,7 @@ export enum CalendarEventParticipantResponseStatus { ACCEPTED = 'ACCEPTED', } -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.calendarEventParticipant, namePlural: 'calendarEventParticipants', labelSingular: 'Calendar event participant', @@ -28,20 +30,10 @@ export enum CalendarEventParticipantResponseStatus { description: 'Calendar event participants', icon: 'IconCalendar', }) -@IsSystem() -@IsNotAuditLogged() -export class CalendarEventParticipantObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ - standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.calendarEvent, - type: FieldMetadataType.RELATION, - label: 'Event ID', - description: 'Event ID', - icon: 'IconCalendar', - joinColumn: 'calendarEventId', - }) - calendarEvent: Relation; - - @FieldMetadata({ +@WorkspaceIsSystem() +@WorkspaceIsNotAuditLogged() +export class CalendarEventParticipantObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.handle, type: FieldMetadataType.TEXT, label: 'Handle', @@ -50,7 +42,7 @@ export class CalendarEventParticipantObjectMetadata extends BaseObjectMetadata { }) handle: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.displayName, type: FieldMetadataType.TEXT, label: 'Display Name', @@ -59,7 +51,7 @@ export class CalendarEventParticipantObjectMetadata extends BaseObjectMetadata { }) displayName: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.isOrganizer, type: FieldMetadataType.BOOLEAN, label: 'Is Organizer', @@ -69,7 +61,7 @@ export class CalendarEventParticipantObjectMetadata extends BaseObjectMetadata { }) isOrganizer: boolean; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.responseStatus, type: FieldMetadataType.SELECT, label: 'Response Status', @@ -105,25 +97,41 @@ export class CalendarEventParticipantObjectMetadata extends BaseObjectMetadata { }) responseStatus: string; - @FieldMetadata({ + @WorkspaceRelation({ + standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.calendarEvent, + type: RelationMetadataType.MANY_TO_ONE, + label: 'Event ID', + description: 'Event ID', + icon: 'IconCalendar', + joinColumn: 'calendarEventId', + inverseSideTarget: () => CalendarEventObjectMetadata, + inverseSideFieldKey: 'calendarEventParticipants', + }) + calendarEvent: Relation; + + @WorkspaceRelation({ standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.person, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Person', description: 'Person', icon: 'IconUser', joinColumn: 'personId', + inverseSideTarget: () => PersonObjectMetadata, + inverseSideFieldKey: 'calendarEventParticipants', }) - @IsNullable() + @WorkspaceIsNullable() person: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.workspaceMember, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Workspace Member', description: 'Workspace Member', icon: 'IconUser', joinColumn: 'workspaceMemberId', + inverseSideTarget: () => WorkspaceMemberObjectMetadata, + inverseSideFieldKey: 'calendarEventParticipants', }) - @IsNullable() + @WorkspaceIsNullable() workspaceMember: Relation; } diff --git a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-event.object-metadata.ts b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-event.object-metadata.ts index a5d71e1dc10..a79b7852c65 100644 --- a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-event.object-metadata.ts +++ b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-event.object-metadata.ts @@ -1,24 +1,24 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { RelationMetadataType, RelationOnDeleteAction, } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { CalendarChannelEventAssociationObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata'; import { CalendarEventParticipantObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event-participant.object-metadata'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { CALENDAR_EVENT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { LinkMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/link.composite-type'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; - -@ObjectMetadata({ +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; + +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.calendarEvent, namePlural: 'calendarEvents', labelSingular: 'Calendar event', @@ -26,10 +26,10 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'Calendar events', icon: 'IconCalendar', }) -@IsSystem() -@IsNotAuditLogged() -export class CalendarEventObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsSystem() +@WorkspaceIsNotAuditLogged() +export class CalendarEventObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.title, type: FieldMetadataType.TEXT, label: 'Title', @@ -38,7 +38,7 @@ export class CalendarEventObjectMetadata extends BaseObjectMetadata { }) title: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.isCanceled, type: FieldMetadataType.BOOLEAN, label: 'Is canceled', @@ -47,7 +47,7 @@ export class CalendarEventObjectMetadata extends BaseObjectMetadata { }) isCanceled: boolean; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.isFullDay, type: FieldMetadataType.BOOLEAN, label: 'Is Full Day', @@ -56,47 +56,47 @@ export class CalendarEventObjectMetadata extends BaseObjectMetadata { }) isFullDay: boolean; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.startsAt, type: FieldMetadataType.DATE_TIME, label: 'Start Date', description: 'Start Date', icon: 'IconCalendarClock', }) - @IsNullable() + @WorkspaceIsNullable() startsAt: string | null; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.endsAt, type: FieldMetadataType.DATE_TIME, label: 'End Date', description: 'End Date', icon: 'IconCalendarClock', }) - @IsNullable() + @WorkspaceIsNullable() endsAt: string | null; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.externalCreatedAt, type: FieldMetadataType.DATE_TIME, label: 'Creation DateTime', description: 'Creation DateTime', icon: 'IconCalendarPlus', }) - @IsNullable() + @WorkspaceIsNullable() externalCreatedAt: string | null; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.externalUpdatedAt, type: FieldMetadataType.DATE_TIME, label: 'Update DateTime', description: 'Update DateTime', icon: 'IconCalendarCog', }) - @IsNullable() + @WorkspaceIsNullable() externalUpdatedAt: string | null; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.description, type: FieldMetadataType.TEXT, label: 'Description', @@ -105,7 +105,7 @@ export class CalendarEventObjectMetadata extends BaseObjectMetadata { }) description: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.location, type: FieldMetadataType.TEXT, label: 'Location', @@ -114,7 +114,7 @@ export class CalendarEventObjectMetadata extends BaseObjectMetadata { }) location: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.iCalUID, type: FieldMetadataType.TEXT, label: 'iCal UID', @@ -123,7 +123,7 @@ export class CalendarEventObjectMetadata extends BaseObjectMetadata { }) iCalUID: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.conferenceSolution, type: FieldMetadataType.TEXT, label: 'Conference Solution', @@ -132,17 +132,17 @@ export class CalendarEventObjectMetadata extends BaseObjectMetadata { }) conferenceSolution: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.conferenceLink, type: FieldMetadataType.LINK, label: 'Meet Link', description: 'Meet Link', icon: 'IconLink', }) - @IsNullable() + @WorkspaceIsNullable() conferenceLink: LinkMetadata; - @FieldMetadata({ + @WorkspaceField({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.recurringEventExternalId, type: FieldMetadataType.TEXT, label: 'Recurring Event ID', @@ -151,33 +151,26 @@ export class CalendarEventObjectMetadata extends BaseObjectMetadata { }) recurringEventExternalId: string; - @FieldMetadata({ + @WorkspaceRelation({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.calendarChannelEventAssociations, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Calendar Channel Event Associations', description: 'Calendar Channel Event Associations', icon: 'IconCalendar', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => CalendarChannelEventAssociationObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, - inverseSideFieldKey: 'calendarEvent', }) calendarChannelEventAssociations: Relation< CalendarChannelEventAssociationObjectMetadata[] >; - @FieldMetadata({ + @WorkspaceRelation({ standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.calendarEventParticipants, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Event Participants', description: 'Event Participants', icon: 'IconUserCircle', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => CalendarEventParticipantObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) diff --git a/packages/twenty-server/src/modules/company/standard-objects/company.object-metadata.ts b/packages/twenty-server/src/modules/company/standard-objects/company.object-metadata.ts index c0f9e2f17a0..6108e543d89 100644 --- a/packages/twenty-server/src/modules/company/standard-objects/company.object-metadata.ts +++ b/packages/twenty-server/src/modules/company/standard-objects/company.object-metadata.ts @@ -9,21 +9,21 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { COMPANY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; import { ActivityTargetObjectMetadata } from 'src/modules/activity/standard-objects/activity-target.object-metadata'; import { AttachmentObjectMetadata } from 'src/modules/attachment/standard-objects/attachment.object-metadata'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { FavoriteObjectMetadata } from 'src/modules/favorite/standard-objects/favorite.object-metadata'; import { OpportunityObjectMetadata } from 'src/modules/opportunity/standard-objects/opportunity.object-metadata'; import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata'; import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; import { TimelineActivityObjectMetadata } from 'src/modules/timeline/standard-objects/timeline-activity.object-metadata'; - -@ObjectMetadata({ +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; + +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.company, namePlural: 'companies', labelSingular: 'Company', @@ -31,8 +31,8 @@ import { TimelineActivityObjectMetadata } from 'src/modules/timeline/standard-ob description: 'A company', icon: 'IconBuildingSkyscraper', }) -export class CompanyObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +export class CompanyObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: COMPANY_STANDARD_FIELD_IDS.name, type: FieldMetadataType.TEXT, label: 'Name', @@ -41,7 +41,7 @@ export class CompanyObjectMetadata extends BaseObjectMetadata { }) name: string; - @FieldMetadata({ + @WorkspaceField({ standardId: COMPANY_STANDARD_FIELD_IDS.domainName, type: FieldMetadataType.TEXT, label: 'Domain Name', @@ -51,7 +51,7 @@ export class CompanyObjectMetadata extends BaseObjectMetadata { }) domainName?: string; - @FieldMetadata({ + @WorkspaceField({ standardId: COMPANY_STANDARD_FIELD_IDS.address, type: FieldMetadataType.TEXT, label: 'Address', @@ -60,37 +60,37 @@ export class CompanyObjectMetadata extends BaseObjectMetadata { }) address: string; - @FieldMetadata({ + @WorkspaceField({ standardId: COMPANY_STANDARD_FIELD_IDS.employees, type: FieldMetadataType.NUMBER, label: 'Employees', description: 'Number of employees in the company', icon: 'IconUsers', }) - @IsNullable() + @WorkspaceIsNullable() employees: number; - @FieldMetadata({ + @WorkspaceField({ standardId: COMPANY_STANDARD_FIELD_IDS.linkedinLink, type: FieldMetadataType.LINK, label: 'Linkedin', description: 'The company Linkedin account', icon: 'IconBrandLinkedin', }) - @IsNullable() + @WorkspaceIsNullable() linkedinLink: LinkMetadata; - @FieldMetadata({ + @WorkspaceField({ standardId: COMPANY_STANDARD_FIELD_IDS.xLink, type: FieldMetadataType.LINK, label: 'X', description: 'The company Twitter/X account', icon: 'IconBrandX', }) - @IsNullable() + @WorkspaceIsNullable() xLink: LinkMetadata; - @FieldMetadata({ + @WorkspaceField({ standardId: COMPANY_STANDARD_FIELD_IDS.annualRecurringRevenue, type: FieldMetadataType.CURRENCY, label: 'ARR', @@ -98,10 +98,10 @@ export class CompanyObjectMetadata extends BaseObjectMetadata { 'Annual Recurring Revenue: The actual or estimated annual revenue of the company', icon: 'IconMoneybag', }) - @IsNullable() + @WorkspaceIsNullable() annualRecurringRevenue: CurrencyMetadata; - @FieldMetadata({ + @WorkspaceField({ standardId: COMPANY_STANDARD_FIELD_IDS.idealCustomerProfile, type: FieldMetadataType.BOOLEAN, label: 'ICP', @@ -112,119 +112,104 @@ export class CompanyObjectMetadata extends BaseObjectMetadata { }) idealCustomerProfile: boolean; - @FieldMetadata({ + @WorkspaceField({ standardId: COMPANY_STANDARD_FIELD_IDS.position, type: FieldMetadataType.POSITION, label: 'Position', description: 'Company record position', icon: 'IconHierarchy2', }) - @IsSystem() - @IsNullable() + @WorkspaceIsSystem() + @WorkspaceIsNullable() position: number; // Relations - @FieldMetadata({ + @WorkspaceRelation({ standardId: COMPANY_STANDARD_FIELD_IDS.people, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'People', description: 'People linked to the company.', icon: 'IconUsers', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => PersonObjectMetadata, onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsNullable() + @WorkspaceIsNullable() people: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: COMPANY_STANDARD_FIELD_IDS.accountOwner, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Account Owner', description: 'Your team member responsible for managing the company account', icon: 'IconUserCircle', joinColumn: 'accountOwnerId', + inverseSideTarget: () => WorkspaceMemberObjectMetadata, + inverseSideFieldKey: 'accountOwnerForCompanies', + onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsNullable() - accountOwner: WorkspaceMemberObjectMetadata; + @WorkspaceIsNullable() + accountOwner: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: COMPANY_STANDARD_FIELD_IDS.activityTargets, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Activities', description: 'Activities tied to the company', icon: 'IconCheckbox', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => ActivityTargetObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() + @WorkspaceIsNullable() activityTargets: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: COMPANY_STANDARD_FIELD_IDS.opportunities, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Opportunities', description: 'Opportunities linked to the company.', icon: 'IconTargetArrow', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => OpportunityObjectMetadata, onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsNullable() + @WorkspaceIsNullable() opportunities: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: COMPANY_STANDARD_FIELD_IDS.favorites, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Favorites', description: 'Favorites linked to the company', icon: 'IconHeart', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => FavoriteObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() - @IsSystem() + @WorkspaceIsNullable() + @WorkspaceIsSystem() favorites: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: COMPANY_STANDARD_FIELD_IDS.attachments, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Attachments', - description: 'Attachments linked to the company.', + description: 'Attachments linked to the company', icon: 'IconFileImport', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => AttachmentObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() + @WorkspaceIsNullable() attachments: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: COMPANY_STANDARD_FIELD_IDS.timelineActivities, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Timeline Activities', description: 'Timeline Activities linked to the company', icon: 'IconIconTimelineEvent', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => TimelineActivityObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() - @IsSystem() + @WorkspaceIsNullable() + @WorkspaceIsSystem() timelineActivities: Relation; } diff --git a/packages/twenty-server/src/modules/connected-account/standard-objects/blocklist.object-metadata.ts b/packages/twenty-server/src/modules/connected-account/standard-objects/blocklist.object-metadata.ts index eceb97b7b67..e532b278f2f 100644 --- a/packages/twenty-server/src/modules/connected-account/standard-objects/blocklist.object-metadata.ts +++ b/packages/twenty-server/src/modules/connected-account/standard-objects/blocklist.object-metadata.ts @@ -3,14 +3,16 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { BLOCKLIST_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.blocklist, namePlural: 'blocklists', labelSingular: 'Blocklist', @@ -18,10 +20,10 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'Blocklist', icon: 'IconForbid2', }) -@IsSystem() -@IsNotAuditLogged() -export class BlocklistObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsSystem() +@WorkspaceIsNotAuditLogged() +export class BlocklistObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: BLOCKLIST_STANDARD_FIELD_IDS.handle, type: FieldMetadataType.TEXT, label: 'Handle', @@ -30,13 +32,15 @@ export class BlocklistObjectMetadata extends BaseObjectMetadata { }) handle: string; - @FieldMetadata({ + @WorkspaceRelation({ standardId: BLOCKLIST_STANDARD_FIELD_IDS.workspaceMember, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'WorkspaceMember', description: 'WorkspaceMember', icon: 'IconCircleUser', joinColumn: 'workspaceMemberId', + inverseSideTarget: () => WorkspaceMemberObjectMetadata, + inverseSideFieldKey: 'blocklist', }) workspaceMember: Relation; } diff --git a/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.object-metadata.ts b/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.object-metadata.ts index 5f7b8d8e9cf..e488b926181 100644 --- a/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.object-metadata.ts +++ b/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.object-metadata.ts @@ -7,22 +7,22 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { CONNECTED_ACCOUNT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata'; import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata'; import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; export enum ConnectedAccountProvider { GOOGLE = 'google', } -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.connectedAccount, namePlural: 'connectedAccounts', labelSingular: 'Connected Account', @@ -30,10 +30,10 @@ export enum ConnectedAccountProvider { description: 'A connected account', icon: 'IconAt', }) -@IsSystem() -@IsNotAuditLogged() -export class ConnectedAccountObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsSystem() +@WorkspaceIsNotAuditLogged() +export class ConnectedAccountObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.handle, type: FieldMetadataType.TEXT, label: 'handle', @@ -42,7 +42,7 @@ export class ConnectedAccountObjectMetadata extends BaseObjectMetadata { }) handle: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.provider, type: FieldMetadataType.TEXT, label: 'provider', @@ -51,7 +51,7 @@ export class ConnectedAccountObjectMetadata extends BaseObjectMetadata { }) provider: ConnectedAccountProvider; // field metadata should be a SELECT - @FieldMetadata({ + @WorkspaceField({ standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.accessToken, type: FieldMetadataType.TEXT, label: 'Access Token', @@ -60,7 +60,7 @@ export class ConnectedAccountObjectMetadata extends BaseObjectMetadata { }) accessToken: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.refreshToken, type: FieldMetadataType.TEXT, label: 'Refresh Token', @@ -69,17 +69,7 @@ export class ConnectedAccountObjectMetadata extends BaseObjectMetadata { }) refreshToken: string; - @FieldMetadata({ - standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.accountOwner, - type: FieldMetadataType.RELATION, - label: 'Account Owner', - description: 'Account Owner', - icon: 'IconUserCircle', - joinColumn: 'accountOwnerId', - }) - accountOwner: Relation; - - @FieldMetadata({ + @WorkspaceField({ standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.lastSyncHistoryId, type: FieldMetadataType.TEXT, label: 'Last sync history ID', @@ -88,39 +78,45 @@ export class ConnectedAccountObjectMetadata extends BaseObjectMetadata { }) lastSyncHistoryId: string; - @FieldMetadata({ + @WorkspaceField({ standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.authFailedAt, type: FieldMetadataType.DATE_TIME, label: 'Auth failed at', description: 'Auth failed at', icon: 'IconX', }) - @IsNullable() + @WorkspaceIsNullable() authFailedAt: Date; - @FieldMetadata({ - standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.messageChannels, - type: FieldMetadataType.RELATION, - label: 'Message Channel', - description: 'Message Channel', - icon: 'IconMessage', + @WorkspaceRelation({ + standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.accountOwner, + type: RelationMetadataType.MANY_TO_ONE, + label: 'Account Owner', + description: 'Account Owner', + icon: 'IconUserCircle', + joinColumn: 'accountOwnerId', + inverseSideTarget: () => WorkspaceMemberObjectMetadata, + inverseSideFieldKey: 'connectedAccounts', }) - @RelationMetadata({ + accountOwner: Relation; + + @WorkspaceRelation({ + standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.messageChannels, type: RelationMetadataType.ONE_TO_MANY, + label: 'Message Channels', + description: 'Message Channels', + icon: 'IconMessage', inverseSideTarget: () => MessageChannelObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) messageChannels: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.calendarChannels, - type: FieldMetadataType.RELATION, - label: 'Calendar Channel', - description: 'Calendar Channel', - icon: 'IconCalendar', - }) - @RelationMetadata({ type: RelationMetadataType.ONE_TO_MANY, + label: 'Calendar Channels', + description: 'Calendar Channels', + icon: 'IconCalendar', inverseSideTarget: () => CalendarChannelObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) diff --git a/packages/twenty-server/src/modules/favorite/standard-objects/favorite.object-metadata.ts b/packages/twenty-server/src/modules/favorite/standard-objects/favorite.object-metadata.ts index b40cc9ddd8a..7b1d646ea46 100644 --- a/packages/twenty-server/src/modules/favorite/standard-objects/favorite.object-metadata.ts +++ b/packages/twenty-server/src/modules/favorite/standard-objects/favorite.object-metadata.ts @@ -3,20 +3,22 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FAVORITE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { CustomObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/custom-objects/custom.object-metadata'; -import { DynamicRelationFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/dynamic-field-metadata.interface'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; +import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity'; import { CompanyObjectMetadata } from 'src/modules/company/standard-objects/company.object-metadata'; import { OpportunityObjectMetadata } from 'src/modules/opportunity/standard-objects/opportunity.object-metadata'; import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata'; import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.favorite, namePlural: 'favorites', labelSingular: 'Favorite', @@ -24,10 +26,10 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'A favorite', icon: 'IconHeart', }) -@IsNotAuditLogged() -@IsSystem() -export class FavoriteObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +@WorkspaceIsSystem() +export class FavoriteObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: FAVORITE_STANDARD_FIELD_IDS.position, type: FieldMetadataType.NUMBER, label: 'Position', @@ -38,56 +40,69 @@ export class FavoriteObjectMetadata extends BaseObjectMetadata { position: number; // Relations - @FieldMetadata({ + @WorkspaceRelation({ standardId: FAVORITE_STANDARD_FIELD_IDS.workspaceMember, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Workspace Member', description: 'Favorite workspace member', icon: 'IconCircleUser', joinColumn: 'workspaceMemberId', + inverseSideFieldKey: 'favorites', + inverseSideTarget: () => WorkspaceMemberObjectMetadata, }) workspaceMember: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: FAVORITE_STANDARD_FIELD_IDS.person, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Person', description: 'Favorite person', icon: 'IconUser', joinColumn: 'personId', + inverseSideTarget: () => PersonObjectMetadata, + inverseSideFieldKey: 'favorites', }) - @IsNullable() + @WorkspaceIsNullable() person: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: FAVORITE_STANDARD_FIELD_IDS.company, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'Favorite company', icon: 'IconBuildingSkyscraper', joinColumn: 'companyId', + inverseSideTarget: () => CompanyObjectMetadata, + inverseSideFieldKey: 'favorites', }) - @IsNullable() + @WorkspaceIsNullable() company: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: FAVORITE_STANDARD_FIELD_IDS.opportunity, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Opportunity', description: 'Favorite opportunity', icon: 'IconTargetArrow', joinColumn: 'opportunityId', + inverseSideTarget: () => OpportunityObjectMetadata, + inverseSideFieldKey: 'favorites', }) - @IsNullable() + @WorkspaceIsNullable() opportunity: Relation; - @DynamicRelationFieldMetadata((oppositeObjectMetadata) => ({ - standardId: FAVORITE_STANDARD_FIELD_IDS.custom, - name: oppositeObjectMetadata.nameSingular, - label: oppositeObjectMetadata.labelSingular, - description: `Favorite ${oppositeObjectMetadata.labelSingular}`, - joinColumn: `${oppositeObjectMetadata.nameSingular}Id`, - icon: 'IconBuildingSkyscraper', - })) - custom: Relation; + @WorkspaceDynamicRelation({ + type: RelationMetadataType.MANY_TO_ONE, + argsFactory: (oppositeObjectMetadata) => ({ + standardId: FAVORITE_STANDARD_FIELD_IDS.custom, + name: oppositeObjectMetadata.nameSingular, + label: oppositeObjectMetadata.labelSingular, + description: `Favorite ${oppositeObjectMetadata.labelSingular}`, + joinColumn: `${oppositeObjectMetadata.nameSingular}Id`, + icon: 'IconBuildingSkyscraper', + }), + inverseSideTarget: () => CustomWorkspaceEntity, + inverseSideFieldKey: 'favorites', + }) + custom: Relation; } diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message-channel-message-association.object-metadata.ts b/packages/twenty-server/src/modules/messaging/standard-objects/message-channel-message-association.object-metadata.ts index 3d9aa168b68..d3ee0151818 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message-channel-message-association.object-metadata.ts +++ b/packages/twenty-server/src/modules/messaging/standard-objects/message-channel-message-association.object-metadata.ts @@ -3,17 +3,19 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata'; import { MessageThreadObjectMetadata } from 'src/modules/messaging/standard-objects/message-thread.object-metadata'; import { MessageObjectMetadata } from 'src/modules/messaging/standard-objects/message.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageChannelMessageAssociation, namePlural: 'messageChannelMessageAssociations', labelSingular: 'Message Channel Message Association', @@ -21,63 +23,69 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'Message Synced with a Message Channel', icon: 'IconMessage', }) -@IsNotAuditLogged() -@IsSystem() -export class MessageChannelMessageAssociationObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +@WorkspaceIsSystem() +export class MessageChannelMessageAssociationObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ + standardId: + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.messageExternalId, + type: FieldMetadataType.TEXT, + label: 'Message External Id', + description: 'Message id from the messaging provider', + icon: 'IconHash', + }) + @WorkspaceIsNullable() + messageExternalId: string; + + @WorkspaceField({ + standardId: + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.messageThreadExternalId, + type: FieldMetadataType.TEXT, + label: 'Thread External Id', + description: 'Thread id from the messaging provider', + icon: 'IconHash', + }) + @WorkspaceIsNullable() + messageThreadExternalId: string; + + @WorkspaceRelation({ standardId: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.messageChannel, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Message Channel Id', description: 'Message Channel Id', icon: 'IconHash', joinColumn: 'messageChannelId', + inverseSideTarget: () => MessageChannelObjectMetadata, + inverseSideFieldKey: 'messageChannelMessageAssociations', }) - @IsNullable() + @WorkspaceIsNullable() messageChannel: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.message, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Message Id', description: 'Message Id', icon: 'IconHash', joinColumn: 'messageId', + inverseSideTarget: () => MessageObjectMetadata, + inverseSideFieldKey: 'messageChannelMessageAssociations', }) - @IsNullable() + @WorkspaceIsNullable() message: Relation; - @FieldMetadata({ - standardId: - MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.messageExternalId, - type: FieldMetadataType.TEXT, - label: 'Message External Id', - description: 'Message id from the messaging provider', - icon: 'IconHash', - }) - @IsNullable() - messageExternalId: string; - - @FieldMetadata({ + @WorkspaceRelation({ standardId: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.messageThread, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Message Thread Id', description: 'Message Thread Id', icon: 'IconHash', joinColumn: 'messageThreadId', + inverseSideTarget: () => MessageThreadObjectMetadata, + inverseSideFieldKey: 'messageChannelMessageAssociations', }) - @IsNullable() + @WorkspaceIsNullable() messageThread: Relation; - - @FieldMetadata({ - standardId: - MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.messageThreadExternalId, - type: FieldMetadataType.TEXT, - label: 'Thread External Id', - description: 'Thread id from the messaging provider', - icon: 'IconHash', - }) - @IsNullable() - messageThreadExternalId: string; } diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message-channel.object-metadata.ts b/packages/twenty-server/src/modules/messaging/standard-objects/message-channel.object-metadata.ts index de2d3678a04..487acf0739f 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message-channel.object-metadata.ts +++ b/packages/twenty-server/src/modules/messaging/standard-objects/message-channel.object-metadata.ts @@ -7,15 +7,15 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { MESSAGE_CHANNEL_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata'; import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel-message-association.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; export enum MessageChannelSyncStatus { PENDING = 'PENDING', @@ -35,7 +35,7 @@ export enum MessageChannelType { SMS = 'sms', } -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageChannel, namePlural: 'messageChannels', labelSingular: 'Message Channel', @@ -43,10 +43,10 @@ export enum MessageChannelType { description: 'Message Channels', icon: 'IconMessage', }) -@IsNotAuditLogged() -@IsSystem() -export class MessageChannelObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +@WorkspaceIsSystem() +export class MessageChannelObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.visibility, type: FieldMetadataType.SELECT, label: 'Visibility', @@ -76,7 +76,7 @@ export class MessageChannelObjectMetadata extends BaseObjectMetadata { }) visibility: string; - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.handle, type: FieldMetadataType.TEXT, label: 'Handle', @@ -85,17 +85,7 @@ export class MessageChannelObjectMetadata extends BaseObjectMetadata { }) handle: string; - @FieldMetadata({ - standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.connectedAccount, - type: FieldMetadataType.RELATION, - label: 'Connected Account', - description: 'Connected Account', - icon: 'IconUserCircle', - joinColumn: 'connectedAccountId', - }) - connectedAccount: Relation; - - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.type, type: FieldMetadataType.SELECT, label: 'Type', @@ -119,7 +109,7 @@ export class MessageChannelObjectMetadata extends BaseObjectMetadata { }) type: string; - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.isContactAutoCreationEnabled, type: FieldMetadataType.BOOLEAN, label: 'Is Contact Auto Creation Enabled', @@ -129,7 +119,7 @@ export class MessageChannelObjectMetadata extends BaseObjectMetadata { }) isContactAutoCreationEnabled: boolean; - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.isSyncEnabled, type: FieldMetadataType.BOOLEAN, label: 'Is Sync Enabled', @@ -139,25 +129,7 @@ export class MessageChannelObjectMetadata extends BaseObjectMetadata { }) isSyncEnabled: boolean; - @FieldMetadata({ - standardId: - MESSAGE_CHANNEL_STANDARD_FIELD_IDS.messageChannelMessageAssociations, - type: FieldMetadataType.RELATION, - label: 'Message Channel Association', - description: 'Messages from the channel.', - icon: 'IconMessage', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, - inverseSideTarget: () => MessageChannelMessageAssociationObjectMetadata, - onDelete: RelationOnDeleteAction.CASCADE, - }) - @IsNullable() - messageChannelMessageAssociations: Relation< - MessageChannelMessageAssociationObjectMetadata[] - >; - - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.syncCursor, type: FieldMetadataType.TEXT, label: 'Last sync cursor', @@ -166,17 +138,17 @@ export class MessageChannelObjectMetadata extends BaseObjectMetadata { }) syncCursor: string; - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.syncedAt, type: FieldMetadataType.DATE_TIME, label: 'Last sync date', description: 'Last sync date', icon: 'IconHistory', }) - @IsNullable() + @WorkspaceIsNullable() syncedAt: string; - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.syncStatus, type: FieldMetadataType.SELECT, label: 'Last sync status', @@ -209,16 +181,43 @@ export class MessageChannelObjectMetadata extends BaseObjectMetadata { }, ], }) - @IsNullable() + @WorkspaceIsNullable() syncStatus: MessageChannelSyncStatus; - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.ongoingSyncStartedAt, type: FieldMetadataType.DATE_TIME, label: 'Ongoing sync started at', description: 'Ongoing sync started at', icon: 'IconHistory', }) - @IsNullable() + @WorkspaceIsNullable() ongoingSyncStartedAt: string; + + @WorkspaceRelation({ + standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.connectedAccount, + type: RelationMetadataType.MANY_TO_ONE, + label: 'Connected Account', + description: 'Connected Account', + icon: 'IconUserCircle', + joinColumn: 'connectedAccountId', + inverseSideTarget: () => ConnectedAccountObjectMetadata, + inverseSideFieldKey: 'messageChannels', + }) + connectedAccount: Relation; + + @WorkspaceRelation({ + standardId: + MESSAGE_CHANNEL_STANDARD_FIELD_IDS.messageChannelMessageAssociations, + type: RelationMetadataType.ONE_TO_MANY, + label: 'Message Channel Association', + description: 'Messages from the channel.', + icon: 'IconMessage', + inverseSideTarget: () => MessageChannelMessageAssociationObjectMetadata, + onDelete: RelationOnDeleteAction.CASCADE, + }) + @WorkspaceIsNullable() + messageChannelMessageAssociations: Relation< + MessageChannelMessageAssociationObjectMetadata[] + >; } diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message-participant.object-metadata.ts b/packages/twenty-server/src/modules/messaging/standard-objects/message-participant.object-metadata.ts index 5a10ce397ff..3acca760adc 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message-participant.object-metadata.ts +++ b/packages/twenty-server/src/modules/messaging/standard-objects/message-participant.object-metadata.ts @@ -3,17 +3,19 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { MessageObjectMetadata } from 'src/modules/messaging/standard-objects/message.object-metadata'; import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata'; import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageParticipant, namePlural: 'messageParticipants', labelSingular: 'Message Participant', @@ -21,20 +23,10 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'Message Participants', icon: 'IconUserCircle', }) -@IsNotAuditLogged() -@IsSystem() -export class MessageParticipantObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ - standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.message, - type: FieldMetadataType.RELATION, - label: 'Message', - description: 'Message', - icon: 'IconMessage', - joinColumn: 'messageId', - }) - message: Relation; - - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +@WorkspaceIsSystem() +export class MessageParticipantObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.role, type: FieldMetadataType.SELECT, label: 'Role', @@ -50,7 +42,7 @@ export class MessageParticipantObjectMetadata extends BaseObjectMetadata { }) role: string; - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.handle, type: FieldMetadataType.TEXT, label: 'Handle', @@ -59,7 +51,7 @@ export class MessageParticipantObjectMetadata extends BaseObjectMetadata { }) handle: string; - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.displayName, type: FieldMetadataType.TEXT, label: 'Display Name', @@ -68,25 +60,41 @@ export class MessageParticipantObjectMetadata extends BaseObjectMetadata { }) displayName: string; - @FieldMetadata({ + @WorkspaceRelation({ + standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.message, + type: RelationMetadataType.MANY_TO_ONE, + label: 'Message', + description: 'Message', + icon: 'IconMessage', + joinColumn: 'messageId', + inverseSideTarget: () => MessageObjectMetadata, + inverseSideFieldKey: 'messageParticipants', + }) + message: Relation; + + @WorkspaceRelation({ standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.person, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Person', description: 'Person', icon: 'IconUser', joinColumn: 'personId', + inverseSideTarget: () => PersonObjectMetadata, + inverseSideFieldKey: 'messageParticipants', }) - @IsNullable() + @WorkspaceIsNullable() person: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.workspaceMember, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Workspace Member', description: 'Workspace member', icon: 'IconCircleUser', joinColumn: 'workspaceMemberId', + inverseSideTarget: () => WorkspaceMemberObjectMetadata, + inverseSideFieldKey: 'messageParticipants', }) - @IsNullable() + @WorkspaceIsNullable() workspaceMember: Relation; } diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message-thread.object-metadata.ts b/packages/twenty-server/src/modules/messaging/standard-objects/message-thread.object-metadata.ts index b06f6d072c8..957251bfc01 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message-thread.object-metadata.ts +++ b/packages/twenty-server/src/modules/messaging/standard-objects/message-thread.object-metadata.ts @@ -1,23 +1,21 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; -import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { RelationMetadataType, RelationOnDeleteAction, } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { MESSAGE_THREAD_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel-message-association.object-metadata'; import { MessageObjectMetadata } from 'src/modules/messaging/standard-objects/message.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageThread, namePlural: 'messageThreads', labelSingular: 'Message Thread', @@ -25,38 +23,32 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'Message Thread', icon: 'IconMessage', }) -@IsNotAuditLogged() -@IsSystem() -export class MessageThreadObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +@WorkspaceIsSystem() +export class MessageThreadObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceRelation({ standardId: MESSAGE_THREAD_STANDARD_FIELD_IDS.messages, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Messages', description: 'Messages from the thread.', icon: 'IconMessage', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => MessageObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() + @WorkspaceIsNullable() messages: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: MESSAGE_THREAD_STANDARD_FIELD_IDS.messageChannelMessageAssociations, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Message Channel Association', - description: 'Messages from the channel.', + description: 'Messages from the channel', icon: 'IconMessage', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => MessageChannelMessageAssociationObjectMetadata, onDelete: RelationOnDeleteAction.RESTRICT, }) - @IsNullable() + @WorkspaceIsNullable() messageChannelMessageAssociations: Relation< MessageChannelMessageAssociationObjectMetadata[] >; diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message.object-metadata.ts b/packages/twenty-server/src/modules/messaging/standard-objects/message.object-metadata.ts index 8319e2618ac..2d7ed865261 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message.object-metadata.ts +++ b/packages/twenty-server/src/modules/messaging/standard-objects/message.object-metadata.ts @@ -7,18 +7,18 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { MESSAGE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel-message-association.object-metadata'; import { MessageParticipantObjectMetadata } from 'src/modules/messaging/standard-objects/message-participant.object-metadata'; import { MessageThreadObjectMetadata } from 'src/modules/messaging/standard-objects/message-thread.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.message, namePlural: 'messages', labelSingular: 'Message', @@ -26,10 +26,10 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'Message', icon: 'IconMessage', }) -@IsNotAuditLogged() -@IsSystem() -export class MessageObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +@WorkspaceIsSystem() +export class MessageObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: MESSAGE_STANDARD_FIELD_IDS.headerMessageId, type: FieldMetadataType.TEXT, label: 'Header message Id', @@ -38,18 +38,7 @@ export class MessageObjectMetadata extends BaseObjectMetadata { }) headerMessageId: string; - @FieldMetadata({ - standardId: MESSAGE_STANDARD_FIELD_IDS.messageThread, - type: FieldMetadataType.RELATION, - label: 'Message Thread Id', - description: 'Message Thread Id', - icon: 'IconHash', - joinColumn: 'messageThreadId', - }) - @IsNullable() - messageThread: Relation; - - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_STANDARD_FIELD_IDS.direction, type: FieldMetadataType.SELECT, label: 'Direction', @@ -63,7 +52,7 @@ export class MessageObjectMetadata extends BaseObjectMetadata { }) direction: string; - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_STANDARD_FIELD_IDS.subject, type: FieldMetadataType.TEXT, label: 'Subject', @@ -72,7 +61,7 @@ export class MessageObjectMetadata extends BaseObjectMetadata { }) subject: string; - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_STANDARD_FIELD_IDS.text, type: FieldMetadataType.TEXT, label: 'Text', @@ -81,45 +70,52 @@ export class MessageObjectMetadata extends BaseObjectMetadata { }) text: string; - @FieldMetadata({ + @WorkspaceField({ standardId: MESSAGE_STANDARD_FIELD_IDS.receivedAt, type: FieldMetadataType.DATE_TIME, label: 'Received At', description: 'The date the message was received', icon: 'IconCalendar', }) - @IsNullable() + @WorkspaceIsNullable() receivedAt: string; - @FieldMetadata({ + @WorkspaceRelation({ + standardId: MESSAGE_STANDARD_FIELD_IDS.messageThread, + type: RelationMetadataType.MANY_TO_ONE, + label: 'Message Thread Id', + description: 'Message Thread Id', + icon: 'IconHash', + joinColumn: 'messageThreadId', + inverseSideTarget: () => MessageThreadObjectMetadata, + inverseSideFieldKey: 'messages', + onDelete: RelationOnDeleteAction.CASCADE, + }) + @WorkspaceIsNullable() + messageThread: Relation; + + @WorkspaceRelation({ standardId: MESSAGE_STANDARD_FIELD_IDS.messageParticipants, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Message Participants', description: 'Message Participants', icon: 'IconUserCircle', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => MessageParticipantObjectMetadata, - inverseSideFieldKey: 'message', onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() + @WorkspaceIsNullable() messageParticipants: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: MESSAGE_STANDARD_FIELD_IDS.messageChannelMessageAssociations, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Message Channel Association', description: 'Messages from the channel.', icon: 'IconMessage', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => MessageChannelMessageAssociationObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() + @WorkspaceIsNullable() messageChannelMessageAssociations: Relation< MessageChannelMessageAssociationObjectMetadata[] >; diff --git a/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.object-metadata.ts b/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.object-metadata.ts index e94897a4849..224ac5fe9ff 100644 --- a/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.object-metadata.ts +++ b/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.object-metadata.ts @@ -8,21 +8,21 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { OPPORTUNITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; import { ActivityTargetObjectMetadata } from 'src/modules/activity/standard-objects/activity-target.object-metadata'; import { AttachmentObjectMetadata } from 'src/modules/attachment/standard-objects/attachment.object-metadata'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { CompanyObjectMetadata } from 'src/modules/company/standard-objects/company.object-metadata'; import { FavoriteObjectMetadata } from 'src/modules/favorite/standard-objects/favorite.object-metadata'; import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata'; import { TimelineActivityObjectMetadata } from 'src/modules/timeline/standard-objects/timeline-activity.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.opportunity, namePlural: 'opportunities', labelSingular: 'Opportunity', @@ -30,9 +30,9 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'An opportunity', icon: 'IconTargetArrow', }) -@IsNotAuditLogged() -export class OpportunityObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +export class OpportunityObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.name, type: FieldMetadataType.TEXT, label: 'Name', @@ -41,27 +41,27 @@ export class OpportunityObjectMetadata extends BaseObjectMetadata { }) name: string; - @FieldMetadata({ + @WorkspaceField({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.amount, type: FieldMetadataType.CURRENCY, label: 'Amount', description: 'Opportunity amount', icon: 'IconCurrencyDollar', }) - @IsNullable() + @WorkspaceIsNullable() amount: CurrencyMetadata; - @FieldMetadata({ + @WorkspaceField({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.closeDate, type: FieldMetadataType.DATE_TIME, label: 'Close date', description: 'Opportunity close date', icon: 'IconCalendarEvent', }) - @IsNullable() + @WorkspaceIsNullable() closeDate: Date; - @FieldMetadata({ + @WorkspaceField({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.probability, type: FieldMetadataType.TEXT, label: 'Probability', @@ -71,7 +71,7 @@ export class OpportunityObjectMetadata extends BaseObjectMetadata { }) probability: string; - @FieldMetadata({ + @WorkspaceField({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.stage, type: FieldMetadataType.SELECT, label: 'Stage', @@ -93,97 +93,91 @@ export class OpportunityObjectMetadata extends BaseObjectMetadata { }) stage: string; - @FieldMetadata({ + @WorkspaceField({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.position, type: FieldMetadataType.POSITION, label: 'Position', description: 'Opportunity record position', icon: 'IconHierarchy2', }) - @IsSystem() - @IsNullable() + @WorkspaceIsSystem() + @WorkspaceIsNullable() position: number; - @FieldMetadata({ + @WorkspaceRelation({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.pointOfContact, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Point of Contact', description: 'Opportunity point of contact', icon: 'IconUser', joinColumn: 'pointOfContactId', + inverseSideTarget: () => PersonObjectMetadata, + inverseSideFieldKey: 'pointOfContactForOpportunities', + onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsNullable() + @WorkspaceIsNullable() pointOfContact: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.company, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'Opportunity company', icon: 'IconBuildingSkyscraper', joinColumn: 'companyId', + inverseSideTarget: () => CompanyObjectMetadata, + inverseSideFieldKey: 'opportunities', + onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsNullable() + @WorkspaceIsNullable() company: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.favorites, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Favorites', description: 'Favorites linked to the opportunity', icon: 'IconHeart', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => FavoriteObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() - @IsSystem() + @WorkspaceIsNullable() + @WorkspaceIsSystem() favorites: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.activityTargets, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Activities', description: 'Activities tied to the opportunity', icon: 'IconCheckbox', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => ActivityTargetObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() + @WorkspaceIsNullable() activityTargets: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.attachments, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Attachments', - description: 'Attachments linked to the opportunity.', + description: 'Attachments linked to the opportunity', icon: 'IconFileImport', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => AttachmentObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() + @WorkspaceIsNullable() attachments: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.timelineActivities, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Timeline Activities', description: 'Timeline Activities linked to the opportunity.', icon: 'IconTimelineEvent', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => TimelineActivityObjectMetadata, onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsNullable() + @WorkspaceIsNullable() timelineActivities: Relation; } diff --git a/packages/twenty-server/src/modules/person/standard-objects/person.object-metadata.ts b/packages/twenty-server/src/modules/person/standard-objects/person.object-metadata.ts index f6333a8c3be..8615dd94afb 100644 --- a/packages/twenty-server/src/modules/person/standard-objects/person.object-metadata.ts +++ b/packages/twenty-server/src/modules/person/standard-objects/person.object-metadata.ts @@ -9,22 +9,22 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { PERSON_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; import { ActivityTargetObjectMetadata } from 'src/modules/activity/standard-objects/activity-target.object-metadata'; import { AttachmentObjectMetadata } from 'src/modules/attachment/standard-objects/attachment.object-metadata'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { CalendarEventParticipantObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event-participant.object-metadata'; import { CompanyObjectMetadata } from 'src/modules/company/standard-objects/company.object-metadata'; import { FavoriteObjectMetadata } from 'src/modules/favorite/standard-objects/favorite.object-metadata'; import { MessageParticipantObjectMetadata } from 'src/modules/messaging/standard-objects/message-participant.object-metadata'; import { OpportunityObjectMetadata } from 'src/modules/opportunity/standard-objects/opportunity.object-metadata'; import { TimelineActivityObjectMetadata } from 'src/modules/timeline/standard-objects/timeline-activity.object-metadata'; - -@ObjectMetadata({ +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; + +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.person, namePlural: 'people', labelSingular: 'Person', @@ -32,18 +32,18 @@ import { TimelineActivityObjectMetadata } from 'src/modules/timeline/standard-ob description: 'A person', icon: 'IconUser', }) -export class PersonObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +export class PersonObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.name, type: FieldMetadataType.FULL_NAME, label: 'Name', description: 'Contact’s name', icon: 'IconUser', }) - @IsNullable() + @WorkspaceIsNullable() name: FullNameMetadata; - @FieldMetadata({ + @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.email, type: FieldMetadataType.EMAIL, label: 'Email', @@ -52,27 +52,27 @@ export class PersonObjectMetadata extends BaseObjectMetadata { }) email: string; - @FieldMetadata({ + @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.linkedinLink, type: FieldMetadataType.LINK, label: 'Linkedin', description: 'Contact’s Linkedin account', icon: 'IconBrandLinkedin', }) - @IsNullable() + @WorkspaceIsNullable() linkedinLink: LinkMetadata; - @FieldMetadata({ + @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.xLink, type: FieldMetadataType.LINK, label: 'X', description: 'Contact’s X/Twitter account', icon: 'IconBrandX', }) - @IsNullable() + @WorkspaceIsNullable() xLink: LinkMetadata; - @FieldMetadata({ + @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.jobTitle, type: FieldMetadataType.TEXT, label: 'Job Title', @@ -81,7 +81,7 @@ export class PersonObjectMetadata extends BaseObjectMetadata { }) jobTitle: string; - @FieldMetadata({ + @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.phone, type: FieldMetadataType.TEXT, label: 'Phone', @@ -90,7 +90,7 @@ export class PersonObjectMetadata extends BaseObjectMetadata { }) phone: string; - @FieldMetadata({ + @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.city, type: FieldMetadataType.TEXT, label: 'City', @@ -99,141 +99,122 @@ export class PersonObjectMetadata extends BaseObjectMetadata { }) city: string; - @FieldMetadata({ + @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.avatarUrl, type: FieldMetadataType.TEXT, label: 'Avatar', description: 'Contact’s avatar', icon: 'IconFileUpload', }) - @IsSystem() + @WorkspaceIsSystem() avatarUrl: string; - @FieldMetadata({ + @WorkspaceField({ standardId: PERSON_STANDARD_FIELD_IDS.position, type: FieldMetadataType.POSITION, label: 'Position', description: 'Person record Position', icon: 'IconHierarchy2', }) - @IsSystem() - @IsNullable() + @WorkspaceIsSystem() + @WorkspaceIsNullable() position: number; // Relations - @FieldMetadata({ + @WorkspaceRelation({ standardId: PERSON_STANDARD_FIELD_IDS.company, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'Contact’s company', icon: 'IconBuildingSkyscraper', joinColumn: 'companyId', + inverseSideTarget: () => CompanyObjectMetadata, + inverseSideFieldKey: 'people', }) - @IsNullable() + @WorkspaceIsNullable() company: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: PERSON_STANDARD_FIELD_IDS.pointOfContactForOpportunities, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'POC for Opportunities', description: 'Point of Contact for Opportunities', icon: 'IconTargetArrow', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => OpportunityObjectMetadata, inverseSideFieldKey: 'pointOfContact', onDelete: RelationOnDeleteAction.SET_NULL, }) pointOfContactForOpportunities: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: PERSON_STANDARD_FIELD_IDS.activityTargets, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Activities', description: 'Activities tied to the contact', icon: 'IconCheckbox', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => ActivityTargetObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) activityTargets: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: PERSON_STANDARD_FIELD_IDS.favorites, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Favorites', description: 'Favorites linked to the contact', icon: 'IconHeart', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => FavoriteObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsSystem() + @WorkspaceIsSystem() favorites: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: PERSON_STANDARD_FIELD_IDS.attachments, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Attachments', description: 'Attachments linked to the contact.', icon: 'IconFileImport', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => AttachmentObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) attachments: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: PERSON_STANDARD_FIELD_IDS.messageParticipants, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Message Participants', description: 'Message Participants', icon: 'IconUserCircle', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => MessageParticipantObjectMetadata, inverseSideFieldKey: 'person', onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsSystem() + @WorkspaceIsSystem() messageParticipants: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: PERSON_STANDARD_FIELD_IDS.calendarEventParticipants, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Calendar Event Participants', description: 'Calendar Event Participants', icon: 'IconCalendar', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => CalendarEventParticipantObjectMetadata, onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsSystem() + @WorkspaceIsSystem() calendarEventParticipants: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: PERSON_STANDARD_FIELD_IDS.timelineActivities, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Events', description: 'Events linked to the company', icon: 'IconTimelineEvent', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => TimelineActivityObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() - @IsSystem() + @WorkspaceIsNullable() + @WorkspaceIsSystem() timelineActivities: Relation; } diff --git a/packages/twenty-server/src/modules/timeline/standard-objects/audit-log.object-metadata.ts b/packages/twenty-server/src/modules/timeline/standard-objects/audit-log.object-metadata.ts index 71f76d9663d..4abf6bb22b1 100644 --- a/packages/twenty-server/src/modules/timeline/standard-objects/audit-log.object-metadata.ts +++ b/packages/twenty-server/src/modules/timeline/standard-objects/audit-log.object-metadata.ts @@ -3,14 +3,16 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { AUDIT_LOGS_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.auditLog, namePlural: 'auditLogs', labelSingular: 'Audit Log', @@ -18,9 +20,9 @@ import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/stan description: 'An audit log of actions performed in the system', icon: 'IconIconTimelineEvent', }) -@IsSystem() -export class AuditLogObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsSystem() +export class AuditLogObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: AUDIT_LOGS_STANDARD_FIELD_IDS.name, type: FieldMetadataType.TEXT, label: 'Event name', @@ -29,17 +31,17 @@ export class AuditLogObjectMetadata extends BaseObjectMetadata { }) name: string; - @FieldMetadata({ + @WorkspaceField({ standardId: AUDIT_LOGS_STANDARD_FIELD_IDS.properties, type: FieldMetadataType.RAW_JSON, label: 'Event details', description: 'Json value for event details', icon: 'IconListDetails', }) - @IsNullable() + @WorkspaceIsNullable() properties: JSON; - @FieldMetadata({ + @WorkspaceField({ standardId: AUDIT_LOGS_STANDARD_FIELD_IDS.context, type: FieldMetadataType.RAW_JSON, label: 'Event context', @@ -47,10 +49,10 @@ export class AuditLogObjectMetadata extends BaseObjectMetadata { 'Json object to provide context (user, device, workspace, etc.)', icon: 'IconListDetails', }) - @IsNullable() + @WorkspaceIsNullable() context: JSON; - @FieldMetadata({ + @WorkspaceField({ standardId: AUDIT_LOGS_STANDARD_FIELD_IDS.objectName, type: FieldMetadataType.TEXT, label: 'Object name', @@ -59,7 +61,7 @@ export class AuditLogObjectMetadata extends BaseObjectMetadata { }) objectName: string; - @FieldMetadata({ + @WorkspaceField({ standardId: AUDIT_LOGS_STANDARD_FIELD_IDS.objectName, type: FieldMetadataType.TEXT, label: 'Object name', @@ -68,24 +70,26 @@ export class AuditLogObjectMetadata extends BaseObjectMetadata { }) objectMetadataId: string; - @FieldMetadata({ + @WorkspaceField({ standardId: AUDIT_LOGS_STANDARD_FIELD_IDS.recordId, type: FieldMetadataType.UUID, label: 'Object id', description: 'Event name/type', icon: 'IconAbc', }) - @IsNullable() + @WorkspaceIsNullable() recordId: string; - @FieldMetadata({ + @WorkspaceRelation({ standardId: AUDIT_LOGS_STANDARD_FIELD_IDS.workspaceMember, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Workspace Member', description: 'Event workspace member', icon: 'IconCircleUser', joinColumn: 'workspaceMemberId', + inverseSideTarget: () => WorkspaceMemberObjectMetadata, + inverseSideFieldKey: 'auditLogs', }) - @IsNullable() + @WorkspaceIsNullable() workspaceMember: Relation; } diff --git a/packages/twenty-server/src/modules/timeline/standard-objects/behavioral-event.object-metadata.ts b/packages/twenty-server/src/modules/timeline/standard-objects/behavioral-event.object-metadata.ts index 4f1643727d5..961c03f3a55 100644 --- a/packages/twenty-server/src/modules/timeline/standard-objects/behavioral-event.object-metadata.ts +++ b/packages/twenty-server/src/modules/timeline/standard-objects/behavioral-event.object-metadata.ts @@ -1,15 +1,15 @@ import { FeatureFlagKeys } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; import { BEHAVIORAL_EVENT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { Gate } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/gate.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.behavioralEvent, namePlural: 'behavioralEvents', labelSingular: 'Behavioral Event', @@ -17,11 +17,11 @@ import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync- description: 'An event related to user behavior', icon: 'IconIconTimelineEvent', }) -@IsSystem() -@Gate({ +@WorkspaceIsSystem() +@WorkspaceGate({ featureFlag: FeatureFlagKeys.IsEventObjectEnabled, }) -export class BehavioralEventObjectMetadata extends BaseObjectMetadata { +export class BehavioralEventObjectMetadata extends BaseWorkspaceEntity { /** * * Common in Segment, Rudderstack, etc. @@ -29,7 +29,7 @@ export class BehavioralEventObjectMetadata extends BaseObjectMetadata { * But doesn't feel that useful. * Let's try living without it. * - @FieldMetadata({ + @WorkspaceField({ standardId: behavioralEventStandardFieldIds.type, type: FieldMetadataType.TEXT, label: 'Event type', @@ -39,7 +39,7 @@ export class BehavioralEventObjectMetadata extends BaseObjectMetadata { type: string; */ - @FieldMetadata({ + @WorkspaceField({ standardId: BEHAVIORAL_EVENT_STANDARD_FIELD_IDS.name, type: FieldMetadataType.TEXT, label: 'Event name', @@ -48,17 +48,17 @@ export class BehavioralEventObjectMetadata extends BaseObjectMetadata { }) name: string; - @FieldMetadata({ + @WorkspaceField({ standardId: BEHAVIORAL_EVENT_STANDARD_FIELD_IDS.properties, type: FieldMetadataType.RAW_JSON, label: 'Event details', description: 'Json value for event details', icon: 'IconListDetails', }) - @IsNullable() + @WorkspaceIsNullable() properties: JSON; - @FieldMetadata({ + @WorkspaceField({ standardId: BEHAVIORAL_EVENT_STANDARD_FIELD_IDS.context, type: FieldMetadataType.RAW_JSON, label: 'Event context', @@ -66,10 +66,10 @@ export class BehavioralEventObjectMetadata extends BaseObjectMetadata { 'Json object to provide context (user, device, workspace, etc.)', icon: 'IconListDetails', }) - @IsNullable() + @WorkspaceIsNullable() context: JSON; - @FieldMetadata({ + @WorkspaceField({ standardId: BEHAVIORAL_EVENT_STANDARD_FIELD_IDS.objectName, type: FieldMetadataType.TEXT, label: 'Object name', @@ -78,13 +78,13 @@ export class BehavioralEventObjectMetadata extends BaseObjectMetadata { }) objectName: string; - @FieldMetadata({ + @WorkspaceField({ standardId: BEHAVIORAL_EVENT_STANDARD_FIELD_IDS.recordId, type: FieldMetadataType.UUID, label: 'Object id', description: 'Event name/type', icon: 'IconAbc', }) - @IsNullable() + @WorkspaceIsNullable() recordId: string; } diff --git a/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.object-metadata.ts b/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.object-metadata.ts index 257b13b8273..bc0d672f284 100644 --- a/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.object-metadata.ts +++ b/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.object-metadata.ts @@ -3,20 +3,22 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { TIMELINE_ACTIVITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { DynamicRelationFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/dynamic-field-metadata.interface'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { CompanyObjectMetadata } from 'src/modules/company/standard-objects/company.object-metadata'; import { OpportunityObjectMetadata } from 'src/modules/opportunity/standard-objects/opportunity.object-metadata'; import { PersonObjectMetadata } from 'src/modules/person/standard-objects/person.object-metadata'; import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; -import { CustomObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/custom-objects/custom.object-metadata'; +import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.timelineActivity, namePlural: 'timelineActivities', labelSingular: 'Timeline Activity', @@ -24,10 +26,10 @@ import { CustomObjectMetadata } from 'src/engine/workspace-manager/workspace-syn description: 'Aggregated / filtered event to be displayed on the timeline', icon: 'IconIconTimelineEvent', }) -@IsSystem() -@IsNotAuditLogged() -export class TimelineActivityObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsSystem() +@WorkspaceIsNotAuditLogged() +export class TimelineActivityObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.happensAt, type: FieldMetadataType.DATE_TIME, label: 'Creation date', @@ -37,7 +39,7 @@ export class TimelineActivityObjectMetadata extends BaseObjectMetadata { }) happensAt: Date; - @FieldMetadata({ + @WorkspaceField({ standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.name, type: FieldMetadataType.TEXT, label: 'Event name', @@ -46,98 +48,111 @@ export class TimelineActivityObjectMetadata extends BaseObjectMetadata { }) name: string; - @FieldMetadata({ + @WorkspaceField({ standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.properties, type: FieldMetadataType.RAW_JSON, label: 'Event details', description: 'Json value for event details', icon: 'IconListDetails', }) - @IsNullable() + @WorkspaceIsNullable() properties: JSON; + // Special objects that don't have their own timeline and are 'link' to the main object + @WorkspaceField({ + standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.linkedRecordCachedName, + type: FieldMetadataType.TEXT, + label: 'Linked Record cached name', + description: 'Cached record name', + icon: 'IconAbc', + }) + linkedRecordCachedName: string; + + @WorkspaceField({ + standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.linkedRecordId, + type: FieldMetadataType.UUID, + label: 'Linked Record id', + description: 'Linked Record id', + icon: 'IconAbc', + }) + @WorkspaceIsNullable() + linkedRecordId: string; + + @WorkspaceField({ + standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.linkedObjectMetadataId, + type: FieldMetadataType.UUID, + label: 'Linked Object Metadata Id', + description: 'inked Object Metadata Id', + icon: 'IconAbc', + }) + @WorkspaceIsNullable() + linkedObjectMetadataId: string; + // Who made the action - @FieldMetadata({ + @WorkspaceRelation({ standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.workspaceMember, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Workspace Member', description: 'Event workspace member', icon: 'IconCircleUser', joinColumn: 'workspaceMemberId', + inverseSideTarget: () => WorkspaceMemberObjectMetadata, + inverseSideFieldKey: 'timelineActivities', }) - @IsNullable() + @WorkspaceIsNullable() workspaceMember: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.person, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Person', description: 'Event person', icon: 'IconUser', joinColumn: 'personId', + inverseSideTarget: () => PersonObjectMetadata, + inverseSideFieldKey: 'timelineActivities', }) - @IsNullable() + @WorkspaceIsNullable() person: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.company, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'Event company', icon: 'IconBuildingSkyscraper', joinColumn: 'companyId', + inverseSideTarget: () => CompanyObjectMetadata, + inverseSideFieldKey: 'timelineActivities', }) - @IsNullable() + @WorkspaceIsNullable() company: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.opportunity, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'Opportunity', - description: 'Events opportunity', + description: 'Event opportunity', icon: 'IconTargetArrow', joinColumn: 'opportunityId', + inverseSideTarget: () => OpportunityObjectMetadata, + inverseSideFieldKey: 'timelineActivities', }) - @IsNullable() + @WorkspaceIsNullable() opportunity: Relation; - @DynamicRelationFieldMetadata((oppositeObjectMetadata) => ({ - standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.custom, - name: oppositeObjectMetadata.nameSingular, - label: oppositeObjectMetadata.labelSingular, - description: `Event ${oppositeObjectMetadata.labelSingular}`, - joinColumn: `${oppositeObjectMetadata.nameSingular}Id`, - icon: 'IconTimeline', - })) - custom: Relation; - - // Special objects that don't have their own timeline and are 'link' to the main object - @FieldMetadata({ - standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.linkedRecordCachedName, - type: FieldMetadataType.TEXT, - label: 'Linked Record cached name', - description: 'Cached record name', - icon: 'IconAbc', - }) - linkedRecordCachedName: string; - - @FieldMetadata({ - standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.linkedRecordId, - type: FieldMetadataType.UUID, - label: 'Linked Record id', - description: 'Linked Record id', - icon: 'IconAbc', - }) - @IsNullable() - linkedRecordId: string; - - @FieldMetadata({ - standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.linkedObjectMetadataId, - type: FieldMetadataType.UUID, - label: 'Linked Object Metadata Id', - description: 'inked Object Metadata Id', - icon: 'IconAbc', + @WorkspaceDynamicRelation({ + type: RelationMetadataType.MANY_TO_ONE, + argsFactory: (oppositeObjectMetadata) => ({ + standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.custom, + name: oppositeObjectMetadata.nameSingular, + label: oppositeObjectMetadata.labelSingular, + description: `Event ${oppositeObjectMetadata.labelSingular}`, + joinColumn: `${oppositeObjectMetadata.nameSingular}Id`, + icon: 'IconTimeline', + }), + inverseSideTarget: () => CustomWorkspaceEntity, + inverseSideFieldKey: 'timelineActivities', }) - @IsNullable() - linkedObjectMetadataId: string; + custom: Relation; } diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-field.object-metadata.ts b/packages/twenty-server/src/modules/view/standard-objects/view-field.object-metadata.ts index 835349be259..75c3a944e73 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-field.object-metadata.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-field.object-metadata.ts @@ -1,15 +1,17 @@ import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { VIEW_FIELD_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { ViewObjectMetadata } from 'src/modules/view/standard-objects/view.object-metadata'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.viewField, namePlural: 'viewFields', labelSingular: 'View Field', @@ -17,10 +19,10 @@ import { ViewObjectMetadata } from 'src/modules/view/standard-objects/view.objec description: '(System) View Fields', icon: 'IconTag', }) -@IsNotAuditLogged() -@IsSystem() -export class ViewFieldObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +@WorkspaceIsSystem() +export class ViewFieldObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: VIEW_FIELD_STANDARD_FIELD_IDS.fieldMetadataId, type: FieldMetadataType.UUID, label: 'Field Metadata Id', @@ -29,7 +31,7 @@ export class ViewFieldObjectMetadata extends BaseObjectMetadata { }) fieldMetadataId: string; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_FIELD_STANDARD_FIELD_IDS.isVisible, type: FieldMetadataType.BOOLEAN, label: 'Visible', @@ -39,7 +41,7 @@ export class ViewFieldObjectMetadata extends BaseObjectMetadata { }) isVisible: boolean; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_FIELD_STANDARD_FIELD_IDS.size, type: FieldMetadataType.NUMBER, label: 'Size', @@ -49,7 +51,7 @@ export class ViewFieldObjectMetadata extends BaseObjectMetadata { }) size: number; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_FIELD_STANDARD_FIELD_IDS.position, type: FieldMetadataType.NUMBER, label: 'Position', @@ -59,14 +61,16 @@ export class ViewFieldObjectMetadata extends BaseObjectMetadata { }) position: number; - @FieldMetadata({ + @WorkspaceRelation({ standardId: VIEW_FIELD_STANDARD_FIELD_IDS.view, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'View', description: 'View Field related view', icon: 'IconLayoutCollage', + inverseSideTarget: () => ViewObjectMetadata, + inverseSideFieldKey: 'viewFields', joinColumn: 'viewId', }) - @IsNullable() + @WorkspaceIsNullable() view?: ViewObjectMetadata; } diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-filter.object-metadata.ts b/packages/twenty-server/src/modules/view/standard-objects/view-filter.object-metadata.ts index 6ac6663d4fb..8be331d1157 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-filter.object-metadata.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-filter.object-metadata.ts @@ -3,15 +3,17 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { VIEW_FILTER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { ViewObjectMetadata } from 'src/modules/view/standard-objects/view.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.viewFilter, namePlural: 'viewFilters', labelSingular: 'View Filter', @@ -19,10 +21,10 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: '(System) View Filters', icon: 'IconFilterBolt', }) -@IsNotAuditLogged() -@IsSystem() -export class ViewFilterObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +@WorkspaceIsSystem() +export class ViewFilterObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: VIEW_FILTER_STANDARD_FIELD_IDS.fieldMetadataId, type: FieldMetadataType.UUID, label: 'Field Metadata Id', @@ -30,7 +32,7 @@ export class ViewFilterObjectMetadata extends BaseObjectMetadata { }) fieldMetadataId: string; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_FILTER_STANDARD_FIELD_IDS.operand, type: FieldMetadataType.TEXT, label: 'Operand', @@ -39,7 +41,7 @@ export class ViewFilterObjectMetadata extends BaseObjectMetadata { }) operand: string; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_FILTER_STANDARD_FIELD_IDS.value, type: FieldMetadataType.TEXT, label: 'Value', @@ -47,7 +49,7 @@ export class ViewFilterObjectMetadata extends BaseObjectMetadata { }) value: string; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_FILTER_STANDARD_FIELD_IDS.displayValue, type: FieldMetadataType.TEXT, label: 'Display Value', @@ -55,14 +57,16 @@ export class ViewFilterObjectMetadata extends BaseObjectMetadata { }) displayValue: string; - @FieldMetadata({ + @WorkspaceRelation({ standardId: VIEW_FILTER_STANDARD_FIELD_IDS.view, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'View', description: 'View Filter related view', icon: 'IconLayoutCollage', joinColumn: 'viewId', + inverseSideTarget: () => ViewObjectMetadata, + inverseSideFieldKey: 'viewFilters', }) - @IsNullable() + @WorkspaceIsNullable() view: Relation; } diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-sort.object-metadata.ts b/packages/twenty-server/src/modules/view/standard-objects/view-sort.object-metadata.ts index b28eb87c0d0..5c1c61a8d03 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-sort.object-metadata.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-sort.object-metadata.ts @@ -3,15 +3,17 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { VIEW_SORT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { ViewObjectMetadata } from 'src/modules/view/standard-objects/view.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.viewSort, namePlural: 'viewSorts', labelSingular: 'View Sort', @@ -19,10 +21,10 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: '(System) View Sorts', icon: 'IconArrowsSort', }) -@IsNotAuditLogged() -@IsSystem() -export class ViewSortObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +@WorkspaceIsSystem() +export class ViewSortObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: VIEW_SORT_STANDARD_FIELD_IDS.fieldMetadataId, type: FieldMetadataType.UUID, label: 'Field Metadata Id', @@ -31,7 +33,7 @@ export class ViewSortObjectMetadata extends BaseObjectMetadata { }) fieldMetadataId: string; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_SORT_STANDARD_FIELD_IDS.direction, type: FieldMetadataType.TEXT, label: 'Direction', @@ -40,14 +42,16 @@ export class ViewSortObjectMetadata extends BaseObjectMetadata { }) direction: string; - @FieldMetadata({ + @WorkspaceRelation({ standardId: VIEW_SORT_STANDARD_FIELD_IDS.view, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.MANY_TO_ONE, label: 'View', description: 'View Sort related view', icon: 'IconLayoutCollage', joinColumn: 'viewId', + inverseSideTarget: () => ViewObjectMetadata, + inverseSideFieldKey: 'viewSorts', }) - @IsNullable() + @WorkspaceIsNullable() view: Relation; } diff --git a/packages/twenty-server/src/modules/view/standard-objects/view.object-metadata.ts b/packages/twenty-server/src/modules/view/standard-objects/view.object-metadata.ts index b113db5409a..aff52692e63 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view.object-metadata.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view.object-metadata.ts @@ -7,18 +7,18 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { VIEW_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { ViewFieldObjectMetadata } from 'src/modules/view/standard-objects/view-field.object-metadata'; import { ViewFilterObjectMetadata } from 'src/modules/view/standard-objects/view-filter.object-metadata'; import { ViewSortObjectMetadata } from 'src/modules/view/standard-objects/view-sort.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.view, namePlural: 'views', labelSingular: 'View', @@ -26,10 +26,10 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: '(System) Views', icon: 'IconLayoutCollage', }) -@IsNotAuditLogged() -@IsSystem() -export class ViewObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +@WorkspaceIsSystem() +export class ViewObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: VIEW_STANDARD_FIELD_IDS.name, type: FieldMetadataType.TEXT, label: 'Name', @@ -37,7 +37,7 @@ export class ViewObjectMetadata extends BaseObjectMetadata { }) name: string; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_STANDARD_FIELD_IDS.objectMetadataId, type: FieldMetadataType.UUID, label: 'Object Metadata Id', @@ -45,7 +45,7 @@ export class ViewObjectMetadata extends BaseObjectMetadata { }) objectMetadataId: string; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_STANDARD_FIELD_IDS.type, type: FieldMetadataType.TEXT, label: 'Type', @@ -54,7 +54,7 @@ export class ViewObjectMetadata extends BaseObjectMetadata { }) type: string; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_STANDARD_FIELD_IDS.key, type: FieldMetadataType.SELECT, label: 'Key', @@ -62,10 +62,10 @@ export class ViewObjectMetadata extends BaseObjectMetadata { options: [{ value: 'INDEX', label: 'Index', position: 0, color: 'red' }], defaultValue: "'INDEX'", }) - @IsNullable() + @WorkspaceIsNullable() key: string; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_STANDARD_FIELD_IDS.icon, type: FieldMetadataType.TEXT, label: 'Icon', @@ -73,7 +73,7 @@ export class ViewObjectMetadata extends BaseObjectMetadata { }) icon: string; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_STANDARD_FIELD_IDS.kanbanFieldMetadataId, type: FieldMetadataType.TEXT, label: 'kanbanfieldMetadataId', @@ -81,16 +81,16 @@ export class ViewObjectMetadata extends BaseObjectMetadata { }) kanbanFieldMetadataId: string; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_STANDARD_FIELD_IDS.position, type: FieldMetadataType.POSITION, label: 'Position', description: 'View position', }) - @IsNullable() + @WorkspaceIsNullable() position: number; - @FieldMetadata({ + @WorkspaceField({ standardId: VIEW_STANDARD_FIELD_IDS.isCompact, type: FieldMetadataType.BOOLEAN, label: 'Compact View', @@ -99,48 +99,39 @@ export class ViewObjectMetadata extends BaseObjectMetadata { }) isCompact: boolean; - @FieldMetadata({ + @WorkspaceRelation({ standardId: VIEW_STANDARD_FIELD_IDS.viewFields, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'View Fields', description: 'View Fields', icon: 'IconTag', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => ViewFieldObjectMetadata, onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsNullable() + @WorkspaceIsNullable() viewFields: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: VIEW_STANDARD_FIELD_IDS.viewFilters, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'View Filters', description: 'View Filters', icon: 'IconFilterBolt', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => ViewFilterObjectMetadata, onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsNullable() + @WorkspaceIsNullable() viewFilters: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: VIEW_STANDARD_FIELD_IDS.viewSorts, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'View Sorts', description: 'View Sorts', icon: 'IconArrowsSort', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => ViewSortObjectMetadata, onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsNullable() + @WorkspaceIsNullable() viewSorts: Relation; } diff --git a/packages/twenty-server/src/modules/webhook/standard-objects/webhook.object-metadata.ts b/packages/twenty-server/src/modules/webhook/standard-objects/webhook.object-metadata.ts index 64de4a7d824..d4ebe3946ae 100644 --- a/packages/twenty-server/src/modules/webhook/standard-objects/webhook.object-metadata.ts +++ b/packages/twenty-server/src/modules/webhook/standard-objects/webhook.object-metadata.ts @@ -1,13 +1,13 @@ import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; import { WEBHOOK_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; -@ObjectMetadata({ +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.webhook, namePlural: 'webhooks', labelSingular: 'Webhook', @@ -15,10 +15,10 @@ import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync- description: 'A webhook', icon: 'IconRobot', }) -@IsNotAuditLogged() -@IsSystem() -export class WebhookObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsNotAuditLogged() +@WorkspaceIsSystem() +export class WebhookObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: WEBHOOK_STANDARD_FIELD_IDS.targetUrl, type: FieldMetadataType.TEXT, label: 'Target Url', @@ -27,7 +27,7 @@ export class WebhookObjectMetadata extends BaseObjectMetadata { }) targetUrl: string; - @FieldMetadata({ + @WorkspaceField({ standardId: WEBHOOK_STANDARD_FIELD_IDS.operation, type: FieldMetadataType.TEXT, label: 'Operation', diff --git a/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.object-metadata.ts b/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.object-metadata.ts index b94b40a3ee1..12ab73c8ac0 100644 --- a/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.object-metadata.ts +++ b/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.object-metadata.ts @@ -8,13 +8,8 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { WORKSPACE_MEMBER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { FieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/field-metadata.decorator'; -import { IsSystem } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-system.decorator'; -import { ObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/object-metadata.decorator'; -import { RelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/relation-metadata.decorator'; import { ActivityObjectMetadata } from 'src/modules/activity/standard-objects/activity.object-metadata'; import { AttachmentObjectMetadata } from 'src/modules/attachment/standard-objects/attachment.object-metadata'; -import { BaseObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects/base.object-metadata'; import { BlocklistObjectMetadata } from 'src/modules/connected-account/standard-objects/blocklist.object-metadata'; import { CalendarEventParticipantObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-event-participant.object-metadata'; import { CommentObjectMetadata } from 'src/modules/activity/standard-objects/comment.object-metadata'; @@ -22,12 +17,17 @@ import { CompanyObjectMetadata } from 'src/modules/company/standard-objects/comp import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata'; import { FavoriteObjectMetadata } from 'src/modules/favorite/standard-objects/favorite.object-metadata'; import { MessageParticipantObjectMetadata } from 'src/modules/messaging/standard-objects/message-participant.object-metadata'; -import { IsNullable } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-nullable.decorator'; import { TimelineActivityObjectMetadata } from 'src/modules/timeline/standard-objects/timeline-activity.object-metadata'; import { AuditLogObjectMetadata } from 'src/modules/timeline/standard-objects/audit-log.object-metadata'; -import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-metadata/decorators/is-not-audit-logged.decorator'; - -@ObjectMetadata({ +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-object.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; + +@WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.workspaceMember, namePlural: 'workspaceMembers', labelSingular: 'Workspace Member', @@ -35,10 +35,10 @@ import { IsNotAuditLogged } from 'src/engine/workspace-manager/workspace-sync-me description: 'A workspace member', icon: 'IconUserCircle', }) -@IsSystem() -@IsNotAuditLogged() -export class WorkspaceMemberObjectMetadata extends BaseObjectMetadata { - @FieldMetadata({ +@WorkspaceIsSystem() +@WorkspaceIsNotAuditLogged() +export class WorkspaceMemberObjectMetadata extends BaseWorkspaceEntity { + @WorkspaceField({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.name, type: FieldMetadataType.FULL_NAME, label: 'Name', @@ -47,7 +47,7 @@ export class WorkspaceMemberObjectMetadata extends BaseObjectMetadata { }) name: FullNameMetadata; - @FieldMetadata({ + @WorkspaceField({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.colorScheme, type: FieldMetadataType.TEXT, label: 'Color Scheme', @@ -57,7 +57,7 @@ export class WorkspaceMemberObjectMetadata extends BaseObjectMetadata { }) colorScheme: string; - @FieldMetadata({ + @WorkspaceField({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.locale, type: FieldMetadataType.TEXT, label: 'Language', @@ -67,7 +67,7 @@ export class WorkspaceMemberObjectMetadata extends BaseObjectMetadata { }) locale: string; - @FieldMetadata({ + @WorkspaceField({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.avatarUrl, type: FieldMetadataType.TEXT, label: 'Avatar Url', @@ -76,7 +76,7 @@ export class WorkspaceMemberObjectMetadata extends BaseObjectMetadata { }) avatarUrl: string; - @FieldMetadata({ + @WorkspaceField({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.userEmail, type: FieldMetadataType.TEXT, label: 'User Email', @@ -85,7 +85,7 @@ export class WorkspaceMemberObjectMetadata extends BaseObjectMetadata { }) userEmail: string; - @FieldMetadata({ + @WorkspaceField({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.userId, type: FieldMetadataType.UUID, label: 'User Id', @@ -95,184 +95,148 @@ export class WorkspaceMemberObjectMetadata extends BaseObjectMetadata { userId: string; // Relations - @FieldMetadata({ + @WorkspaceRelation({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.authoredActivities, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Authored activities', description: 'Activities created by the workspace member', icon: 'IconCheckbox', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => ActivityObjectMetadata, inverseSideFieldKey: 'author', onDelete: RelationOnDeleteAction.SET_NULL, }) authoredActivities: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.assignedActivities, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Assigned activities', description: 'Activities assigned to the workspace member', icon: 'IconCheckbox', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => ActivityObjectMetadata, inverseSideFieldKey: 'assignee', onDelete: RelationOnDeleteAction.SET_NULL, }) assignedActivities: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.favorites, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Favorites', description: 'Favorites linked to the workspace member', icon: 'IconHeart', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => FavoriteObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) favorites: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.accountOwnerForCompanies, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Account Owner For Companies', description: 'Account owner for companies', icon: 'IconBriefcase', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => CompanyObjectMetadata, inverseSideFieldKey: 'accountOwner', onDelete: RelationOnDeleteAction.SET_NULL, }) accountOwnerForCompanies: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.authoredAttachments, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Authored attachments', description: 'Attachments created by the workspace member', icon: 'IconFileImport', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => AttachmentObjectMetadata, inverseSideFieldKey: 'author', onDelete: RelationOnDeleteAction.SET_NULL, }) authoredAttachments: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.authoredComments, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Authored comments', description: 'Authored comments', icon: 'IconComment', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => CommentObjectMetadata, inverseSideFieldKey: 'author', onDelete: RelationOnDeleteAction.SET_NULL, }) authoredComments: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.connectedAccounts, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Connected accounts', description: 'Connected accounts', icon: 'IconAt', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => ConnectedAccountObjectMetadata, inverseSideFieldKey: 'accountOwner', onDelete: RelationOnDeleteAction.CASCADE, }) connectedAccounts: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.messageParticipants, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Message Participants', description: 'Message Participants', icon: 'IconUserCircle', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => MessageParticipantObjectMetadata, inverseSideFieldKey: 'workspaceMember', onDelete: RelationOnDeleteAction.SET_NULL, }) messageParticipants: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.blocklist, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Blocklist', description: 'Blocklisted handles', icon: 'IconForbid2', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => BlocklistObjectMetadata, inverseSideFieldKey: 'workspaceMember', onDelete: RelationOnDeleteAction.SET_NULL, }) blocklist: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.calendarEventParticipants, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Calendar Event Participants', description: 'Calendar Event Participants', icon: 'IconCalendar', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => CalendarEventParticipantObjectMetadata, inverseSideFieldKey: 'workspaceMember', onDelete: RelationOnDeleteAction.SET_NULL, }) calendarEventParticipants: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.timelineActivities, - type: FieldMetadataType.RELATION, + type: RelationMetadataType.ONE_TO_MANY, label: 'Events', description: 'Events linked to the workspace member', icon: 'IconTimelineEvent', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => TimelineActivityObjectMetadata, onDelete: RelationOnDeleteAction.CASCADE, }) - @IsNullable() - @IsSystem() + @WorkspaceIsNullable() + @WorkspaceIsSystem() timelineActivities: Relation; - @FieldMetadata({ + @WorkspaceRelation({ standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.auditLogs, - type: FieldMetadataType.RELATION, - label: 'Aud tLogs', + type: RelationMetadataType.ONE_TO_MANY, + label: 'Audit Logs', description: 'Audit Logs linked to the workspace member', icon: 'IconTimelineEvent', - }) - @RelationMetadata({ - type: RelationMetadataType.ONE_TO_MANY, inverseSideTarget: () => AuditLogObjectMetadata, onDelete: RelationOnDeleteAction.SET_NULL, }) - @IsNullable() - @IsSystem() + @WorkspaceIsNullable() + @WorkspaceIsSystem() auditLogs: Relation; } diff --git a/packages/twenty-server/src/utils/typed-reflect.ts b/packages/twenty-server/src/utils/typed-reflect.ts index 82c1e84a038..6e9fdb81938 100644 --- a/packages/twenty-server/src/utils/typed-reflect.ts +++ b/packages/twenty-server/src/utils/typed-reflect.ts @@ -1,24 +1,8 @@ import 'reflect-metadata'; -import { GateDecoratorParams } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/gate-decorator.interface'; -import { ReflectBaseCustomObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-custom-object-metadata.interface'; -import { ReflectDynamicRelationFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-computed-relation-field-metadata.interface'; -import { ReflectFieldMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-field-metadata.interface'; -import { ReflectObjectMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-object-metadata.interface'; -import { ReflectRelationMetadata } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/reflect-relation-metadata.interface'; import { Gate } from 'src/engine/twenty-orm/interfaces/gate.interface'; export interface ReflectMetadataTypeMap { - objectMetadata: ReflectObjectMetadata; - extendObjectMetadata: ReflectBaseCustomObjectMetadata; - fieldMetadataMap: ReflectFieldMetadata; - dynamicRelationFieldMetadataMap: ReflectDynamicRelationFieldMetadata; - reflectRelationMetadataCollection: ReflectRelationMetadata[]; - gate: GateDecoratorParams; - isNullable: true; - isSystem: true; - isAuditLogged: false; - ['workspace:is-nullable-metadata-args']: true; ['workspace:gate-metadata-args']: Gate; ['workspace:is-system-metadata-args']: true;