From 96eaf999a357b3e1e0e5895f4f77cf8bb90c6441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Magrin?= Date: Tue, 25 Jun 2024 17:24:26 +0200 Subject: [PATCH 1/9] feat: manually implement joinColumn --- .../timeline-calendar-event.service.ts | 12 +++---- .../workspace-join-column.decorator.ts | 13 ++++++++ .../workspace-relation.decorator.ts | 31 ++----------------- .../factories/entity-schema-column.factory.ts | 24 ++++++++++++-- .../factories/entity-schema.factory.ts | 3 ++ ...ce-join-columns-metadata-args.interface.ts | 17 ++++++++++ ...kspace-relation-metadata-args.interface.ts | 5 --- .../storage/metadata-args.storage.ts | 20 ++++++++++++ .../factories/standard-field.factory.ts | 25 +++++++++++++-- .../activity-target.workspace-entity.ts | 17 +++++++--- .../activity.workspace-entity.ts | 9 ++++-- .../comment.workspace-entity.ts | 9 ++++-- .../attachment.workspace-entity.ts | 21 ++++++++++--- ...ocklist-item-delete-calendar-events.job.ts | 9 ++---- ...eate-company-and-contact-after-sync.job.ts | 4 +-- ...calendar-event-find-many.pre-query.hook.ts | 4 +-- .../calendar-event-find-one.pre-query-hook.ts | 4 +-- .../google-calendar-sync.service.ts | 12 +++---- ...nnel-event-association.workspace-entity.ts | 9 ++++-- .../calendar-channel.workspace-entity.ts | 3 +- ...ndar-event-participant.workspace-entity.ts | 13 ++++++-- .../company.workspace-entity.ts | 5 ++- .../blocklist.workspace-entity.ts | 5 ++- .../connected-account.workspace-entity.ts | 3 +- .../favorite.workspace-entity.ts | 17 +++++++--- ...el-message-association.workspace-entity.ts | 13 ++++++-- .../message-channel.workspace-entity.ts | 5 ++- .../message-participant.workspace-entity.ts | 13 ++++++-- .../message.workspace-entity.ts | 5 ++- .../opportunity.workspace-entity.ts | 9 ++++-- .../person.workspace-entity.ts | 5 ++- .../audit-log.workspace-entity.ts | 5 ++- .../timeline-activity.workspace-entity.ts | 17 +++++++--- .../view-field.workspace-entity.ts | 5 ++- .../view-filter.workspace-entity.ts | 5 ++- .../view-sort.workspace-entity.ts | 5 ++- ...kspace-member-delete-one.pre-query.hook.ts | 8 ++--- .../twenty-server/src/utils/typed-reflect.ts | 1 - 38 files changed, 269 insertions(+), 121 deletions(-) create mode 100644 packages/twenty-server/src/engine/twenty-orm/decorators/workspace-join-column.decorator.ts create mode 100644 packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-join-columns-metadata-args.interface.ts diff --git a/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.service.ts b/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.service.ts index 1a2b903a9961..59013ab3d472 100644 --- a/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.service.ts +++ b/packages/twenty-server/src/engine/core-modules/calendar/timeline-calendar-event.service.ts @@ -31,9 +31,7 @@ export class TimelineCalendarEventService { const calendarEventIds = await this.calendarEventRepository.find({ where: { calendarEventParticipants: { - person: { - id: Any(personIds), - }, + personId: Any(personIds), }, }, select: { @@ -81,8 +79,8 @@ export class TimelineCalendarEventService { const participants = event.calendarEventParticipants.map( (participant) => ({ calendarEventId: event.id, - personId: participant.person?.id ?? null, - workspaceMemberId: participant.workspaceMember?.id ?? null, + personId: participant.personId ?? null, + workspaceMemberId: participant.workspaceMemberId ?? null, firstName: participant.person?.name?.firstName || participant.workspaceMember?.name.firstName || @@ -135,9 +133,7 @@ export class TimelineCalendarEventService { ): Promise { const personIds = await this.personRepository.find({ where: { - company: { - id: companyId, - }, + companyId, }, select: { id: true, diff --git a/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-join-column.decorator.ts b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-join-column.decorator.ts new file mode 100644 index 000000000000..4d1326f9bb8d --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/decorators/workspace-join-column.decorator.ts @@ -0,0 +1,13 @@ +import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; + +export function WorkspaceJoinColumn( + relationPropertyKey: string, +): PropertyDecorator { + return (object, propertyKey) => { + metadataArgsStorage.addJoinColumns({ + target: object.constructor, + relationName: relationPropertyKey, + joinColumn: propertyKey.toString(), + }); + }; +} 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 e20877f00eab..2ead553d039b 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 @@ -8,35 +8,19 @@ import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args import { TypedReflect } from 'src/utils/typed-reflect'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -interface WorkspaceBaseRelationOptions { +interface WorkspaceRelationOptions { standardId: string; label: string | ((objectMetadata: ObjectMetadataEntity) => string); description?: string | ((objectMetadata: ObjectMetadataEntity) => string); icon?: string; - type: TType; + type: RelationMetadataType; inverseSideTarget: () => ObjectType; inverseSideFieldKey?: keyof TClass; onDelete?: RelationOnDeleteAction; } -export interface WorkspaceManyToOneRelationOptions - extends WorkspaceBaseRelationOptions< - RelationMetadataType.MANY_TO_ONE | RelationMetadataType.ONE_TO_ONE, - TClass - > { - joinColumn?: string; -} - -export interface WorkspaceOtherRelationOptions - extends WorkspaceBaseRelationOptions< - RelationMetadataType.ONE_TO_MANY | RelationMetadataType.MANY_TO_MANY, - TClass - > {} - export function WorkspaceRelation( - options: - | WorkspaceManyToOneRelationOptions - | WorkspaceOtherRelationOptions, + options: WorkspaceRelationOptions, ): PropertyDecorator { return (object, propertyKey) => { const isPrimary = @@ -63,14 +47,6 @@ export function WorkspaceRelation( propertyKey.toString(), ); - let joinColumn: string | undefined; - - if ('joinColumn' in options) { - joinColumn = options.joinColumn - ? options.joinColumn - : `${propertyKey.toString()}Id`; - } - metadataArgsStorage.addRelations({ target: object.constructor, standardId: options.standardId, @@ -82,7 +58,6 @@ export function WorkspaceRelation( inverseSideTarget: options.inverseSideTarget, inverseSideFieldKey: options.inverseSideFieldKey as string | undefined, onDelete: options.onDelete, - joinColumn, isPrimary, isNullable, isSystem, diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts index 68b537d8634b..3e295f7e12c3 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts @@ -4,6 +4,7 @@ import { ColumnType, EntitySchemaColumnOptions } from 'typeorm'; import { WorkspaceFieldMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface'; import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface'; +import { WorkspaceJoinColumnsMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-join-columns-metadata-args.interface'; import { fieldMetadataTypeToColumnType } from 'src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util'; import { isEnumFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util'; @@ -12,6 +13,7 @@ import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-me import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; type EntitySchemaColumnMap = { [key: string]: EntitySchemaColumnOptions; @@ -22,6 +24,7 @@ export class EntitySchemaColumnFactory { create( fieldMetadataArgsCollection: WorkspaceFieldMetadataArgs[], relationMetadataArgsCollection: WorkspaceRelationMetadataArgs[], + joinColumnsMetadataArgsCollection: WorkspaceJoinColumnsMetadataArgs[], ): EntitySchemaColumnMap { let entitySchemaColumnMap: EntitySchemaColumnMap = {}; @@ -56,9 +59,24 @@ export class EntitySchemaColumnFactory { }; for (const relationMetadataArgs of relationMetadataArgsCollection) { - if (relationMetadataArgs.joinColumn) { - entitySchemaColumnMap[relationMetadataArgs.joinColumn] = { - name: relationMetadataArgs.joinColumn, + const joinColumnMetadataArgs = joinColumnsMetadataArgsCollection.find( + (joinColumnMetadataArgs) => + joinColumnMetadataArgs.relationName === relationMetadataArgs.name, + ); + + if ( + !joinColumnMetadataArgs && + (relationMetadataArgs.type === RelationMetadataType.ONE_TO_ONE || + relationMetadataArgs.type === RelationMetadataType.MANY_TO_ONE) + ) { + throw new Error( + `Join column not found for relation ${relationMetadataArgs.name}`, + ); + } + + if (joinColumnMetadataArgs) { + entitySchemaColumnMap[joinColumnMetadataArgs.joinColumn] = { + name: joinColumnMetadataArgs.joinColumn, type: 'uuid', nullable: relationMetadataArgs.isNullable, }; 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 326f5558a01a..ea489dde7510 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 @@ -23,12 +23,15 @@ export class EntitySchemaFactory { const fieldMetadataArgsCollection = metadataArgsStorage.filterFields(target); + const joinColumnsMetadataArgsCollection = + metadataArgsStorage.filterJoinColumns(target); const relationMetadataArgsCollection = metadataArgsStorage.filterRelations(target); const columns = this.entitySchemaColumnFactory.create( fieldMetadataArgsCollection, relationMetadataArgsCollection, + joinColumnsMetadataArgsCollection, ); const relations = this.entitySchemaRelationFactory.create( diff --git a/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-join-columns-metadata-args.interface.ts b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-join-columns-metadata-args.interface.ts new file mode 100644 index 000000000000..481f4a77ea2d --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/interfaces/workspace-join-columns-metadata-args.interface.ts @@ -0,0 +1,17 @@ +export interface WorkspaceJoinColumnsMetadataArgs { + /** + * Class to which relation is applied. + */ + // eslint-disable-next-line @typescript-eslint/ban-types + readonly target: Function; + + /** + * Relation name. + */ + readonly relationName: string; + + /** + * Relation label. + */ + readonly joinColumn: string; +} 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 911e9d78e8ed..861b1e7d44d4 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 @@ -62,11 +62,6 @@ export interface WorkspaceRelationMetadataArgs { */ readonly onDelete?: RelationOnDeleteAction; - /** - * Relation join column. - */ - readonly joinColumn?: string; - /** * Is primary field. */ 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 f228116b562d..77b038b335c7 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 @@ -6,6 +6,7 @@ import { WorkspaceEntityMetadataArgs } from 'src/engine/twenty-orm/interfaces/wo 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'; import { WorkspaceIndexMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-index-metadata-args.interface'; +import { WorkspaceJoinColumnsMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-join-columns-metadata-args.interface'; export class MetadataArgsStorage { private readonly entities: WorkspaceEntityMetadataArgs[] = []; @@ -15,6 +16,7 @@ export class MetadataArgsStorage { private readonly dynamicRelations: WorkspaceDynamicRelationMetadataArgs[] = []; private readonly indexes: WorkspaceIndexMetadataArgs[] = []; + private readonly joinColumns: WorkspaceJoinColumnsMetadataArgs[] = []; addEntities(...entities: WorkspaceEntityMetadataArgs[]): void { this.entities.push(...entities); @@ -44,6 +46,10 @@ export class MetadataArgsStorage { this.dynamicRelations.push(...dynamicRelations); } + addJoinColumns(...joinColumns: WorkspaceJoinColumnsMetadataArgs[]): void { + this.joinColumns.push(...joinColumns); + } + filterEntities( target: Function | string, ): WorkspaceEntityMetadataArgs | undefined; @@ -123,6 +129,20 @@ export class MetadataArgsStorage { return this.filterByTarget(this.dynamicRelations, target); } + filterJoinColumns( + target: Function | string, + ): WorkspaceJoinColumnsMetadataArgs[]; + + filterJoinColumns( + target: (Function | string)[], + ): WorkspaceJoinColumnsMetadataArgs[]; + + filterJoinColumns( + target: (Function | string) | (Function | string)[], + ): WorkspaceJoinColumnsMetadataArgs[] { + return this.filterByTarget(this.joinColumns, target); + } + protected filterByTarget( array: T[], target: (Function | string) | (Function | string)[], 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 07bb1ef059d2..8b359d1595ae 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 @@ -16,6 +16,7 @@ import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args 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'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; @Injectable() export class StandardFieldFactory { @@ -139,6 +140,15 @@ export class StandardFieldFactory { const foreignKeyStandardId = createDeterministicUuid( workspaceRelationMetadataArgs.standardId, ); + const joinColumnMetadataArgsCollection = + metadataArgsStorage.filterJoinColumns( + workspaceRelationMetadataArgs.target, + ); + const joinColumnMetadataArgs = joinColumnMetadataArgsCollection.find( + (joinColumnMetadataArgs) => + joinColumnMetadataArgs.relationName === + workspaceRelationMetadataArgs.name, + ); if ( isGatedAndNotEnabled( @@ -149,11 +159,22 @@ export class StandardFieldFactory { return []; } - if (workspaceRelationMetadataArgs.joinColumn) { + if ( + !joinColumnMetadataArgs && + (workspaceRelationMetadataArgs.type === + RelationMetadataType.MANY_TO_ONE || + workspaceRelationMetadataArgs.type === RelationMetadataType.ONE_TO_ONE) + ) { + throw new Error( + `Join column not found for relation ${workspaceRelationMetadataArgs.name}`, + ); + } + + if (joinColumnMetadataArgs) { fieldMetadataCollection.push({ type: FieldMetadataType.UUID, standardId: foreignKeyStandardId, - name: workspaceRelationMetadataArgs.joinColumn, + name: joinColumnMetadataArgs.joinColumn, label: `${workspaceRelationMetadataArgs.label} id (foreign key)`, description: `${workspaceRelationMetadataArgs.description} id foreign key`, icon: workspaceRelationMetadataArgs.icon, diff --git a/packages/twenty-server/src/modules/activity/standard-objects/activity-target.workspace-entity.ts b/packages/twenty-server/src/modules/activity/standard-objects/activity-target.workspace-entity.ts index a72330bfd201..dd2ef18cb94e 100644 --- a/packages/twenty-server/src/modules/activity/standard-objects/activity-target.workspace-entity.ts +++ b/packages/twenty-server/src/modules/activity/standard-objects/activity-target.workspace-entity.ts @@ -14,6 +14,7 @@ import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/works 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'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.activityTarget, @@ -31,52 +32,60 @@ export class ActivityTargetWorkspaceEntity extends BaseWorkspaceEntity { label: 'Activity', description: 'ActivityTarget activity', icon: 'IconNotes', - joinColumn: 'activityId', inverseSideTarget: () => ActivityWorkspaceEntity, inverseSideFieldKey: 'activityTargets', }) @WorkspaceIsNullable() activity: Relation | null; + @WorkspaceJoinColumn('activity') + activityId: string | null; + @WorkspaceRelation({ standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.person, type: RelationMetadataType.MANY_TO_ONE, label: 'Person', description: 'ActivityTarget person', icon: 'IconUser', - joinColumn: 'personId', inverseSideTarget: () => PersonWorkspaceEntity, inverseSideFieldKey: 'activityTargets', }) @WorkspaceIsNullable() person: Relation | null; + @WorkspaceJoinColumn('person') + personId: string | null; + @WorkspaceRelation({ standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.company, type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'ActivityTarget company', icon: 'IconBuildingSkyscraper', - joinColumn: 'companyId', inverseSideTarget: () => CompanyWorkspaceEntity, inverseSideFieldKey: 'activityTargets', }) @WorkspaceIsNullable() company: Relation | null; + @WorkspaceJoinColumn('company') + companyId: string | null; + @WorkspaceRelation({ standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.opportunity, type: RelationMetadataType.MANY_TO_ONE, label: 'Opportunity', description: 'ActivityTarget opportunity', icon: 'IconTargetArrow', - joinColumn: 'opportunityId', inverseSideTarget: () => OpportunityWorkspaceEntity, inverseSideFieldKey: 'activityTargets', }) @WorkspaceIsNullable() opportunity: Relation | null; + @WorkspaceJoinColumn('opportunity') + opportunityId: string | null; + @WorkspaceDynamicRelation({ type: RelationMetadataType.MANY_TO_ONE, argsFactory: (oppositeObjectMetadata) => ({ diff --git a/packages/twenty-server/src/modules/activity/standard-objects/activity.workspace-entity.ts b/packages/twenty-server/src/modules/activity/standard-objects/activity.workspace-entity.ts index d27fd026f5ed..f8d81dfebca2 100644 --- a/packages/twenty-server/src/modules/activity/standard-objects/activity.workspace-entity.ts +++ b/packages/twenty-server/src/modules/activity/standard-objects/activity.workspace-entity.ts @@ -17,6 +17,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field 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'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.activity, @@ -131,11 +132,13 @@ export class ActivityWorkspaceEntity extends BaseWorkspaceEntity { inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, inverseSideFieldKey: 'authoredActivities', onDelete: RelationOnDeleteAction.SET_NULL, - joinColumn: 'authorId', }) @WorkspaceIsNullable() author: Relation | null; + @WorkspaceJoinColumn('author') + authorId: string | null; + @WorkspaceRelation({ standardId: ACTIVITY_STANDARD_FIELD_IDS.assignee, label: 'Assignee', @@ -145,8 +148,10 @@ export class ActivityWorkspaceEntity extends BaseWorkspaceEntity { inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, inverseSideFieldKey: 'assignedActivities', onDelete: RelationOnDeleteAction.SET_NULL, - joinColumn: 'assigneeId', }) @WorkspaceIsNullable() assignee: Relation | null; + + @WorkspaceJoinColumn('assignee') + assigneeId: string | null; } diff --git a/packages/twenty-server/src/modules/activity/standard-objects/comment.workspace-entity.ts b/packages/twenty-server/src/modules/activity/standard-objects/comment.workspace-entity.ts index b198e36da399..a572f5d074ad 100644 --- a/packages/twenty-server/src/modules/activity/standard-objects/comment.workspace-entity.ts +++ b/packages/twenty-server/src/modules/activity/standard-objects/comment.workspace-entity.ts @@ -11,6 +11,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field 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'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.comment, @@ -37,21 +38,25 @@ export class CommentWorkspaceEntity extends BaseWorkspaceEntity { label: 'Author', description: 'Comment author', icon: 'IconCircleUser', - joinColumn: 'authorId', inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, inverseSideFieldKey: 'authoredComments', }) author: Relation; + @WorkspaceJoinColumn('author') + authorId: string; + @WorkspaceRelation({ standardId: COMMENT_STANDARD_FIELD_IDS.activity, type: RelationMetadataType.MANY_TO_ONE, label: 'Activity', description: 'Comment activity', icon: 'IconNotes', - joinColumn: 'activityId', inverseSideTarget: () => ActivityWorkspaceEntity, inverseSideFieldKey: 'comments', }) activity: Relation; + + @WorkspaceJoinColumn('activity') + activityId: string; } diff --git a/packages/twenty-server/src/modules/attachment/standard-objects/attachment.workspace-entity.ts b/packages/twenty-server/src/modules/attachment/standard-objects/attachment.workspace-entity.ts index 3b4b9f9afca1..a4ea0b2e7d14 100644 --- a/packages/twenty-server/src/modules/attachment/standard-objects/attachment.workspace-entity.ts +++ b/packages/twenty-server/src/modules/attachment/standard-objects/attachment.workspace-entity.ts @@ -18,6 +18,7 @@ import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metad 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'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.attachment, @@ -63,64 +64,74 @@ export class AttachmentWorkspaceEntity extends BaseWorkspaceEntity { label: 'Author', description: 'Attachment author', icon: 'IconCircleUser', - joinColumn: 'authorId', inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, inverseSideFieldKey: 'authoredAttachments', }) author: Relation; + @WorkspaceJoinColumn('author') + authorId: string; + @WorkspaceRelation({ standardId: ATTACHMENT_STANDARD_FIELD_IDS.activity, type: RelationMetadataType.MANY_TO_ONE, label: 'Activity', description: 'Attachment activity', icon: 'IconNotes', - joinColumn: 'activityId', inverseSideTarget: () => ActivityWorkspaceEntity, inverseSideFieldKey: 'attachments', }) @WorkspaceIsNullable() activity: Relation | null; + @WorkspaceJoinColumn('activity') + activityId: string | null; + @WorkspaceRelation({ standardId: ATTACHMENT_STANDARD_FIELD_IDS.person, type: RelationMetadataType.MANY_TO_ONE, label: 'Person', description: 'Attachment person', icon: 'IconUser', - joinColumn: 'personId', inverseSideTarget: () => PersonWorkspaceEntity, inverseSideFieldKey: 'attachments', }) @WorkspaceIsNullable() person: Relation | null; + @WorkspaceJoinColumn('person') + personId: string | null; + @WorkspaceRelation({ standardId: ATTACHMENT_STANDARD_FIELD_IDS.company, type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'Attachment company', icon: 'IconBuildingSkyscraper', - joinColumn: 'companyId', inverseSideTarget: () => CompanyWorkspaceEntity, inverseSideFieldKey: 'attachments', }) @WorkspaceIsNullable() company: Relation | null; + @WorkspaceJoinColumn('company') + companyId: string | null; + @WorkspaceRelation({ standardId: ATTACHMENT_STANDARD_FIELD_IDS.opportunity, type: RelationMetadataType.MANY_TO_ONE, label: 'Opportunity', description: 'Attachment opportunity', icon: 'IconBuildingSkyscraper', - joinColumn: 'opportunityId', inverseSideTarget: () => OpportunityWorkspaceEntity, inverseSideFieldKey: 'attachments', }) @WorkspaceIsNullable() opportunity: Relation | null; + @WorkspaceJoinColumn('opportunity') + opportunityId: string | null; + @WorkspaceDynamicRelation({ type: RelationMetadataType.MANY_TO_ONE, argsFactory: (oppositeObjectMetadata) => ({ diff --git a/packages/twenty-server/src/modules/calendar/jobs/blocklist-item-delete-calendar-events.job.ts b/packages/twenty-server/src/modules/calendar/jobs/blocklist-item-delete-calendar-events.job.ts index 6dc9eef1ceb1..3af5c2a476bd 100644 --- a/packages/twenty-server/src/modules/calendar/jobs/blocklist-item-delete-calendar-events.job.ts +++ b/packages/twenty-server/src/modules/calendar/jobs/blocklist-item-delete-calendar-events.job.ts @@ -70,12 +70,9 @@ export class BlocklistItemDeleteCalendarEventsJob { const calendarChannels = await this.calendarChannelRepository.find({ where: { connectedAccount: { - accountOwner: { - id: workspaceMemberId, - }, + accountOwnerId: workspaceMemberId, }, }, - relations: ['connectedAccount.accountOwner'], }); const calendarChannelIds = calendarChannels.map(({ id }) => id); @@ -88,9 +85,7 @@ export class BlocklistItemDeleteCalendarEventsJob { handle: isHandleDomain ? ILike(`%${handle}`) : handle, }, calendarChannelEventAssociations: { - calendarChannel: { - id: Any(calendarChannelIds), - }, + calendarChannelId: Any(calendarChannelIds), }, }, }); diff --git a/packages/twenty-server/src/modules/calendar/jobs/calendar-create-company-and-contact-after-sync.job.ts b/packages/twenty-server/src/modules/calendar/jobs/calendar-create-company-and-contact-after-sync.job.ts index 77cf65b231f9..3ca7266340ae 100644 --- a/packages/twenty-server/src/modules/calendar/jobs/calendar-create-company-and-contact-after-sync.job.ts +++ b/packages/twenty-server/src/modules/calendar/jobs/calendar-create-company-and-contact-after-sync.job.ts @@ -72,9 +72,7 @@ export class CalendarCreateCompanyAndContactAfterSyncJob { where: { calendarEvent: { calendarChannelEventAssociations: { - calendarChannel: { - id: calendarChannelId, - }, + calendarChannelId, }, calendarEventParticipants: { person: IsNull(), diff --git a/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts b/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts index d7c67d409efc..b46693fb1433 100644 --- a/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts @@ -34,9 +34,7 @@ export class CalendarEventFindManyPreQueryHook const calendarChannelCalendarEventAssociations = await this.calendarChannelEventAssociationRepository.find({ where: { - calendarEvent: { - id: payload?.filter?.id?.eq, - }, + calendarEventId: payload?.filter?.id?.eq, }, relations: ['calendarChannel.connectedAccount'], }); diff --git a/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts b/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts index 4deb02b2c97f..d95c3aaf5e9b 100644 --- a/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts +++ b/packages/twenty-server/src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts @@ -35,9 +35,7 @@ export class CalendarEventFindOnePreQueryHook const calendarChannelCalendarEventAssociations = await this.calendarChannelEventAssociationRepository.find({ where: { - calendarEvent: { - id: payload?.filter?.id?.eq, - }, + calendarEventId: payload?.filter?.id?.eq, }, relations: ['calendarChannel.connectedAccount'], }); diff --git a/packages/twenty-server/src/modules/calendar/services/google-calendar-sync/google-calendar-sync.service.ts b/packages/twenty-server/src/modules/calendar/services/google-calendar-sync/google-calendar-sync.service.ts index a7d653967ac4..3c1af9938225 100644 --- a/packages/twenty-server/src/modules/calendar/services/google-calendar-sync/google-calendar-sync.service.ts +++ b/packages/twenty-server/src/modules/calendar/services/google-calendar-sync/google-calendar-sync.service.ts @@ -496,13 +496,11 @@ export class GoogleCalendarSyncService { const existingCalendarEventParticipants = await this.calendarEventParticipantsRepository.find({ where: { - calendarEvent: { - id: Any( - participantsToUpdate - .map((participant) => participant.calendarEventId) - .filter(isDefined), - ), - }, + calendarEventId: Any( + participantsToUpdate + .map((participant) => participant.calendarEventId) + .filter(isDefined), + ), }, }); diff --git a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel-event-association.workspace-entity.ts b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel-event-association.workspace-entity.ts index bf1e82aa7210..fdae18bc8533 100644 --- a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel-event-association.workspace-entity.ts +++ b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel-event-association.workspace-entity.ts @@ -12,6 +12,7 @@ import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metad import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-channel.workspace-entity'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.calendarChannelEventAssociation, @@ -41,12 +42,14 @@ export class CalendarChannelEventAssociationWorkspaceEntity extends BaseWorkspac label: 'Channel ID', description: 'Channel ID', icon: 'IconCalendar', - joinColumn: 'calendarChannelId', inverseSideTarget: () => CalendarChannelWorkspaceEntity, inverseSideFieldKey: 'calendarChannelEventAssociations', }) calendarChannel: Relation; + @WorkspaceJoinColumn('calendarChannel') + calendarChannelId: string; + @WorkspaceRelation({ standardId: CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS.calendarEvent, @@ -54,9 +57,11 @@ export class CalendarChannelEventAssociationWorkspaceEntity extends BaseWorkspac label: 'Event ID', description: 'Event ID', icon: 'IconCalendar', - joinColumn: 'calendarEventId', inverseSideTarget: () => CalendarEventWorkspaceEntity, inverseSideFieldKey: 'calendarChannelEventAssociations', }) calendarEvent: Relation; + + @WorkspaceJoinColumn('calendarEvent') + calendarEventId: string; } diff --git a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel.workspace-entity.ts b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel.workspace-entity.ts index 3e63dcbe26da..d886865dd34b 100644 --- a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel.workspace-entity.ts +++ b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-channel.workspace-entity.ts @@ -16,6 +16,7 @@ import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/work 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 { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; export enum CalendarChannelVisibility { METADATA = 'METADATA', @@ -231,12 +232,12 @@ export class CalendarChannelWorkspaceEntity extends BaseWorkspaceEntity { label: 'Connected Account', description: 'Connected Account', icon: 'IconUserCircle', - joinColumn: 'connectedAccountId', inverseSideTarget: () => ConnectedAccountWorkspaceEntity, inverseSideFieldKey: 'calendarChannels', }) connectedAccount: Relation; + @WorkspaceJoinColumn('connectedAccount') connectedAccountId: string; @WorkspaceRelation({ diff --git a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-event-participant.workspace-entity.ts b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-event-participant.workspace-entity.ts index 6e6d81f2252e..3cf8f25b2e4a 100644 --- a/packages/twenty-server/src/modules/calendar/standard-objects/calendar-event-participant.workspace-entity.ts +++ b/packages/twenty-server/src/modules/calendar/standard-objects/calendar-event-participant.workspace-entity.ts @@ -14,6 +14,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field 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 { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; export enum CalendarEventParticipantResponseStatus { NEEDS_ACTION = 'NEEDS_ACTION', @@ -103,35 +104,41 @@ export class CalendarEventParticipantWorkspaceEntity extends BaseWorkspaceEntity label: 'Event ID', description: 'Event ID', icon: 'IconCalendar', - joinColumn: 'calendarEventId', inverseSideTarget: () => CalendarEventWorkspaceEntity, inverseSideFieldKey: 'calendarEventParticipants', }) calendarEvent: Relation; + @WorkspaceJoinColumn('calendarEvent') + calendarEventId: string; + @WorkspaceRelation({ standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.person, type: RelationMetadataType.MANY_TO_ONE, label: 'Person', description: 'Person', icon: 'IconUser', - joinColumn: 'personId', inverseSideTarget: () => PersonWorkspaceEntity, inverseSideFieldKey: 'calendarEventParticipants', }) @WorkspaceIsNullable() person: Relation | null; + @WorkspaceJoinColumn('person') + personId: string | null; + @WorkspaceRelation({ standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.workspaceMember, type: RelationMetadataType.MANY_TO_ONE, label: 'Workspace Member', description: 'Workspace Member', icon: 'IconUser', - joinColumn: 'workspaceMemberId', inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, inverseSideFieldKey: 'calendarEventParticipants', }) @WorkspaceIsNullable() workspaceMember: Relation | null; + + @WorkspaceJoinColumn('workspaceMember') + workspaceMemberId: string | null; } diff --git a/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts b/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts index 490a33919c28..c721f4b14ffe 100644 --- a/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts +++ b/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts @@ -22,6 +22,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field 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 { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.company, @@ -143,7 +144,6 @@ export class CompanyWorkspaceEntity extends BaseWorkspaceEntity { description: 'Your team member responsible for managing the company account', icon: 'IconUserCircle', - joinColumn: 'accountOwnerId', inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, inverseSideFieldKey: 'accountOwnerForCompanies', onDelete: RelationOnDeleteAction.SET_NULL, @@ -151,6 +151,9 @@ export class CompanyWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceIsNullable() accountOwner: Relation | null; + @WorkspaceJoinColumn('accountOwner') + accountOwnerId: string | null; + @WorkspaceRelation({ standardId: COMPANY_STANDARD_FIELD_IDS.activityTargets, type: RelationMetadataType.ONE_TO_MANY, diff --git a/packages/twenty-server/src/modules/connected-account/standard-objects/blocklist.workspace-entity.ts b/packages/twenty-server/src/modules/connected-account/standard-objects/blocklist.workspace-entity.ts index fce1a5eb201d..323f211a5e35 100644 --- a/packages/twenty-server/src/modules/connected-account/standard-objects/blocklist.workspace-entity.ts +++ b/packages/twenty-server/src/modules/connected-account/standard-objects/blocklist.workspace-entity.ts @@ -11,6 +11,7 @@ import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/work 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 { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.blocklist, @@ -38,9 +39,11 @@ export class BlocklistWorkspaceEntity extends BaseWorkspaceEntity { label: 'WorkspaceMember', description: 'WorkspaceMember', icon: 'IconCircleUser', - joinColumn: 'workspaceMemberId', inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, inverseSideFieldKey: 'blocklist', }) workspaceMember: Relation; + + @WorkspaceJoinColumn('workspaceMember') + workspaceMemberId: string; } diff --git a/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts b/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts index 5302d08ee9ee..3bcae0231b83 100644 --- a/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts +++ b/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts @@ -17,6 +17,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; export enum ConnectedAccountProvider { GOOGLE = 'google', @@ -94,12 +95,12 @@ export class ConnectedAccountWorkspaceEntity extends BaseWorkspaceEntity { label: 'Account Owner', description: 'Account Owner', icon: 'IconUserCircle', - joinColumn: 'accountOwnerId', inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, inverseSideFieldKey: 'connectedAccounts', }) accountOwner: Relation; + @WorkspaceJoinColumn('accountOwner') accountOwnerId: string; @WorkspaceRelation({ diff --git a/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts b/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts index 9995a4af7fdf..705c62d32f71 100644 --- a/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts +++ b/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts @@ -17,6 +17,7 @@ import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-re 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 { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.favorite, @@ -46,51 +47,59 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity { label: 'Workspace Member', description: 'Favorite workspace member', icon: 'IconCircleUser', - joinColumn: 'workspaceMemberId', inverseSideFieldKey: 'favorites', inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, }) workspaceMember: Relation; + @WorkspaceJoinColumn('workspaceMember') + workspaceMemberId: string; + @WorkspaceRelation({ standardId: FAVORITE_STANDARD_FIELD_IDS.person, type: RelationMetadataType.MANY_TO_ONE, label: 'Person', description: 'Favorite person', icon: 'IconUser', - joinColumn: 'personId', inverseSideTarget: () => PersonWorkspaceEntity, inverseSideFieldKey: 'favorites', }) @WorkspaceIsNullable() person: Relation | null; + @WorkspaceJoinColumn('person') + personId: string; + @WorkspaceRelation({ standardId: FAVORITE_STANDARD_FIELD_IDS.company, type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'Favorite company', icon: 'IconBuildingSkyscraper', - joinColumn: 'companyId', inverseSideTarget: () => CompanyWorkspaceEntity, inverseSideFieldKey: 'favorites', }) @WorkspaceIsNullable() company: Relation | null; + @WorkspaceJoinColumn('company') + companyId: string; + @WorkspaceRelation({ standardId: FAVORITE_STANDARD_FIELD_IDS.opportunity, type: RelationMetadataType.MANY_TO_ONE, label: 'Opportunity', description: 'Favorite opportunity', icon: 'IconTargetArrow', - joinColumn: 'opportunityId', inverseSideTarget: () => OpportunityWorkspaceEntity, inverseSideFieldKey: 'favorites', }) @WorkspaceIsNullable() opportunity: Relation | null; + @WorkspaceJoinColumn('opportunity') + opportunityId: string; + @WorkspaceDynamicRelation({ type: RelationMetadataType.MANY_TO_ONE, argsFactory: (oppositeObjectMetadata) => ({ diff --git a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts index 8792293d6e1a..0e0171766c54 100644 --- a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts @@ -14,6 +14,7 @@ import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metad import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageChannelMessageAssociation, @@ -55,26 +56,30 @@ export class MessageChannelMessageAssociationWorkspaceEntity extends BaseWorkspa label: 'Message Channel Id', description: 'Message Channel Id', icon: 'IconHash', - joinColumn: 'messageChannelId', inverseSideTarget: () => MessageChannelWorkspaceEntity, inverseSideFieldKey: 'messageChannelMessageAssociations', }) @WorkspaceIsNullable() messageChannel: Relation | null; + @WorkspaceJoinColumn('messageChannel') + messageChannelId: string; + @WorkspaceRelation({ standardId: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.message, type: RelationMetadataType.MANY_TO_ONE, label: 'Message Id', description: 'Message Id', icon: 'IconHash', - joinColumn: 'messageId', inverseSideTarget: () => MessageWorkspaceEntity, inverseSideFieldKey: 'messageChannelMessageAssociations', }) @WorkspaceIsNullable() message: Relation | null; + @WorkspaceJoinColumn('message') + messageId: string; + @WorkspaceRelation({ standardId: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.messageThread, @@ -82,10 +87,12 @@ export class MessageChannelMessageAssociationWorkspaceEntity extends BaseWorkspa label: 'Message Thread Id', description: 'Message Thread Id', icon: 'IconHash', - joinColumn: 'messageThreadId', inverseSideTarget: () => MessageThreadWorkspaceEntity, inverseSideFieldKey: 'messageChannelMessageAssociations', }) @WorkspaceIsNullable() messageThread: Relation | null; + + @WorkspaceJoinColumn('messageThread') + messageThreadId: string; } diff --git a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts index 9db9772d33b7..18e0be7fa50f 100644 --- a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts @@ -16,6 +16,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; export enum MessageChannelSyncStatus { // TO BE DEPRECATED @@ -300,13 +301,15 @@ export class MessageChannelWorkspaceEntity extends BaseWorkspaceEntity { label: 'Connected Account', description: 'Connected Account', icon: 'IconUserCircle', - joinColumn: 'connectedAccountId', inverseSideTarget: () => ConnectedAccountWorkspaceEntity, inverseSideFieldKey: 'messageChannels', }) connectedAccount: Relation; connectedAccountId: string; + @WorkspaceJoinColumn('connectedAccount') + connectedAccountId: string; + @WorkspaceRelation({ standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.messageChannelMessageAssociations, diff --git a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts index 32068791b135..0821bf32c012 100644 --- a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts @@ -14,6 +14,7 @@ import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-re 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 { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageParticipant, @@ -66,35 +67,41 @@ export class MessageParticipantWorkspaceEntity extends BaseWorkspaceEntity { label: 'Message', description: 'Message', icon: 'IconMessage', - joinColumn: 'messageId', inverseSideTarget: () => MessageWorkspaceEntity, inverseSideFieldKey: 'messageParticipants', }) message: Relation; + @WorkspaceJoinColumn('message') + messageId: string; + @WorkspaceRelation({ standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.person, type: RelationMetadataType.MANY_TO_ONE, label: 'Person', description: 'Person', icon: 'IconUser', - joinColumn: 'personId', inverseSideTarget: () => PersonWorkspaceEntity, inverseSideFieldKey: 'messageParticipants', }) @WorkspaceIsNullable() person: Relation | null; + @WorkspaceJoinColumn('person') + personId: string | null; + @WorkspaceRelation({ standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.workspaceMember, type: RelationMetadataType.MANY_TO_ONE, label: 'Workspace Member', description: 'Workspace member', icon: 'IconCircleUser', - joinColumn: 'workspaceMemberId', inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, inverseSideFieldKey: 'messageParticipants', }) @WorkspaceIsNullable() workspaceMember: Relation | null; + + @WorkspaceJoinColumn('workspaceMember') + workspaceMemberId: string | null; } diff --git a/packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts index 3b2c899ca26d..a9475a96d6ce 100644 --- a/packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts @@ -17,6 +17,7 @@ import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-re import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.message, @@ -86,7 +87,6 @@ export class MessageWorkspaceEntity extends BaseWorkspaceEntity { label: 'Message Thread Id', description: 'Message Thread Id', icon: 'IconHash', - joinColumn: 'messageThreadId', inverseSideTarget: () => MessageThreadWorkspaceEntity, inverseSideFieldKey: 'messages', onDelete: RelationOnDeleteAction.CASCADE, @@ -94,6 +94,9 @@ export class MessageWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceIsNullable() messageThread: Relation | null; + @WorkspaceJoinColumn('messageThread') + messageThreadId: string | null; + @WorkspaceRelation({ standardId: MESSAGE_STANDARD_FIELD_IDS.messageParticipants, type: RelationMetadataType.ONE_TO_MANY, diff --git a/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts b/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts index 859263261696..719ee7501f3a 100644 --- a/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts +++ b/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts @@ -21,6 +21,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field 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 { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.opportunity, @@ -110,7 +111,6 @@ export class OpportunityWorkspaceEntity extends BaseWorkspaceEntity { label: 'Point of Contact', description: 'Opportunity point of contact', icon: 'IconUser', - joinColumn: 'pointOfContactId', inverseSideTarget: () => PersonWorkspaceEntity, inverseSideFieldKey: 'pointOfContactForOpportunities', onDelete: RelationOnDeleteAction.SET_NULL, @@ -118,13 +118,15 @@ export class OpportunityWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceIsNullable() pointOfContact: Relation | null; + @WorkspaceJoinColumn('pointOfContact') + pointOfContactId: string | null; + @WorkspaceRelation({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.company, type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'Opportunity company', icon: 'IconBuildingSkyscraper', - joinColumn: 'companyId', inverseSideTarget: () => CompanyWorkspaceEntity, inverseSideFieldKey: 'opportunities', onDelete: RelationOnDeleteAction.SET_NULL, @@ -132,6 +134,9 @@ export class OpportunityWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceIsNullable() company: Relation | null; + @WorkspaceJoinColumn('company') + companyId: string | null; + @WorkspaceRelation({ standardId: OPPORTUNITY_STANDARD_FIELD_IDS.favorites, type: RelationMetadataType.ONE_TO_MANY, diff --git a/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts b/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts index 6340c84297e8..537a8300f8db 100644 --- a/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts +++ b/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts @@ -23,6 +23,7 @@ import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace- import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.person, @@ -127,13 +128,15 @@ export class PersonWorkspaceEntity extends BaseWorkspaceEntity { label: 'Company', description: 'Contact’s company', icon: 'IconBuildingSkyscraper', - joinColumn: 'companyId', inverseSideTarget: () => CompanyWorkspaceEntity, inverseSideFieldKey: 'people', }) @WorkspaceIsNullable() company: Relation | null; + @WorkspaceJoinColumn('company') + companyId: string | null; + @WorkspaceRelation({ standardId: PERSON_STANDARD_FIELD_IDS.pointOfContactForOpportunities, type: RelationMetadataType.ONE_TO_MANY, diff --git a/packages/twenty-server/src/modules/timeline/standard-objects/audit-log.workspace-entity.ts b/packages/twenty-server/src/modules/timeline/standard-objects/audit-log.workspace-entity.ts index b0b801db8c0f..26e51423c737 100644 --- a/packages/twenty-server/src/modules/timeline/standard-objects/audit-log.workspace-entity.ts +++ b/packages/twenty-server/src/modules/timeline/standard-objects/audit-log.workspace-entity.ts @@ -11,6 +11,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field 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 { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.auditLog, @@ -86,10 +87,12 @@ export class AuditLogWorkspaceEntity extends BaseWorkspaceEntity { label: 'Workspace Member', description: 'Event workspace member', icon: 'IconCircleUser', - joinColumn: 'workspaceMemberId', inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, inverseSideFieldKey: 'auditLogs', }) @WorkspaceIsNullable() workspaceMember: Relation | null; + + @WorkspaceJoinColumn('workspaceMember') + workspaceMemberId: string | null; } diff --git a/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts b/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts index 2e366378ff26..c104b5df8931 100644 --- a/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts +++ b/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts @@ -17,6 +17,7 @@ import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace- 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'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.timelineActivity, @@ -95,52 +96,60 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity { label: 'Workspace Member', description: 'Event workspace member', icon: 'IconCircleUser', - joinColumn: 'workspaceMemberId', inverseSideTarget: () => WorkspaceMemberWorkspaceEntity, inverseSideFieldKey: 'timelineActivities', }) @WorkspaceIsNullable() workspaceMember: Relation | null; + @WorkspaceJoinColumn('workspaceMember') + workspaceMemberId: string | null; + @WorkspaceRelation({ standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.person, type: RelationMetadataType.MANY_TO_ONE, label: 'Person', description: 'Event person', icon: 'IconUser', - joinColumn: 'personId', inverseSideTarget: () => PersonWorkspaceEntity, inverseSideFieldKey: 'timelineActivities', }) @WorkspaceIsNullable() person: Relation | null; + @WorkspaceJoinColumn('person') + personId: string | null; + @WorkspaceRelation({ standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.company, type: RelationMetadataType.MANY_TO_ONE, label: 'Company', description: 'Event company', icon: 'IconBuildingSkyscraper', - joinColumn: 'companyId', inverseSideTarget: () => CompanyWorkspaceEntity, inverseSideFieldKey: 'timelineActivities', }) @WorkspaceIsNullable() company: Relation | null; + @WorkspaceJoinColumn('company') + companyId: string | null; + @WorkspaceRelation({ standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.opportunity, type: RelationMetadataType.MANY_TO_ONE, label: 'Opportunity', description: 'Event opportunity', icon: 'IconTargetArrow', - joinColumn: 'opportunityId', inverseSideTarget: () => OpportunityWorkspaceEntity, inverseSideFieldKey: 'timelineActivities', }) @WorkspaceIsNullable() opportunity: Relation | null; + @WorkspaceJoinColumn('opportunity') + opportunityId: string | null; + @WorkspaceDynamicRelation({ type: RelationMetadataType.MANY_TO_ONE, argsFactory: (oppositeObjectMetadata) => ({ diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-field.workspace-entity.ts b/packages/twenty-server/src/modules/view/standard-objects/view-field.workspace-entity.ts index 474fedb8251f..e46ee8c0effd 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-field.workspace-entity.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-field.workspace-entity.ts @@ -10,6 +10,7 @@ import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-re 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 { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.viewField, @@ -69,8 +70,10 @@ export class ViewFieldWorkspaceEntity extends BaseWorkspaceEntity { icon: 'IconLayoutCollage', inverseSideTarget: () => ViewWorkspaceEntity, inverseSideFieldKey: 'viewFields', - joinColumn: 'viewId', }) @WorkspaceIsNullable() view?: ViewWorkspaceEntity | null; + + @WorkspaceJoinColumn('view') + viewId: string | null; } diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts b/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts index 5d0f5598fdae..149171e6eb7f 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts @@ -12,6 +12,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field 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 { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.viewFilter, @@ -63,10 +64,12 @@ export class ViewFilterWorkspaceEntity extends BaseWorkspaceEntity { label: 'View', description: 'View Filter related view', icon: 'IconLayoutCollage', - joinColumn: 'viewId', inverseSideTarget: () => ViewWorkspaceEntity, inverseSideFieldKey: 'viewFilters', }) @WorkspaceIsNullable() view: Relation | null; + + @WorkspaceJoinColumn('view') + viewId: string | null; } diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-sort.workspace-entity.ts b/packages/twenty-server/src/modules/view/standard-objects/view-sort.workspace-entity.ts index 6ecc1b4fe34c..5abc9848ed7d 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-sort.workspace-entity.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-sort.workspace-entity.ts @@ -12,6 +12,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field 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 { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.viewSort, @@ -48,10 +49,12 @@ export class ViewSortWorkspaceEntity extends BaseWorkspaceEntity { label: 'View', description: 'View Sort related view', icon: 'IconLayoutCollage', - joinColumn: 'viewId', inverseSideTarget: () => ViewWorkspaceEntity, inverseSideFieldKey: 'viewSorts', }) @WorkspaceIsNullable() view: Relation | null; + + @WorkspaceJoinColumn('view') + viewId: string | null; } diff --git a/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-delete-one.pre-query.hook.ts b/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-delete-one.pre-query.hook.ts index d5edd6ff5b32..e068da436be3 100644 --- a/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-delete-one.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/workspace-member/query-hooks/workspace-member-delete-one.pre-query.hook.ts @@ -27,15 +27,11 @@ export class WorkspaceMemberDeleteOnePreQueryHook const authorId = payload.id; await this.attachmentRepository.delete({ - author: { - id: authorId, - }, + authorId, }); await this.commentRepository.delete({ - author: { - id: authorId, - }, + authorId, }); } } diff --git a/packages/twenty-server/src/utils/typed-reflect.ts b/packages/twenty-server/src/utils/typed-reflect.ts index c8a25cee9365..6e9fdb819385 100644 --- a/packages/twenty-server/src/utils/typed-reflect.ts +++ b/packages/twenty-server/src/utils/typed-reflect.ts @@ -8,7 +8,6 @@ export interface ReflectMetadataTypeMap { ['workspace:is-system-metadata-args']: true; ['workspace:is-audit-logged-metadata-args']: false; ['workspace:is-primary-field-metadata-args']: true; - ['workspace:join-column']: true; } export class TypedReflect { From 5e42fe75708fb090a03b880ad3fcde1d12063e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Magrin?= Date: Tue, 25 Jun 2024 17:30:44 +0200 Subject: [PATCH 2/9] fix: missing part --- .../factories/entity-schema-relation.factory.ts | 16 ++++++++++++++-- .../factories/entity-schema.factory.ts | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts index d194879214f3..df7f8de2e2ef 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts @@ -4,6 +4,7 @@ import { EntitySchemaRelationOptions } from 'typeorm'; import { RelationType } from 'typeorm/metadata/types/RelationTypes'; import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface'; +import { WorkspaceJoinColumnsMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-join-columns-metadata-args.interface'; import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util'; import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; @@ -18,6 +19,7 @@ export class EntitySchemaRelationFactory { // eslint-disable-next-line @typescript-eslint/ban-types target: Function, relationMetadataArgsCollection: WorkspaceRelationMetadataArgs[], + joinColumnsMetadataArgsCollection: WorkspaceJoinColumnsMetadataArgs[], ): EntitySchemaRelationMap { const entitySchemaRelationMap: EntitySchemaRelationMap = {}; @@ -27,16 +29,26 @@ export class EntitySchemaRelationFactory { const oppositeObjectName = convertClassNameToObjectMetadataName( oppositeTarget.name, ); + const joinColumnsMetadataArgs = joinColumnsMetadataArgsCollection.find( + (joinColumnsMetadataArgs) => + joinColumnsMetadataArgs.relationName === relationMetadataArgs.name, + ); const relationType = this.getRelationType(relationMetadataArgs); + if (!joinColumnsMetadataArgs) { + throw new Error( + `Join columns metadata args are missing for relation ${relationMetadataArgs.name}`, + ); + } + entitySchemaRelationMap[relationMetadataArgs.name] = { type: relationType, target: oppositeObjectName, inverseSide: relationMetadataArgs.inverseSideFieldKey ?? objectName, - joinColumn: relationMetadataArgs.joinColumn + joinColumn: joinColumnsMetadataArgs.joinColumn ? { - name: relationMetadataArgs.joinColumn, + name: joinColumnsMetadataArgs.joinColumn, } : undefined, }; 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 ea489dde7510..75f63dcb221d 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 @@ -37,6 +37,7 @@ export class EntitySchemaFactory { const relations = this.entitySchemaRelationFactory.create( target, relationMetadataArgsCollection, + joinColumnsMetadataArgsCollection, ); const entitySchema = new EntitySchema({ From ef86814e6a77258046f7a7f4bf7c7240bc230329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Magrin?= Date: Tue, 25 Jun 2024 17:38:06 +0200 Subject: [PATCH 3/9] fix: remove old ObjectRecord type --- .../user/services/user.service.ts | 4 +--- .../types/object-record.ts | 20 ------------------ .../calendar-event-participant.listener.ts | 3 +-- .../calendar-event-participant.service.ts | 7 +++---- .../google-calendar-sync.service.ts | 5 ++--- .../modules/calendar/types/calendar-event.ts | 5 ++--- .../create-contact/create-contact.service.ts | 3 +-- .../create-company-and-contact.service.ts | 8 +++---- ...contacts-from-company-or-workspace.util.ts | 3 +-- .../repositories/blocklist.repository.ts | 7 +++---- .../connected-account.repository.ts | 21 +++++++++---------- ...-channel-message-association.repository.ts | 13 ++++++------ .../message-channel.repository.ts | 17 +++++++-------- .../message-participant.repository.ts | 3 +-- .../common/repositories/message.repository.ts | 7 +++---- .../messaging-error-handling.service.ts | 11 +++++----- .../messaging-message-participant.service.ts | 7 +++---- .../services/messaging-message.service.ts | 7 +++---- ...es-and-enqueue-contact-creation.service.ts | 8 +++---- ...g-gmail-full-message-list-fetch.service.ts | 5 ++--- ...messaging-gmail-messages-import.service.ts | 7 +++---- ...mail-partial-message-list-fetch.service.ts | 5 ++--- .../listeners/message-participant.listener.ts | 3 +-- .../person/repositories/person.repository.ts | 5 ++--- .../workspace-member.repository.ts | 7 +++---- 25 files changed, 72 insertions(+), 119 deletions(-) delete mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/types/object-record.ts diff --git a/packages/twenty-server/src/engine/core-modules/user/services/user.service.ts b/packages/twenty-server/src/engine/core-modules/user/services/user.service.ts index 47b90a4197a7..853bafed4156 100644 --- a/packages/twenty-server/src/engine/core-modules/user/services/user.service.ts +++ b/packages/twenty-server/src/engine/core-modules/user/services/user.service.ts @@ -12,7 +12,6 @@ import { TypeORMService } from 'src/database/typeorm/typeorm.service'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service'; export class UserService extends TypeOrmQueryService { @@ -113,8 +112,7 @@ export class UserService extends TypeOrmQueryService { `SELECT * FROM ${dataSourceMetadata.schema}."workspaceMember"`, ); const workspaceMember = workspaceMembers.filter( - (member: ObjectRecord) => - member.userId === userId, + (member: WorkspaceMemberWorkspaceEntity) => member.userId === userId, )?.[0]; assert(workspaceMember, 'WorkspaceMember not found'); 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 deleted file mode 100644 index 659f07256064..000000000000 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/types/object-record.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; - -type RelationKeys = { - [K in keyof T]: NonNullable extends BaseWorkspaceEntity ? K : never; -}[keyof T]; - -type ForeignKeyMap = { - [K in RelationKeys as `${K & string}Id`]: string; -}; - -type RecursiveObjectRecord = { - [P in keyof T]: NonNullable extends BaseWorkspaceEntity - ? ObjectRecord> & ForeignKeyMap> - : T[P]; -}; - -// TODO: We should get rid of that it's causing too much issues -// Some relations can be null or undefined because they're not mendatory and other cannot -// This utility type put as defined all the joinColumn, so it's not well typed -export type ObjectRecord = RecursiveObjectRecord & ForeignKeyMap; diff --git a/packages/twenty-server/src/modules/calendar/listeners/calendar-event-participant.listener.ts b/packages/twenty-server/src/modules/calendar/listeners/calendar-event-participant.listener.ts index 7f8e6e3c0e43..852b7919affa 100644 --- a/packages/twenty-server/src/modules/calendar/listeners/calendar-event-participant.listener.ts +++ b/packages/twenty-server/src/modules/calendar/listeners/calendar-event-participant.listener.ts @@ -10,7 +10,6 @@ import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/work import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-event-participant.workspace-entity'; import { TimelineActivityRepository } from 'src/modules/timeline/repositiories/timeline-activity.repository'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; @Injectable() export class CalendarEventParticipantListener { @@ -26,7 +25,7 @@ export class CalendarEventParticipantListener { public async handleCalendarEventParticipantMatchedEvent(payload: { workspaceId: string; workspaceMemberId: string; - calendarEventParticipants: ObjectRecord[]; + calendarEventParticipants: CalendarEventParticipantWorkspaceEntity[]; }): Promise { const calendarEventParticipants = payload.calendarEventParticipants ?? []; diff --git a/packages/twenty-server/src/modules/calendar/services/calendar-event-participant/calendar-event-participant.service.ts b/packages/twenty-server/src/modules/calendar/services/calendar-event-participant/calendar-event-participant.service.ts index dee6a2aeadb0..3d46165d021d 100644 --- a/packages/twenty-server/src/modules/calendar/services/calendar-event-participant/calendar-event-participant.service.ts +++ b/packages/twenty-server/src/modules/calendar/services/calendar-event-participant/calendar-event-participant.service.ts @@ -11,7 +11,6 @@ import { getFlattenedValuesAndValuesStringForBatchRawQuery } from 'src/modules/c import { CalendarEventParticipant } from 'src/modules/calendar/types/calendar-event'; import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-event-participant.workspace-entity'; import { AddPersonIdAndWorkspaceMemberIdService } from 'src/modules/calendar-messaging-participant/services/add-person-id-and-workspace-member-id/add-person-id-and-workspace-member-id.service'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; @@ -28,10 +27,10 @@ export class CalendarEventParticipantService { ) {} public async updateCalendarEventParticipantsAfterPeopleCreation( - createdPeople: ObjectRecord[], + createdPeople: PersonWorkspaceEntity[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const participants = await this.calendarEventParticipantRepository.find({ where: { handle: Any(createdPeople.map((person) => person.email)), @@ -88,7 +87,7 @@ export class CalendarEventParticipantService { calendarEventParticipants: CalendarEventParticipant[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { if (calendarEventParticipants.length === 0) { return []; } diff --git a/packages/twenty-server/src/modules/calendar/services/google-calendar-sync/google-calendar-sync.service.ts b/packages/twenty-server/src/modules/calendar/services/google-calendar-sync/google-calendar-sync.service.ts index 3c1af9938225..db6bfccb5175 100644 --- a/packages/twenty-server/src/modules/calendar/services/google-calendar-sync/google-calendar-sync.service.ts +++ b/packages/twenty-server/src/modules/calendar/services/google-calendar-sync/google-calendar-sync.service.ts @@ -37,7 +37,6 @@ import { } from 'src/modules/connected-account/auto-companies-and-contacts-creation/jobs/create-company-and-contact.job'; import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { isDefined } from 'src/utils/is-defined'; import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource'; import { InjectWorkspaceDatasource } from 'src/engine/twenty-orm/decorators/inject-workspace-datasource.decorator'; @@ -416,7 +415,7 @@ export class GoogleCalendarSyncService { eventExternalId: string; calendarChannelId: string; }[], - connectedAccount: ObjectRecord, + connectedAccount: ConnectedAccountWorkspaceEntity, calendarChannel: CalendarChannelWorkspaceEntity, workspaceId: string, ): Promise { @@ -431,7 +430,7 @@ export class GoogleCalendarSyncService { let startTime: number; let endTime: number; - const savedCalendarEventParticipantsToEmit: ObjectRecord[] = + const savedCalendarEventParticipantsToEmit: CalendarEventParticipantWorkspaceEntity[] = []; try { diff --git a/packages/twenty-server/src/modules/calendar/types/calendar-event.ts b/packages/twenty-server/src/modules/calendar/types/calendar-event.ts index c2d7bd596603..f727691c1d4d 100644 --- a/packages/twenty-server/src/modules/calendar/types/calendar-event.ts +++ b/packages/twenty-server/src/modules/calendar/types/calendar-event.ts @@ -1,9 +1,8 @@ import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-event-participant.workspace-entity'; import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-event.workspace-entity'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; export type CalendarEvent = Omit< - ObjectRecord, + CalendarEventWorkspaceEntity, | 'createdAt' | 'updatedAt' | 'calendarChannelEventAssociations' @@ -15,7 +14,7 @@ export type CalendarEvent = Omit< }; export type CalendarEventParticipant = Omit< - ObjectRecord, + CalendarEventParticipantWorkspaceEntity, | 'id' | 'createdAt' | 'updatedAt' diff --git a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/create-contact/create-contact.service.ts b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/create-contact/create-contact.service.ts index a8a121526b83..1a63e8cd9a7c 100644 --- a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/create-contact/create-contact.service.ts +++ b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/create-contact/create-contact.service.ts @@ -7,7 +7,6 @@ import { PersonRepository } from 'src/modules/person/repositories/person.reposit import { getFirstNameAndLastNameFromHandleAndDisplayName } from 'src/modules/calendar-messaging-participant/utils/get-first-name-and-last-name-from-handle-and-display-name.util'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; type ContactToCreate = { handle: string; @@ -55,7 +54,7 @@ export class CreateContactService { contactsToCreate: ContactToCreate[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { if (contactsToCreate.length === 0) return []; const formattedContacts = this.formatContacts(contactsToCreate); diff --git a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service.ts b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service.ts index abe0f2603a91..3238c094ab33 100644 --- a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service.ts +++ b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service.ts @@ -17,7 +17,6 @@ import { getUniqueContactsAndHandles } from 'src/modules/connected-account/auto- import { Contacts } from 'src/modules/connected-account/auto-companies-and-contacts-creation/types/contact.type'; import { CalendarEventParticipantService } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.service'; import { filterOutContactsFromCompanyOrWorkspace } from 'src/modules/connected-account/auto-companies-and-contacts-creation/utils/filter-out-contacts-from-company-or-workspace.util'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service'; import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-event-participant.workspace-entity'; @@ -46,7 +45,7 @@ export class CreateCompanyAndContactService { contactsToCreate: Contacts, workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { if (!contactsToCreate || contactsToCreate.length === 0) { return []; } @@ -136,9 +135,8 @@ export class CreateCompanyAndContactService { contactsToCreate: Contacts, workspaceId: string, ) { - let updatedMessageParticipants: ObjectRecord[] = - []; - let updatedCalendarEventParticipants: ObjectRecord[] = + let updatedMessageParticipants: MessageParticipantWorkspaceEntity[] = []; + let updatedCalendarEventParticipants: CalendarEventParticipantWorkspaceEntity[] = []; await this.workspaceDataSource?.transaction( diff --git a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/utils/filter-out-contacts-from-company-or-workspace.util.ts b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/utils/filter-out-contacts-from-company-or-workspace.util.ts index eadb0e9c134b..c746dabaea8b 100644 --- a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/utils/filter-out-contacts-from-company-or-workspace.util.ts +++ b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/utils/filter-out-contacts-from-company-or-workspace.util.ts @@ -1,12 +1,11 @@ import { getDomainNameFromHandle } from 'src/modules/calendar-messaging-participant/utils/get-domain-name-from-handle.util'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { Contacts } from 'src/modules/connected-account/auto-companies-and-contacts-creation/types/contact.type'; export function filterOutContactsFromCompanyOrWorkspace( contacts: Contacts, selfHandle: string, - workspaceMembers: ObjectRecord[], + workspaceMembers: WorkspaceMemberWorkspaceEntity[], ): Contacts { const selfDomainName = getDomainNameFromHandle(selfHandle); diff --git a/packages/twenty-server/src/modules/connected-account/repositories/blocklist.repository.ts b/packages/twenty-server/src/modules/connected-account/repositories/blocklist.repository.ts index 99ec3ecbb6a1..5b9108b687ea 100644 --- a/packages/twenty-server/src/modules/connected-account/repositories/blocklist.repository.ts +++ b/packages/twenty-server/src/modules/connected-account/repositories/blocklist.repository.ts @@ -3,7 +3,6 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; @Injectable() @@ -16,7 +15,7 @@ export class BlocklistRepository { id: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise | null> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -39,7 +38,7 @@ export class BlocklistRepository { workspaceMemberId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -56,7 +55,7 @@ export class BlocklistRepository { handle: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); diff --git a/packages/twenty-server/src/modules/connected-account/repositories/connected-account.repository.ts b/packages/twenty-server/src/modules/connected-account/repositories/connected-account.repository.ts index 1658befee36b..ce6fd5a16c6b 100644 --- a/packages/twenty-server/src/modules/connected-account/repositories/connected-account.repository.ts +++ b/packages/twenty-server/src/modules/connected-account/repositories/connected-account.repository.ts @@ -4,7 +4,6 @@ import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; @Injectable() export class ConnectedAccountRepository { @@ -15,7 +14,7 @@ export class ConnectedAccountRepository { public async getAll( workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -31,7 +30,7 @@ export class ConnectedAccountRepository { connectedAccountIds: string[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -47,7 +46,7 @@ export class ConnectedAccountRepository { workspaceMemberId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise[] | undefined> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -66,7 +65,7 @@ export class ConnectedAccountRepository { userId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise[] | undefined> { + ): Promise { const schemaExists = await this.workspaceDataSourceService.checkSchemaExists(workspaceId); @@ -102,7 +101,7 @@ export class ConnectedAccountRepository { workspaceMemberId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise[] | undefined> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -119,7 +118,7 @@ export class ConnectedAccountRepository { public async create( connectedAccount: Pick< - ObjectRecord, + ConnectedAccountWorkspaceEntity, | 'id' | 'handle' | 'provider' @@ -129,7 +128,7 @@ export class ConnectedAccountRepository { >, workspaceId: string, transactionManager?: EntityManager, - ): Promise> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -170,7 +169,7 @@ export class ConnectedAccountRepository { connectedAccountId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise | undefined> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -189,7 +188,7 @@ export class ConnectedAccountRepository { connectedAccountId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise> { + ): Promise { const connectedAccount = await this.getById( connectedAccountId, workspaceId, @@ -293,7 +292,7 @@ export class ConnectedAccountRepository { public async getConnectedAccountOrThrow( workspaceId: string, connectedAccountId: string, - ): Promise> { + ): Promise { const connectedAccount = await this.getById( connectedAccountId, workspaceId, diff --git a/packages/twenty-server/src/modules/messaging/common/repositories/message-channel-message-association.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message-channel-message-association.repository.ts index 8699a7670f3a..e9b0ffa0d56a 100644 --- a/packages/twenty-server/src/modules/messaging/common/repositories/message-channel-message-association.repository.ts +++ b/packages/twenty-server/src/modules/messaging/common/repositories/message-channel-message-association.repository.ts @@ -3,7 +3,6 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; @Injectable() @@ -17,7 +16,7 @@ export class MessageChannelMessageAssociationRepository { messageChannelId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -130,7 +129,7 @@ export class MessageChannelMessageAssociationRepository { messageChannelIds: string[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -183,7 +182,7 @@ export class MessageChannelMessageAssociationRepository { messageThreadExternalIds: string[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -200,7 +199,7 @@ export class MessageChannelMessageAssociationRepository { messageThreadExternalId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise | null> { + ): Promise { const existingMessageChannelMessageAssociations = await this.getByMessageThreadExternalIds( [messageThreadExternalId], @@ -222,7 +221,7 @@ export class MessageChannelMessageAssociationRepository { messageIds: string[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -239,7 +238,7 @@ export class MessageChannelMessageAssociationRepository { messageThreadId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); diff --git a/packages/twenty-server/src/modules/messaging/common/repositories/message-channel.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message-channel.repository.ts index f2fd69cab8c5..3e46454fb732 100644 --- a/packages/twenty-server/src/modules/messaging/common/repositories/message-channel.repository.ts +++ b/packages/twenty-server/src/modules/messaging/common/repositories/message-channel.repository.ts @@ -3,7 +3,6 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { MessageChannelWorkspaceEntity, MessageChannelSyncStatus, @@ -18,7 +17,7 @@ export class MessageChannelRepository { public async create( messageChannel: Pick< - ObjectRecord, + MessageChannelWorkspaceEntity, | 'id' | 'connectedAccountId' | 'type' @@ -72,7 +71,7 @@ export class MessageChannelRepository { public async getAll( workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -88,7 +87,7 @@ export class MessageChannelRepository { connectedAccountId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -103,7 +102,7 @@ export class MessageChannelRepository { public async getFirstByConnectedAccountIdOrFail( connectedAccountId: string, workspaceId: string, - ): Promise> { + ): Promise { const messageChannel = await this.getFirstByConnectedAccountId( connectedAccountId, workspaceId, @@ -122,7 +121,7 @@ export class MessageChannelRepository { connectedAccountId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise | undefined> { + ): Promise { const messageChannels = await this.getByConnectedAccountId( connectedAccountId, workspaceId, @@ -136,7 +135,7 @@ export class MessageChannelRepository { ids: string[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -152,7 +151,7 @@ export class MessageChannelRepository { id: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -171,7 +170,7 @@ export class MessageChannelRepository { workspaceMemberId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); diff --git a/packages/twenty-server/src/modules/messaging/common/repositories/message-participant.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message-participant.repository.ts index 7d6515ae4a3b..2cb2214f1168 100644 --- a/packages/twenty-server/src/modules/messaging/common/repositories/message-participant.repository.ts +++ b/packages/twenty-server/src/modules/messaging/common/repositories/message-participant.repository.ts @@ -3,7 +3,6 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; import { ParticipantWithId } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; @@ -17,7 +16,7 @@ export class MessageParticipantRepository { handles: string[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); diff --git a/packages/twenty-server/src/modules/messaging/common/repositories/message.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message.repository.ts index ed75638c1f01..5f1d3eb25a4c 100644 --- a/packages/twenty-server/src/modules/messaging/common/repositories/message.repository.ts +++ b/packages/twenty-server/src/modules/messaging/common/repositories/message.repository.ts @@ -3,7 +3,6 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; @Injectable() @@ -40,7 +39,7 @@ export class MessageRepository { headerMessageId: string, workspaceId: string, transactionManager?: EntityManager, - ): Promise | null> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -62,7 +61,7 @@ export class MessageRepository { messageIds: string[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -94,7 +93,7 @@ export class MessageRepository { messageThreadIds: string[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); diff --git a/packages/twenty-server/src/modules/messaging/common/services/messaging-error-handling.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-error-handling.service.ts index fb3c7b99d21c..f17e56232dfe 100644 --- a/packages/twenty-server/src/modules/messaging/common/services/messaging-error-handling.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-error-handling.service.ts @@ -3,7 +3,6 @@ import { Injectable } from '@nestjs/common'; import snakeCase from 'lodash.snakecase'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service'; @@ -36,7 +35,7 @@ export class MessagingErrorHandlingService { public async handleGmailError( error: GmailError, syncStep: SyncStep, - messageChannel: ObjectRecord, + messageChannel: MessageChannelWorkspaceEntity, workspaceId: string, ): Promise { const { code, reason } = error; @@ -141,7 +140,7 @@ export class MessagingErrorHandlingService { private async handleRateLimitExceeded( error: GmailError, syncStep: SyncStep, - messageChannel: ObjectRecord, + messageChannel: MessageChannelWorkspaceEntity, workspaceId: string, ): Promise { await this.messagingTelemetryService.track({ @@ -195,7 +194,7 @@ export class MessagingErrorHandlingService { private async handleInsufficientPermissions( error: GmailError, syncStep: SyncStep, - messageChannel: ObjectRecord, + messageChannel: MessageChannelWorkspaceEntity, workspaceId: string, ): Promise { await this.messagingTelemetryService.track({ @@ -226,7 +225,7 @@ export class MessagingErrorHandlingService { private async handleNotFound( error: GmailError, syncStep: SyncStep, - messageChannel: ObjectRecord, + messageChannel: MessageChannelWorkspaceEntity, workspaceId: string, ): Promise { if (syncStep === 'messages-import') { @@ -248,7 +247,7 @@ export class MessagingErrorHandlingService { } private async throttle( - messageChannel: ObjectRecord, + messageChannel: MessageChannelWorkspaceEntity, workspaceId: string, ): Promise { await this.messageChannelRepository.incrementThrottleFailureCount( diff --git a/packages/twenty-server/src/modules/messaging/common/services/messaging-message-participant.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-message-participant.service.ts index 527a3951c2e7..625191061320 100644 --- a/packages/twenty-server/src/modules/messaging/common/services/messaging-message-participant.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-message-participant.service.ts @@ -9,7 +9,6 @@ import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/perso import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; import { getFlattenedValuesAndValuesStringForBatchRawQuery } from 'src/modules/calendar/utils/get-flattened-values-and-values-string-for-batch-raw-query.util'; import { AddPersonIdAndWorkspaceMemberIdService } from 'src/modules/calendar-messaging-participant/services/add-person-id-and-workspace-member-id/add-person-id-and-workspace-member-id.service'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { MessageParticipantRepository } from 'src/modules/messaging/common/repositories/message-participant.repository'; import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; import { ParticipantWithMessageId } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; @@ -29,10 +28,10 @@ export class MessagingMessageParticipantService { ) {} public async updateMessageParticipantsAfterPeopleCreation( - createdPeople: ObjectRecord[], + createdPeople: PersonWorkspaceEntity[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const participants = await this.messageParticipantRepository.getByHandles( createdPeople.map((person) => person.email), workspaceId, @@ -87,7 +86,7 @@ export class MessagingMessageParticipantService { participants: ParticipantWithMessageId[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { if (!participants) return []; const dataSourceSchema = diff --git a/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts index 4b475d095d7d..fa0d62425d3a 100644 --- a/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts @@ -4,7 +4,6 @@ import { DataSource, EntityManager } from 'typeorm'; import { v4 } from 'uuid'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; @@ -39,7 +38,7 @@ export class MessagingMessageService { public async saveMessagesWithinTransaction( messages: GmailMessage[], - connectedAccount: ObjectRecord, + connectedAccount: ConnectedAccountWorkspaceEntity, gmailMessageChannelId: string, workspaceId: string, transactionManager: EntityManager, @@ -99,7 +98,7 @@ export class MessagingMessageService { public async saveMessages( messages: GmailMessage[], workspaceDataSource: DataSource, - connectedAccount: ObjectRecord, + connectedAccount: ConnectedAccountWorkspaceEntity, gmailMessageChannelId: string, workspaceId: string, ): Promise> { @@ -191,7 +190,7 @@ export class MessagingMessageService { private async saveMessageOrReturnExistingMessage( message: GmailMessage, messageThreadId: string, - connectedAccount: ObjectRecord, + connectedAccount: ConnectedAccountWorkspaceEntity, workspaceId: string, manager: EntityManager, ): Promise { diff --git a/packages/twenty-server/src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service.ts index 1493acb8a559..16f9a32bb25c 100644 --- a/packages/twenty-server/src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service.ts @@ -7,7 +7,6 @@ import { EntityManager, Repository } from 'typeorm'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { CreateCompanyAndContactJobData, @@ -43,8 +42,8 @@ export class MessagingSaveMessagesAndEnqueueContactCreationService { async saveMessagesAndEnqueueContactCreationJob( messagesToSave: GmailMessage[], - messageChannel: ObjectRecord, - connectedAccount: ObjectRecord, + messageChannel: MessageChannelWorkspaceEntity, + connectedAccount: ConnectedAccountWorkspaceEntity, workspaceId: string, ) { const workspaceDataSource = @@ -62,8 +61,7 @@ export class MessagingSaveMessagesAndEnqueueContactCreationService { const isContactCreationForSentAndReceivedEmailsEnabled = isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag?.value; - let savedMessageParticipants: ObjectRecord[] = - []; + let savedMessageParticipants: MessageParticipantWorkspaceEntity[] = []; const participantsWithMessageId = await workspaceDataSource?.transaction( async (transactionManager: EntityManager) => { diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service.ts index 079baf1ac9cf..8f870751bcab 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service.ts @@ -9,7 +9,6 @@ import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decora import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; @@ -50,8 +49,8 @@ export class MessagingGmailFullMessageListFetchService { ) {} public async processMessageListFetch( - messageChannel: ObjectRecord, - connectedAccount: ObjectRecord, + messageChannel: MessageChannelWorkspaceEntity, + connectedAccount: ConnectedAccountWorkspaceEntity, workspaceId: string, ) { await this.messagingChannelSyncStatusService.markAsMessagesListFetchOngoing( diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service.ts index 083ff2d522af..cd3ba81eddac 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service.ts @@ -4,7 +4,6 @@ import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/s import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service'; import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; @@ -44,8 +43,8 @@ export class MessagingGmailMessagesImportService { ) {} async processMessageBatchImport( - messageChannel: ObjectRecord, - connectedAccount: ObjectRecord, + messageChannel: MessageChannelWorkspaceEntity, + connectedAccount: ConnectedAccountWorkspaceEntity, workspaceId: string, ) { if ( @@ -185,7 +184,7 @@ export class MessagingGmailMessagesImportService { } private async trackMessageImportCompleted( - messageChannel: ObjectRecord, + messageChannel: MessageChannelWorkspaceEntity, workspaceId: string, ) { await this.messagingTelemetryService.track({ diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service.ts index 654150d5b1da..63c2fa84b6df 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service.ts @@ -7,7 +7,6 @@ import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/s import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; @@ -41,8 +40,8 @@ export class MessagingGmailPartialMessageListFetchService { ) {} public async processMessageListFetch( - messageChannel: ObjectRecord, - connectedAccount: ObjectRecord, + messageChannel: MessageChannelWorkspaceEntity, + connectedAccount: ConnectedAccountWorkspaceEntity, workspaceId: string, ): Promise { await this.messagingChannelSyncStatusService.markAsMessagesListFetchOngoing( diff --git a/packages/twenty-server/src/modules/messaging/message-participants-manager/listeners/message-participant.listener.ts b/packages/twenty-server/src/modules/messaging/message-participants-manager/listeners/message-participant.listener.ts index 346dcf64fb59..a2fd781c1e07 100644 --- a/packages/twenty-server/src/modules/messaging/message-participants-manager/listeners/message-participant.listener.ts +++ b/packages/twenty-server/src/modules/messaging/message-participants-manager/listeners/message-participant.listener.ts @@ -9,7 +9,6 @@ import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repos import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; import { TimelineActivityRepository } from 'src/modules/timeline/repositiories/timeline-activity.repository'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; @Injectable() @@ -26,7 +25,7 @@ export class MessageParticipantListener { public async handleMessageParticipantMatched(payload: { workspaceId: string; workspaceMemberId: string; - messageParticipants: ObjectRecord[]; + messageParticipants: MessageParticipantWorkspaceEntity[]; }): Promise { const messageParticipants = payload.messageParticipants ?? []; diff --git a/packages/twenty-server/src/modules/person/repositories/person.repository.ts b/packages/twenty-server/src/modules/person/repositories/person.repository.ts index 57e1464fc955..df6af48a9bcb 100644 --- a/packages/twenty-server/src/modules/person/repositories/person.repository.ts +++ b/packages/twenty-server/src/modules/person/repositories/person.repository.ts @@ -3,7 +3,6 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; import { getFlattenedValuesAndValuesStringForBatchRawQuery } from 'src/modules/calendar/utils/get-flattened-values-and-values-string-for-batch-raw-query.util'; @@ -17,7 +16,7 @@ export class PersonRepository { emails: string[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -56,7 +55,7 @@ export class PersonRepository { }[], workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); diff --git a/packages/twenty-server/src/modules/workspace-member/repositories/workspace-member.repository.ts b/packages/twenty-server/src/modules/workspace-member/repositories/workspace-member.repository.ts index c67c5e66fcec..115ab85f3a70 100644 --- a/packages/twenty-server/src/modules/workspace-member/repositories/workspace-member.repository.ts +++ b/packages/twenty-server/src/modules/workspace-member/repositories/workspace-member.repository.ts @@ -4,7 +4,6 @@ import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; @Injectable() export class WorkspaceMemberRepository { @@ -15,7 +14,7 @@ export class WorkspaceMemberRepository { public async getByIds( userIds: string[], workspaceId: string, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -45,7 +44,7 @@ export class WorkspaceMemberRepository { public async getByIdOrFail( userId: string, workspaceId: string, - ): Promise> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); @@ -68,7 +67,7 @@ export class WorkspaceMemberRepository { public async getAllByWorkspaceId( workspaceId: string, transactionManager?: EntityManager, - ): Promise[]> { + ): Promise { const dataSourceSchema = this.workspaceDataSourceService.getSchemaName(workspaceId); From a904261fc5dd139692a8c055cd4a6e5754dacbdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Magrin?= Date: Tue, 25 Jun 2024 17:40:24 +0200 Subject: [PATCH 4/9] fix: nullability check --- .../messaging/common/services/messaging-message.service.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts index fa0d62425d3a..cb954a325fe0 100644 --- a/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts @@ -152,6 +152,12 @@ export class MessagingMessageService { manager, ); + if (!savedOrExistingMessageThreadId) { + throw new Error( + `No message thread found for message ${message.headerMessageId} in workspace ${workspaceId} in saveMessages`, + ); + } + const savedOrExistingMessageId = await this.saveMessageOrReturnExistingMessage( message, From 5b127cac12ef634c1c9577e5275abd2968f87582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Magrin?= Date: Wed, 26 Jun 2024 09:33:58 +0200 Subject: [PATCH 5/9] fix: nullability check --- .../messaging/common/services/messaging-message.service.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts index cb954a325fe0..e27c5b3671ee 100644 --- a/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts @@ -67,6 +67,12 @@ export class MessagingMessageService { transactionManager, ); + if (!savedOrExistingMessageThreadId) { + throw new Error( + `No message thread found for message ${message.headerMessageId} in workspace ${workspaceId} in saveMessages`, + ); + } + const savedOrExistingMessageId = await this.saveMessageOrReturnExistingMessage( message, From 21821d5009dd76d1c044d8bc6333e4328eab8268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Magrin?= Date: Wed, 26 Jun 2024 15:27:34 +0200 Subject: [PATCH 6/9] feat: better join columns errors --- .../factories/entity-schema-column.factory.ts | 24 ++----- .../entity-schema-relation.factory.ts | 20 ++---- .../twenty-orm/utils/get-join-column.util.ts | 69 +++++++++++++++++++ .../factories/standard-field.factory.ts | 24 ++----- 4 files changed, 89 insertions(+), 48 deletions(-) create mode 100644 packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts index 3e295f7e12c3..83106f92fa68 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-column.factory.ts @@ -13,7 +13,7 @@ import { computeCompositeColumnName } from 'src/engine/metadata-modules/field-me import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util'; import { compositeTypeDefintions } from 'src/engine/metadata-modules/field-metadata/composite-types'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { getJoinColumn } from 'src/engine/twenty-orm/utils/get-join-column.util'; type EntitySchemaColumnMap = { [key: string]: EntitySchemaColumnOptions; @@ -59,24 +59,14 @@ export class EntitySchemaColumnFactory { }; for (const relationMetadataArgs of relationMetadataArgsCollection) { - const joinColumnMetadataArgs = joinColumnsMetadataArgsCollection.find( - (joinColumnMetadataArgs) => - joinColumnMetadataArgs.relationName === relationMetadataArgs.name, + const joinColumn = getJoinColumn( + joinColumnsMetadataArgsCollection, + relationMetadataArgs, ); - if ( - !joinColumnMetadataArgs && - (relationMetadataArgs.type === RelationMetadataType.ONE_TO_ONE || - relationMetadataArgs.type === RelationMetadataType.MANY_TO_ONE) - ) { - throw new Error( - `Join column not found for relation ${relationMetadataArgs.name}`, - ); - } - - if (joinColumnMetadataArgs) { - entitySchemaColumnMap[joinColumnMetadataArgs.joinColumn] = { - name: joinColumnMetadataArgs.joinColumn, + if (joinColumn) { + entitySchemaColumnMap[joinColumn] = { + name: joinColumn, type: 'uuid', nullable: relationMetadataArgs.isNullable, }; diff --git a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts index df7f8de2e2ef..bc83b460b26a 100644 --- a/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts +++ b/packages/twenty-server/src/engine/twenty-orm/factories/entity-schema-relation.factory.ts @@ -8,6 +8,7 @@ import { WorkspaceJoinColumnsMetadataArgs } from 'src/engine/twenty-orm/interfac import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util'; import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { getJoinColumn } from 'src/engine/twenty-orm/utils/get-join-column.util'; type EntitySchemaRelationMap = { [key: string]: EntitySchemaRelationOptions; @@ -29,26 +30,19 @@ export class EntitySchemaRelationFactory { const oppositeObjectName = convertClassNameToObjectMetadataName( oppositeTarget.name, ); - const joinColumnsMetadataArgs = joinColumnsMetadataArgsCollection.find( - (joinColumnsMetadataArgs) => - joinColumnsMetadataArgs.relationName === relationMetadataArgs.name, - ); - const relationType = this.getRelationType(relationMetadataArgs); - - if (!joinColumnsMetadataArgs) { - throw new Error( - `Join columns metadata args are missing for relation ${relationMetadataArgs.name}`, - ); - } + const joinColumn = getJoinColumn( + joinColumnsMetadataArgsCollection, + relationMetadataArgs, + ); entitySchemaRelationMap[relationMetadataArgs.name] = { type: relationType, target: oppositeObjectName, inverseSide: relationMetadataArgs.inverseSideFieldKey ?? objectName, - joinColumn: joinColumnsMetadataArgs.joinColumn + joinColumn: joinColumn ? { - name: joinColumnsMetadataArgs.joinColumn, + name: joinColumn, } : undefined, }; diff --git a/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts b/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts new file mode 100644 index 000000000000..1f94e232eee1 --- /dev/null +++ b/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts @@ -0,0 +1,69 @@ +import { WorkspaceJoinColumnsMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-join-columns-metadata-args.interface'; +import { WorkspaceRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-relation-metadata-args.interface'; + +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage'; + +export const getJoinColumn = ( + joinColumnsMetadataArgsCollection: WorkspaceJoinColumnsMetadataArgs[], + relationMetadataArgs: WorkspaceRelationMetadataArgs, +): string | null => { + if ( + relationMetadataArgs.type === RelationMetadataType.ONE_TO_MANY || + relationMetadataArgs.type === RelationMetadataType.MANY_TO_MANY + ) { + return null; + } + + const filteredJoinColumnsMetadataArgsCollection = + joinColumnsMetadataArgsCollection.filter( + (joinColumnsMetadataArgs) => + joinColumnsMetadataArgs.relationName === relationMetadataArgs.name, + ); + + // If we're in a ONE_TO_ONE relation and there are no join columns, we need to find the join column on the inverse side + if ( + relationMetadataArgs.type === RelationMetadataType.ONE_TO_ONE && + filteredJoinColumnsMetadataArgsCollection.length === 0 + ) { + const inverseSideTarget = relationMetadataArgs.inverseSideTarget(); + const inverseSideJoinColumnsMetadataArgsCollection = + metadataArgsStorage.filterJoinColumns(inverseSideTarget); + const inverseSideRelationMetadataArgsCollection = + metadataArgsStorage.filterRelations(inverseSideTarget); + const inverseSideRelationMetadataArgs = + inverseSideRelationMetadataArgsCollection.find( + (inverseSideRelationMetadataArgs) => + inverseSideRelationMetadataArgs.inverseSideFieldKey === + relationMetadataArgs.name, + ); + + if (!inverseSideRelationMetadataArgs) { + throw new Error( + `Inverse side relation metadata args are missing for relation ${relationMetadataArgs.name}`, + ); + } + + return getJoinColumn( + inverseSideJoinColumnsMetadataArgsCollection, + inverseSideRelationMetadataArgs, + ); + } + + // Check if there are multiple join columns for the relation + if (filteredJoinColumnsMetadataArgsCollection.length > 1) { + throw new Error( + `Multiple join columns metadata args found for relation ${relationMetadataArgs.name}`, + ); + } + + const joinColumnsMetadataArgs = filteredJoinColumnsMetadataArgsCollection[0]; + + if (!joinColumnsMetadataArgs) { + throw new Error( + `Join columns metadata args are missing for relation ${relationMetadataArgs.name}`, + ); + } + + return joinColumnsMetadataArgs.joinColumn; +}; 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 8b359d1595ae..8d714e19b299 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 @@ -16,7 +16,7 @@ import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args 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'; -import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { getJoinColumn } from 'src/engine/twenty-orm/utils/get-join-column.util'; @Injectable() export class StandardFieldFactory { @@ -144,10 +144,9 @@ export class StandardFieldFactory { metadataArgsStorage.filterJoinColumns( workspaceRelationMetadataArgs.target, ); - const joinColumnMetadataArgs = joinColumnMetadataArgsCollection.find( - (joinColumnMetadataArgs) => - joinColumnMetadataArgs.relationName === - workspaceRelationMetadataArgs.name, + const joinColumn = getJoinColumn( + joinColumnMetadataArgsCollection, + workspaceRelationMetadataArgs, ); if ( @@ -159,22 +158,11 @@ export class StandardFieldFactory { return []; } - if ( - !joinColumnMetadataArgs && - (workspaceRelationMetadataArgs.type === - RelationMetadataType.MANY_TO_ONE || - workspaceRelationMetadataArgs.type === RelationMetadataType.ONE_TO_ONE) - ) { - throw new Error( - `Join column not found for relation ${workspaceRelationMetadataArgs.name}`, - ); - } - - if (joinColumnMetadataArgs) { + if (joinColumn) { fieldMetadataCollection.push({ type: FieldMetadataType.UUID, standardId: foreignKeyStandardId, - name: joinColumnMetadataArgs.joinColumn, + name: joinColumn, label: `${workspaceRelationMetadataArgs.label} id (foreign key)`, description: `${workspaceRelationMetadataArgs.description} id foreign key`, icon: workspaceRelationMetadataArgs.icon, From acd15a90bb992222bf0e9a2af1a555195c70cee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Magrin?= Date: Wed, 26 Jun 2024 15:29:47 +0200 Subject: [PATCH 7/9] fix: avoid infinite recursion --- .../src/engine/twenty-orm/utils/get-join-column.util.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts b/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts index 1f94e232eee1..5d47467887b1 100644 --- a/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts +++ b/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts @@ -7,6 +7,7 @@ import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args export const getJoinColumn = ( joinColumnsMetadataArgsCollection: WorkspaceJoinColumnsMetadataArgs[], relationMetadataArgs: WorkspaceRelationMetadataArgs, + opposite = false, ): string | null => { if ( relationMetadataArgs.type === RelationMetadataType.ONE_TO_MANY || @@ -24,7 +25,8 @@ export const getJoinColumn = ( // If we're in a ONE_TO_ONE relation and there are no join columns, we need to find the join column on the inverse side if ( relationMetadataArgs.type === RelationMetadataType.ONE_TO_ONE && - filteredJoinColumnsMetadataArgsCollection.length === 0 + filteredJoinColumnsMetadataArgsCollection.length === 0 && + !opposite ) { const inverseSideTarget = relationMetadataArgs.inverseSideTarget(); const inverseSideJoinColumnsMetadataArgsCollection = @@ -47,6 +49,8 @@ export const getJoinColumn = ( return getJoinColumn( inverseSideJoinColumnsMetadataArgsCollection, inverseSideRelationMetadataArgs, + // Avoid infinite recursion + true, ); } From 676745698ecffa45c5e2ade21c1a2abf76c7e943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Magrin?= Date: Wed, 26 Jun 2024 15:42:55 +0200 Subject: [PATCH 8/9] fix: avoid join column on both side --- .../twenty-orm/utils/get-join-column.util.ts | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts b/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts index 5d47467887b1..a328b5a3f6b4 100644 --- a/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts +++ b/packages/twenty-server/src/engine/twenty-orm/utils/get-join-column.util.ts @@ -16,11 +16,28 @@ export const getJoinColumn = ( return null; } + const inverseSideTarget = relationMetadataArgs.inverseSideTarget(); + const inverseSideJoinColumnsMetadataArgsCollection = + metadataArgsStorage.filterJoinColumns(inverseSideTarget); const filteredJoinColumnsMetadataArgsCollection = joinColumnsMetadataArgsCollection.filter( (joinColumnsMetadataArgs) => joinColumnsMetadataArgs.relationName === relationMetadataArgs.name, ); + const oppositeFilteredJoinColumnsMetadataArgsCollection = + inverseSideJoinColumnsMetadataArgsCollection.filter( + (joinColumnsMetadataArgs) => + joinColumnsMetadataArgs.relationName === relationMetadataArgs.name, + ); + + if ( + filteredJoinColumnsMetadataArgsCollection.length > 0 && + oppositeFilteredJoinColumnsMetadataArgsCollection.length > 0 + ) { + throw new Error( + `Join column for ${relationMetadataArgs.name} relation is present on both sides`, + ); + } // If we're in a ONE_TO_ONE relation and there are no join columns, we need to find the join column on the inverse side if ( @@ -28,9 +45,6 @@ export const getJoinColumn = ( filteredJoinColumnsMetadataArgsCollection.length === 0 && !opposite ) { - const inverseSideTarget = relationMetadataArgs.inverseSideTarget(); - const inverseSideJoinColumnsMetadataArgsCollection = - metadataArgsStorage.filterJoinColumns(inverseSideTarget); const inverseSideRelationMetadataArgsCollection = metadataArgsStorage.filterRelations(inverseSideTarget); const inverseSideRelationMetadataArgs = @@ -42,7 +56,7 @@ export const getJoinColumn = ( if (!inverseSideRelationMetadataArgs) { throw new Error( - `Inverse side relation metadata args are missing for relation ${relationMetadataArgs.name}`, + `Inverse side join column of relation ${relationMetadataArgs.name} is missing`, ); } @@ -57,7 +71,7 @@ export const getJoinColumn = ( // Check if there are multiple join columns for the relation if (filteredJoinColumnsMetadataArgsCollection.length > 1) { throw new Error( - `Multiple join columns metadata args found for relation ${relationMetadataArgs.name}`, + `Multiple join columns found for relation ${relationMetadataArgs.name}`, ); } @@ -65,7 +79,7 @@ export const getJoinColumn = ( if (!joinColumnsMetadataArgs) { throw new Error( - `Join columns metadata args are missing for relation ${relationMetadataArgs.name}`, + `Join column is missing for relation ${relationMetadataArgs.name}`, ); } From be77e4ac6bd0d75035257cfa18516795d409c308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Magrin?= Date: Wed, 26 Jun 2024 17:25:55 +0200 Subject: [PATCH 9/9] fix: duplicate identifier --- .../common/standard-objects/message-channel.workspace-entity.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts index 18e0be7fa50f..160912737e3a 100644 --- a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts @@ -305,7 +305,6 @@ export class MessageChannelWorkspaceEntity extends BaseWorkspaceEntity { inverseSideFieldKey: 'messageChannels', }) connectedAccount: Relation; - connectedAccountId: string; @WorkspaceJoinColumn('connectedAccount') connectedAccountId: string;