From d8cadad0fa0c5cc5f0fbae93061780980b4bd237 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Sat, 20 Jul 2024 00:43:29 +0200 Subject: [PATCH] Deprecate inject workspace repo (#6353) --- .../auth/services/google-apis.service.ts | 43 +++---- .../core-modules/billing/billing.resolver.ts | 22 ++-- .../billing/billing.workspace-service.ts | 21 ++-- .../billing/jobs/update-subscription.job.ts | 9 +- .../onboarding/onboarding.service.ts | 31 +++--- .../user-workspace/user-workspace.service.ts | 15 +-- .../workspace/workspace.resolver.ts | 40 +++---- .../datasource/workspace.datasource.ts | 4 + .../factories/entity-schema.factory.ts | 30 +---- .../engine/twenty-orm/twenty-orm.manager.ts | 105 ++++++++++++------ .../engine/twenty-orm/twenty-orm.module.ts | 6 +- .../engine/twenty-orm/twenty-orm.providers.ts | 44 -------- ...ocklist-item-delete-calendar-events.job.ts | 22 ++-- .../blocklist-reimport-calendar-events.job.ts | 18 +-- .../calendar-event-cleaner.service.ts | 31 +++--- .../jobs/calendar-event-list-fetch.job.ts | 25 +++-- .../calendar-channel-sync-status.service.ts | 69 +++++++++--- ...dar-event-import-error-handling.service.ts | 13 ++- .../calendar-events-import.service.ts | 24 ++-- .../services/calendar-save-events.service.ts | 32 +++--- ...eate-company-and-contact-after-sync.job.ts | 22 ++-- .../calendar-event-participant.service.ts | 41 ++++--- ...calendar-event-find-many.pre-query.hook.ts | 15 ++- .../calendar-event-find-one.pre-query-hook.ts | 13 ++- .../can-access-calendar-event.service.ts | 23 ++-- ...ected-account-delete-one.pre-query.hook.ts | 15 ++- .../messaging-message-cleaner.service.ts | 28 +++-- .../jobs/messaging-ongoing-stale.job.ts | 15 ++- ...kspace-member-delete-one.pre-query.hook.ts | 24 ++-- 29 files changed, 441 insertions(+), 359 deletions(-) delete mode 100644 packages/twenty-server/src/engine/twenty-orm/twenty-orm.providers.ts diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts index 534ad1a6e..6b28e10a2 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts @@ -4,42 +4,42 @@ import { EntityManager } from 'typeorm'; import { v4 } from 'uuid'; import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; +import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource'; +import { InjectWorkspaceDatasource } from 'src/engine/twenty-orm/decorators/inject-workspace-datasource.decorator'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { + CalendarEventListFetchJob, + CalendarEventsImportJobData, +} from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job'; +import { + CalendarChannelVisibility, + CalendarChannelWorkspaceEntity, +} from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { - ConnectedAccountWorkspaceEntity, ConnectedAccountProvider, + ConnectedAccountWorkspaceEntity, } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; import { - MessageChannelWorkspaceEntity, + MessageChannelSyncStatus, MessageChannelType, MessageChannelVisibility, - MessageChannelSyncStatus, + MessageChannelWorkspaceEntity, } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { MessagingMessageListFetchJob, MessagingMessageListFetchJobData, } from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job'; -import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decorators/message-queue.decorator'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; -import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource'; -import { InjectWorkspaceDatasource } from 'src/engine/twenty-orm/decorators/inject-workspace-datasource.decorator'; -import { - CalendarChannelWorkspaceEntity, - CalendarChannelVisibility, -} from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; -import { - CalendarEventsImportJobData, - CalendarEventListFetchJob, -} from 'src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job'; @Injectable() export class GoogleAPIsService { constructor( + private readonly twentyORMManager: TwentyORMManager, @InjectWorkspaceDatasource() private readonly workspaceDataSource: WorkspaceDataSource, @InjectMessageQueue(MessageQueue.messagingQueue) @@ -51,8 +51,6 @@ export class GoogleAPIsService { private readonly connectedAccountRepository: ConnectedAccountRepository, @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) private readonly messageChannelRepository: MessageChannelRepository, - @InjectWorkspaceRepository(CalendarChannelWorkspaceEntity) - private readonly calendarChannelRepository: WorkspaceRepository, ) {} async refreshGoogleRefreshToken(input: { @@ -86,6 +84,11 @@ export class GoogleAPIsService { const existingAccountId = connectedAccounts?.[0]?.id; const newOrExistingConnectedAccountId = existingAccountId ?? v4(); + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + await this.workspaceDataSource.transaction( async (manager: EntityManager) => { if (!existingAccountId) { @@ -117,7 +120,7 @@ export class GoogleAPIsService { ); if (isCalendarEnabled) { - await this.calendarChannelRepository.save( + await calendarChannelRepository.save( { id: v4(), connectedAccountId: newOrExistingConnectedAccountId, @@ -167,7 +170,7 @@ export class GoogleAPIsService { } if (isCalendarEnabled) { - const calendarChannels = await this.calendarChannelRepository.find({ + const calendarChannels = await calendarChannelRepository.find({ where: { connectedAccountId: newOrExistingConnectedAccountId, }, diff --git a/packages/twenty-server/src/engine/core-modules/billing/billing.resolver.ts b/packages/twenty-server/src/engine/core-modules/billing/billing.resolver.ts index 40c90fbc2..0f4d772aa 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/billing.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/billing.resolver.ts @@ -1,20 +1,22 @@ -import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; import { UseGuards } from '@nestjs/common'; +import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; import { AvailableProduct, BillingWorkspaceService, } from 'src/engine/core-modules/billing/billing.workspace-service'; -import { ProductInput } from 'src/engine/core-modules/billing/dto/product.input'; -import { assert } from 'src/utils/assert'; -import { ProductPricesEntity } from 'src/engine/core-modules/billing/dto/product-prices.entity'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; -import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; -import { User } from 'src/engine/core-modules/user/user.entity'; -import { CheckoutSessionInput } from 'src/engine/core-modules/billing/dto/checkout-session.input'; -import { SessionEntity } from 'src/engine/core-modules/billing/dto/session.entity'; import { BillingSessionInput } from 'src/engine/core-modules/billing/dto/billing-session.input'; +import { CheckoutSessionInput } from 'src/engine/core-modules/billing/dto/checkout-session.input'; +import { ProductPricesEntity } from 'src/engine/core-modules/billing/dto/product-prices.entity'; +import { ProductInput } from 'src/engine/core-modules/billing/dto/product.input'; +import { SessionEntity } from 'src/engine/core-modules/billing/dto/session.entity'; import { UpdateBillingEntity } from 'src/engine/core-modules/billing/dto/update-billing.entity'; +import { User } from 'src/engine/core-modules/user/user.entity'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; +import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; +import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { assert } from 'src/utils/assert'; @Resolver() export class BillingResolver { @@ -60,6 +62,7 @@ export class BillingResolver { @Mutation(() => SessionEntity) @UseGuards(JwtAuthGuard) async checkoutSession( + @AuthWorkspace() workspace: Workspace, @AuthUser() user: User, @Args() { recurringInterval, successUrlPath }: CheckoutSessionInput, ) { @@ -87,6 +90,7 @@ export class BillingResolver { return { url: await this.billingWorkspaceService.computeCheckoutSessionURL( user, + workspace, stripePriceId, successUrlPath, ), diff --git a/packages/twenty-server/src/engine/core-modules/billing/billing.workspace-service.ts b/packages/twenty-server/src/engine/core-modules/billing/billing.workspace-service.ts index d912751ea..f0d1e4090 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/billing.workspace-service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/billing.workspace-service.ts @@ -4,24 +4,24 @@ import { InjectRepository } from '@nestjs/typeorm'; import Stripe from 'stripe'; import { Not, Repository } from 'typeorm'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service'; +import { BillingService } from 'src/engine/core-modules/billing/billing.service'; +import { ProductPriceEntity } from 'src/engine/core-modules/billing/dto/product-price.entity'; +import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity'; import { BillingSubscription, SubscriptionInterval, SubscriptionStatus, } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; -import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { ProductPriceEntity } from 'src/engine/core-modules/billing/dto/product-price.entity'; -import { User } from 'src/engine/core-modules/user/user.entity'; -import { assert } from 'src/utils/assert'; -import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; +import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service'; import { FeatureFlagEntity, FeatureFlagKeys, } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { BillingService } from 'src/engine/core-modules/billing/billing.service'; +import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; +import { User } from 'src/engine/core-modules/user/user.entity'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { assert } from 'src/utils/assert'; export enum AvailableProduct { BasePlan = 'base-plan', @@ -219,6 +219,7 @@ export class BillingWorkspaceService { async computeCheckoutSessionURL( user: User, + workspace: Workspace, priceId: string, successUrlPath?: string, ): Promise { @@ -228,7 +229,7 @@ export class BillingWorkspaceService { : frontBaseUrl; const quantity = - (await this.userWorkspaceService.getWorkspaceMemberCount()) || 1; + (await this.userWorkspaceService.getUserCount(workspace.id)) || 1; const stripeCustomerId = ( await this.billingSubscriptionRepository.findOneBy({ diff --git a/packages/twenty-server/src/engine/core-modules/billing/jobs/update-subscription.job.ts b/packages/twenty-server/src/engine/core-modules/billing/jobs/update-subscription.job.ts index 9302c50f8..02e803b54 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/jobs/update-subscription.job.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/jobs/update-subscription.job.ts @@ -1,11 +1,11 @@ import { Logger, Scope } from '@nestjs/common'; import { BillingWorkspaceService } from 'src/engine/core-modules/billing/billing.workspace-service'; -import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service'; +import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; +import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; export type UpdateSubscriptionJobData = { workspaceId: string }; @Processor({ @@ -23,8 +23,9 @@ export class UpdateSubscriptionJob { @Process(UpdateSubscriptionJob.name) async handle(data: UpdateSubscriptionJobData): Promise { - const workspaceMembersCount = - await this.userWorkspaceService.getWorkspaceMemberCount(); + const workspaceMembersCount = await this.userWorkspaceService.getUserCount( + data.workspaceId, + ); if (!workspaceMembersCount || workspaceMembersCount <= 0) { return; diff --git a/packages/twenty-server/src/engine/core-modules/onboarding/onboarding.service.ts b/packages/twenty-server/src/engine/core-modules/onboarding/onboarding.service.ts index f131e5bca..5062bc54f 100644 --- a/packages/twenty-server/src/engine/core-modules/onboarding/onboarding.service.ts +++ b/packages/twenty-server/src/engine/core-modules/onboarding/onboarding.service.ts @@ -1,20 +1,20 @@ +/* eslint-disable @nx/workspace-inject-workspace-repository */ import { Injectable } from '@nestjs/common'; +import { BillingWorkspaceService } from 'src/engine/core-modules/billing/billing.workspace-service'; +import { SubscriptionStatus } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; import { KeyValuePairService } from 'src/engine/core-modules/key-value-pair/key-value-pair.service'; import { OnboardingStatus } from 'src/engine/core-modules/onboarding/enums/onboarding-status.enum'; +import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; 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 { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; -import { SubscriptionStatus } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; +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 { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; import { isDefined } from 'src/utils/is-defined'; -import { BillingWorkspaceService } from 'src/engine/core-modules/billing/billing.workspace-service'; enum OnboardingStepValues { SKIPPED = 'SKIPPED', @@ -33,14 +33,13 @@ type OnboardingKeyValueType = { @Injectable() export class OnboardingService { constructor( + private readonly twentyORMManager: TwentyORMManager, private readonly billingWorkspaceService: BillingWorkspaceService, private readonly workspaceManagerService: WorkspaceManagerService, private readonly userWorkspaceService: UserWorkspaceService, private readonly keyValuePairService: KeyValuePairService, @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) private readonly connectedAccountRepository: ConnectedAccountRepository, - @InjectWorkspaceRepository(WorkspaceMemberWorkspaceEntity) - private readonly workspaceMemberRepository: WorkspaceRepository, ) {} private async isSubscriptionIncompleteOnboardingStatus(user: User) { @@ -71,7 +70,12 @@ export class OnboardingService { } private async isProfileCreationOnboardingStatus(user: User) { - const workspaceMember = await this.workspaceMemberRepository.findOneBy({ + const workspaceMemberRepository = + await this.twentyORMManager.getRepository( + 'workspaceMember', + ); + + const workspaceMember = await workspaceMemberRepository.findOneBy({ userId: user.id, }); @@ -104,8 +108,9 @@ export class OnboardingService { }); const isInviteTeamSkipped = inviteTeamValue === OnboardingStepValues.SKIPPED; - const workspaceMemberCount = - await this.userWorkspaceService.getWorkspaceMemberCount(); + const workspaceMemberCount = await this.userWorkspaceService.getUserCount( + workspace.id, + ); return ( !isInviteTeamSkipped && diff --git a/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.service.ts b/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.service.ts index 9d6ea4184..821e2e65c 100644 --- a/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.service.ts +++ b/packages/twenty-server/src/engine/core-modules/user-workspace/user-workspace.service.ts @@ -11,8 +11,6 @@ import { User } from 'src/engine/core-modules/user/user.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { ObjectRecordCreateEvent } from 'src/engine/integrations/event-emitter/types/object-record-create.event'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; import { assert } from 'src/utils/assert'; @@ -22,8 +20,6 @@ export class UserWorkspaceService extends TypeOrmQueryService { private readonly userWorkspaceRepository: Repository, @InjectRepository(User, 'core') private readonly userRepository: Repository, - @InjectWorkspaceRepository(WorkspaceMemberWorkspaceEntity) - private readonly workspaceMemberRepository: WorkspaceRepository, private readonly dataSourceService: DataSourceService, private readonly typeORMService: TypeORMService, private eventEmitter: EventEmitter2, @@ -107,13 +103,10 @@ export class UserWorkspaceService extends TypeOrmQueryService { }); } - public async getWorkspaceMemberCount(): Promise { - // TODO: to refactor, this could happen today for the first signup since the workspace does not exist yet - if (!this.workspaceMemberRepository) { - return undefined; - } - - return await this.workspaceMemberRepository.count(); + public async getUserCount(workspaceId): Promise { + return await this.userWorkspaceRepository.countBy({ + workspaceId, + }); } async checkUserWorkspaceExists( diff --git a/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts b/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts index 5ead7800d..2ee565590 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/workspace.resolver.ts @@ -1,33 +1,33 @@ +import { UseGuards } from '@nestjs/common'; import { - Resolver, - Query, Args, Mutation, - ResolveField, Parent, + Query, + ResolveField, + Resolver, } from '@nestjs/graphql'; -import { UseGuards } from '@nestjs/common'; import { FileUpload, GraphQLUpload } from 'graphql-upload'; import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface'; -import { streamToBuffer } from 'src/utils/stream-to-buffer'; -import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; -import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; -import { assert } from 'src/utils/assert'; -import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; -import { UpdateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/update-workspace-input'; -import { User } from 'src/engine/core-modules/user/user.entity'; -import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; -import { ActivateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/activate-workspace-input'; -import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; import { BillingWorkspaceService } from 'src/engine/core-modules/billing/billing.workspace-service'; -import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard'; -import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service'; +import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; +import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service'; +import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; +import { User } from 'src/engine/core-modules/user/user.entity'; +import { ActivateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/activate-workspace-input'; import { SendInviteLink } from 'src/engine/core-modules/workspace/dtos/send-invite-link.entity'; import { SendInviteLinkInput } from 'src/engine/core-modules/workspace/dtos/send-invite-link.input'; -import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; +import { UpdateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/update-workspace-input'; +import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator'; +import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; +import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard'; +import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard'; +import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service'; +import { assert } from 'src/utils/assert'; +import { streamToBuffer } from 'src/utils/stream-to-buffer'; import { Workspace } from './workspace.entity'; @@ -128,8 +128,10 @@ export class WorkspaceResolver { } @ResolveField(() => Number) - async workspaceMembersCount(): Promise { - return await this.userWorkspaceService.getWorkspaceMemberCount(); + async workspaceMembersCount( + @Parent() workspace: Workspace, + ): Promise { + return await this.userWorkspaceService.getUserCount(workspace.id); } @Mutation(() => SendInviteLink) diff --git a/packages/twenty-server/src/engine/twenty-orm/datasource/workspace.datasource.ts b/packages/twenty-server/src/engine/twenty-orm/datasource/workspace.datasource.ts index 076ef7f7e..b83b7b940 100644 --- a/packages/twenty-server/src/engine/twenty-orm/datasource/workspace.datasource.ts +++ b/packages/twenty-server/src/engine/twenty-orm/datasource/workspace.datasource.ts @@ -36,4 +36,8 @@ export class WorkspaceDataSource extends DataSource { ): WorkspaceEntityManager { return new WorkspaceEntityManager(this.internalContext, this, queryRunner); } + + getWorkspaceId(): string { + return this.internalContext.workspaceId; + } } 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 daf83b09f..423cf458f 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 @@ -2,9 +2,9 @@ import { Injectable } from '@nestjs/common'; import { EntitySchema } from 'typeorm'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { EntitySchemaColumnFactory } from 'src/engine/twenty-orm/factories/entity-schema-column.factory'; import { EntitySchemaRelationFactory } from 'src/engine/twenty-orm/factories/entity-schema-relation.factory'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { WorkspaceEntitiesStorage } from 'src/engine/twenty-orm/storage/workspace-entities.storage'; import { computeTableName } from 'src/engine/utils/compute-table-name.util'; import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; @@ -20,35 +20,7 @@ export class EntitySchemaFactory { async create( workspaceId: string, objectMetadata: ObjectMetadataEntity, - ): Promise; - - async create( - workspaceId: string, - objectMetadataName: string, - ): Promise; - - async create( - workspaceId: string, - objectMetadataOrObjectMetadataName: ObjectMetadataEntity | string, ): Promise { - let objectMetadata: ObjectMetadataEntity | null = - typeof objectMetadataOrObjectMetadataName !== 'string' - ? objectMetadataOrObjectMetadataName - : null; - - if (typeof objectMetadataOrObjectMetadataName === 'string') { - objectMetadata = - (await this.workspaceCacheStorageService.getObjectMetadata( - workspaceId, - (objectMetadata) => - objectMetadata.nameSingular === objectMetadataOrObjectMetadataName, - )) ?? null; - } - - if (!objectMetadata) { - throw new Error('Object metadata not found'); - } - const columns = this.entitySchemaColumnFactory.create( workspaceId, objectMetadata.fields, diff --git a/packages/twenty-server/src/engine/twenty-orm/twenty-orm.manager.ts b/packages/twenty-server/src/engine/twenty-orm/twenty-orm.manager.ts index a6852503c..ce53d3a14 100644 --- a/packages/twenty-server/src/engine/twenty-orm/twenty-orm.manager.ts +++ b/packages/twenty-server/src/engine/twenty-orm/twenty-orm.manager.ts @@ -54,9 +54,42 @@ export class TwentyORMManager { throw new Error('Workspace data source not found'); } + const workspaceId = this.workspaceDataSource.getWorkspaceId(); + + let objectMetadataCollection = + await this.workspaceCacheStorageService.getObjectMetadataCollection( + workspaceId, + ); + + if (!objectMetadataCollection) { + objectMetadataCollection = await this.objectMetadataRepository.find({ + where: { workspaceId }, + relations: [ + 'fields.object', + 'fields', + 'fields.fromRelationMetadata', + 'fields.toRelationMetadata', + 'fields.fromRelationMetadata.toObjectMetadata', + ], + }); + + await this.workspaceCacheStorageService.setObjectMetadataCollection( + workspaceId, + objectMetadataCollection, + ); + } + + const objectMetadata = objectMetadataCollection.find( + (objectMetadata) => objectMetadata.nameSingular === objectMetadataName, + ); + + if (!objectMetadata) { + throw new Error('Object metadata not found'); + } + const entitySchema = await this.entitySchemaFactory.create( - this.workspaceDataSource.internalContext.workspaceId, - objectMetadataName, + workspaceId, + objectMetadata, ); if (!entitySchema) { @@ -95,38 +128,38 @@ export class TwentyORMManager { ); } + let objectMetadataCollection = + await this.workspaceCacheStorageService.getObjectMetadataCollection( + workspaceId, + ); + + if (!objectMetadataCollection) { + objectMetadataCollection = await this.objectMetadataRepository.find({ + where: { workspaceId }, + relations: [ + 'fields.object', + 'fields', + 'fields.fromRelationMetadata', + 'fields.toRelationMetadata', + 'fields.fromRelationMetadata.toObjectMetadata', + ], + }); + + await this.workspaceCacheStorageService.setObjectMetadataCollection( + workspaceId, + objectMetadataCollection, + ); + } + + const entities = await Promise.all( + objectMetadataCollection.map((objectMetadata) => + this.entitySchemaFactory.create(workspaceId, objectMetadata), + ), + ); + const workspaceDataSource = await workspaceDataSourceCacheInstance.execute( `${workspaceId}-${cacheVersion}`, async () => { - let objectMetadataCollection = - await this.workspaceCacheStorageService.getObjectMetadataCollection( - workspaceId, - ); - - if (!objectMetadataCollection) { - objectMetadataCollection = await this.objectMetadataRepository.find({ - where: { workspaceId }, - relations: [ - 'fields.object', - 'fields', - 'fields.fromRelationMetadata', - 'fields.toRelationMetadata', - 'fields.fromRelationMetadata.toObjectMetadata', - ], - }); - - await this.workspaceCacheStorageService.setObjectMetadataCollection( - workspaceId, - objectMetadataCollection, - ); - } - - const entities = await Promise.all( - objectMetadataCollection.map((objectMetadata) => - this.entitySchemaFactory.create(workspaceId, objectMetadata), - ), - ); - const workspaceDataSource = await this.workspaceDataSourceFactory.create(entities, workspaceId); @@ -135,9 +168,17 @@ export class TwentyORMManager { (dataSource) => dataSource.destroy(), ); + const objectMetadata = objectMetadataCollection.find( + (objectMetadata) => objectMetadata.nameSingular === objectMetadataName, + ); + + if (!objectMetadata) { + throw new Error('Object metadata not found'); + } + const entitySchema = await this.entitySchemaFactory.create( workspaceId, - objectMetadataName, + objectMetadata, ); if (!workspaceDataSource) { diff --git a/packages/twenty-server/src/engine/twenty-orm/twenty-orm.module.ts b/packages/twenty-server/src/engine/twenty-orm/twenty-orm.module.ts index cd94d0129..ecca90357 100644 --- a/packages/twenty-server/src/engine/twenty-orm/twenty-orm.module.ts +++ b/packages/twenty-server/src/engine/twenty-orm/twenty-orm.module.ts @@ -6,9 +6,9 @@ import { TwentyORMOptions, } from 'src/engine/twenty-orm/interfaces/twenty-orm-options.interface'; -import { createTwentyORMProviders } from 'src/engine/twenty-orm/twenty-orm.providers'; import { TwentyORMCoreModule } from 'src/engine/twenty-orm/twenty-orm-core.module'; +// Todo: remove this file @Global() @Module({}) export class TwentyORMModule { @@ -19,8 +19,8 @@ export class TwentyORMModule { }; } - static forFeature(objects: EntityClassOrSchema[] = []): DynamicModule { - const providers = createTwentyORMProviders(objects); + static forFeature(_objects: EntityClassOrSchema[] = []): DynamicModule { + const providers = []; return { module: TwentyORMModule, diff --git a/packages/twenty-server/src/engine/twenty-orm/twenty-orm.providers.ts b/packages/twenty-server/src/engine/twenty-orm/twenty-orm.providers.ts deleted file mode 100644 index ca0afc7ee..000000000 --- a/packages/twenty-server/src/engine/twenty-orm/twenty-orm.providers.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Provider, Type } from '@nestjs/common'; -import { EntityClassOrSchema } from '@nestjs/typeorm/dist/interfaces/entity-class-or-schema.type'; - -import { getWorkspaceRepositoryToken } from 'src/engine/twenty-orm/utils/get-workspace-repository-token.util'; -import { TWENTY_ORM_WORKSPACE_DATASOURCE } from 'src/engine/twenty-orm/twenty-orm.constants'; -import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory'; -import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource'; -import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util'; - -/** - * Create providers for the given entities. - */ -export function createTwentyORMProviders( - objects?: EntityClassOrSchema[], -): Provider[] { - return (objects || []).map((object) => ({ - provide: getWorkspaceRepositoryToken(object), - useFactory: async ( - dataSource: WorkspaceDataSource | null, - entitySchemaFactory: EntitySchemaFactory, - ) => { - const objectMetadataName = convertClassNameToObjectMetadataName( - (object as Type).name, - ); - - if (!dataSource) { - // TODO: Throw here when the code is well architected - return null; - } - - const entitySchema = await entitySchemaFactory.create( - dataSource.internalContext.workspaceId, - objectMetadataName, - ); - - if (!entitySchema) { - throw new Error('Entity schema not found'); - } - - return dataSource.getRepository(entitySchema); - }, - inject: [TWENTY_ORM_WORKSPACE_DATASOURCE, EntitySchemaFactory], - })); -} diff --git a/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-item-delete-calendar-events.job.ts b/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-item-delete-calendar-events.job.ts index 7091c127a..9f9777328 100644 --- a/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-item-delete-calendar-events.job.ts +++ b/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-item-delete-calendar-events.job.ts @@ -6,13 +6,10 @@ import { Process } from 'src/engine/integrations/message-queue/decorators/proces import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository'; import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; import { CalendarEventCleanerService } from 'src/modules/calendar/calendar-event-cleaner/services/calendar-event-cleaner.service'; -import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity'; -import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; export type BlocklistItemDeleteCalendarEventsJobData = { workspaceId: string; @@ -29,10 +26,7 @@ export class BlocklistItemDeleteCalendarEventsJob { ); constructor( - @InjectWorkspaceRepository(CalendarChannelWorkspaceEntity) - private readonly calendarChannelRepository: WorkspaceRepository, - @InjectWorkspaceRepository(CalendarChannelEventAssociationWorkspaceEntity) - private readonly calendarChannelEventAssociationRepository: WorkspaceRepository, + private readonly twentyORMManager: TwentyORMManager, @InjectObjectMetadataRepository(BlocklistWorkspaceEntity) private readonly blocklistRepository: BlocklistRepository, private readonly calendarEventCleanerService: CalendarEventCleanerService, @@ -67,7 +61,10 @@ export class BlocklistItemDeleteCalendarEventsJob { ); } - const calendarChannels = await this.calendarChannelRepository.find({ + const calendarChannelRepository = + await this.twentyORMManager.getRepository('calendarChannel'); + + const calendarChannels = await calendarChannelRepository.find({ where: { connectedAccount: { accountOwnerId: workspaceMemberId, @@ -79,7 +76,12 @@ export class BlocklistItemDeleteCalendarEventsJob { const isHandleDomain = handle.startsWith('@'); - await this.calendarChannelEventAssociationRepository.delete({ + const calendarChannelEventAssociationRepository = + await this.twentyORMManager.getRepository( + 'calendarChannelEventAssociation', + ); + + await calendarChannelEventAssociationRepository.delete({ calendarEvent: { calendarEventParticipants: { handle: isHandleDomain ? ILike(`%${handle}`) : handle, diff --git a/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-reimport-calendar-events.job.ts b/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-reimport-calendar-events.job.ts index 4eef5ecdb..d8d35d128 100644 --- a/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-reimport-calendar-events.job.ts +++ b/packages/twenty-server/src/modules/calendar/blocklist-manager/jobs/blocklist-reimport-calendar-events.job.ts @@ -2,18 +2,17 @@ import { Scope } from '@nestjs/common'; import { Any } from 'typeorm'; +import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -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 { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { CalendarChannelSyncStage, CalendarChannelWorkspaceEntity, } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; +import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; +import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; export type BlocklistReimportCalendarEventsJobData = { workspaceId: string; @@ -26,10 +25,9 @@ export type BlocklistReimportCalendarEventsJobData = { }) export class BlocklistReimportCalendarEventsJob { constructor( + private readonly twentyORMManager: TwentyORMManager, @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) private readonly connectedAccountRepository: ConnectedAccountRepository, - @InjectWorkspaceRepository(CalendarChannelWorkspaceEntity) - private readonly calendarChannelRepository: WorkspaceRepository, ) {} @Process(BlocklistReimportCalendarEventsJob.name) @@ -46,7 +44,11 @@ export class BlocklistReimportCalendarEventsJob { return; } - await this.calendarChannelRepository.update( + const calendarChannelRepository = await this.twentyORMManager.getRepository( + CalendarChannelWorkspaceEntity, + ); + + await calendarChannelRepository.update( { connectedAccountId: Any( connectedAccounts.map((connectedAccount) => connectedAccount.id), diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-cleaner/services/calendar-event-cleaner.service.ts b/packages/twenty-server/src/modules/calendar/calendar-event-cleaner/services/calendar-event-cleaner.service.ts index 0248957a6..a2d7af0a3 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-cleaner/services/calendar-event-cleaner.service.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-cleaner/services/calendar-event-cleaner.service.ts @@ -2,38 +2,35 @@ import { Injectable } from '@nestjs/common'; import { Any, IsNull } from 'typeorm'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { deleteUsingPagination } from 'src/modules/messaging/message-cleaner/utils/delete-using-pagination.util'; -import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity'; @Injectable() export class CalendarEventCleanerService { - constructor( - @InjectWorkspaceRepository(CalendarEventWorkspaceEntity) - private readonly calendarEventRepository: WorkspaceRepository, - ) {} + constructor(private readonly twentyORMManager: TwentyORMManager) {} public async cleanWorkspaceCalendarEvents(workspaceId: string) { + const calendarEventRepository = + await this.twentyORMManager.getRepository('calendarEvent'); + await deleteUsingPagination( workspaceId, 500, async (limit, offset) => { - const nonAssociatedCalendarEvents = - await this.calendarEventRepository.find({ - where: { - calendarChannelEventAssociations: { - id: IsNull(), - }, + const nonAssociatedCalendarEvents = await calendarEventRepository.find({ + where: { + calendarChannelEventAssociations: { + id: IsNull(), }, - take: limit, - skip: offset, - }); + }, + take: limit, + skip: offset, + }); return nonAssociatedCalendarEvents.map(({ id }) => id); }, async (ids) => { - await this.calendarEventRepository.delete({ id: Any(ids) }); + await calendarEventRepository.delete({ id: Any(ids) }); }, ); } diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job.ts index 34ba97fea..9006872ac 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/jobs/calendar-event-list-fetch.job.ts @@ -1,19 +1,18 @@ import { Scope } from '@nestjs/common'; +import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; -import { CalendarEventsImportService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service'; -import { isThrottled } from 'src/modules/connected-account/utils/is-throttled'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -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 { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { CalendarEventsImportService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service'; import { CalendarChannelSyncStage, CalendarChannelWorkspaceEntity, } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; +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 { isThrottled } from 'src/modules/connected-account/utils/is-throttled'; export type CalendarEventsImportJobData = { calendarChannelId: string; @@ -26,18 +25,22 @@ export type CalendarEventsImportJobData = { }) export class CalendarEventListFetchJob { constructor( + private readonly twentyORMManager: TwentyORMManager, private readonly calendarEventsImportService: CalendarEventsImportService, @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) private readonly connectedAccountRepository: ConnectedAccountRepository, - @InjectWorkspaceRepository(CalendarChannelWorkspaceEntity) - private readonly calendarChannelRepository: WorkspaceRepository, ) {} @Process(CalendarEventListFetchJob.name) async handle(data: CalendarEventsImportJobData): Promise { const { workspaceId, calendarChannelId } = data; - const calendarChannel = await this.calendarChannelRepository.findOne({ + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + + const calendarChannel = await calendarChannelRepository.findOne({ where: { id: calendarChannelId, isSyncEnabled: true, @@ -65,7 +68,7 @@ export class CalendarEventListFetchJob { switch (calendarChannel.syncStage) { case CalendarChannelSyncStage.FULL_CALENDAR_EVENT_LIST_FETCH_PENDING: - await this.calendarChannelRepository.update(calendarChannelId, { + await calendarChannelRepository.update(calendarChannelId, { syncCursor: '', syncStageStartedAt: null, }); diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-channel-sync-status.service.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-channel-sync-status.service.ts index 0d6dd28fc..c1e41fe1d 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-channel-sync-status.service.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-channel-sync-status.service.ts @@ -3,8 +3,7 @@ import { Injectable } from '@nestjs/common'; 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 { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { CalendarChannelSyncStage, CalendarChannelSyncStatus, @@ -14,14 +13,18 @@ import { @Injectable() export class CalendarChannelSyncStatusService { constructor( - @InjectWorkspaceRepository(CalendarChannelWorkspaceEntity) - private readonly calendarChannelRepository: WorkspaceRepository, + private readonly twentyORMManager: TwentyORMManager, @InjectCacheStorage(CacheStorageNamespace.Calendar) private readonly cacheStorage: CacheStorageService, ) {} public async scheduleFullCalendarEventListFetch(calendarChannelId: string) { - await this.calendarChannelRepository.update(calendarChannelId, { + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + + await calendarChannelRepository.update(calendarChannelId, { syncStage: CalendarChannelSyncStage.FULL_CALENDAR_EVENT_LIST_FETCH_PENDING, }); @@ -30,14 +33,24 @@ export class CalendarChannelSyncStatusService { public async schedulePartialCalendarEventListFetch( calendarChannelId: string, ) { - await this.calendarChannelRepository.update(calendarChannelId, { + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + + await calendarChannelRepository.update(calendarChannelId, { syncStage: CalendarChannelSyncStage.PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING, }); } public async markAsCalendarEventListFetchOngoing(calendarChannelId: string) { - await this.calendarChannelRepository.update(calendarChannelId, { + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + + await calendarChannelRepository.update(calendarChannelId, { syncStage: CalendarChannelSyncStage.CALENDAR_EVENT_LIST_FETCH_ONGOING, syncStatus: CalendarChannelSyncStatus.ONGOING, syncStageStartedAt: new Date().toISOString(), @@ -52,7 +65,12 @@ export class CalendarChannelSyncStatusService { `calendar-events-to-import:${workspaceId}:google-calendar:${calendarChannelId}`, ); - await this.calendarChannelRepository.update(calendarChannelId, { + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + + await calendarChannelRepository.update(calendarChannelId, { syncCursor: '', syncStageStartedAt: null, throttleFailureCount: 0, @@ -62,13 +80,23 @@ export class CalendarChannelSyncStatusService { } public async scheduleCalendarEventsImport(calendarChannelId: string) { - await this.calendarChannelRepository.update(calendarChannelId, { + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + + await calendarChannelRepository.update(calendarChannelId, { syncStage: CalendarChannelSyncStage.CALENDAR_EVENTS_IMPORT_PENDING, }); } public async markAsCalendarEventsImportOngoing(calendarChannelId: string) { - await this.calendarChannelRepository.update(calendarChannelId, { + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + + await calendarChannelRepository.update(calendarChannelId, { syncStage: CalendarChannelSyncStage.CALENDAR_EVENTS_IMPORT_ONGOING, syncStatus: CalendarChannelSyncStatus.ONGOING, }); @@ -77,7 +105,12 @@ export class CalendarChannelSyncStatusService { public async markAsCompletedAndSchedulePartialMessageListFetch( calendarChannelId: string, ) { - await this.calendarChannelRepository.update(calendarChannelId, { + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + + await calendarChannelRepository.update(calendarChannelId, { syncStage: CalendarChannelSyncStage.PARTIAL_CALENDAR_EVENT_LIST_FETCH_PENDING, syncStatus: CalendarChannelSyncStatus.ACTIVE, @@ -92,11 +125,16 @@ export class CalendarChannelSyncStatusService { calendarChannelId: string, workspaceId: string, ) { + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + await this.cacheStorage.del( `calendar-events-to-import:${workspaceId}:google-calendar:${calendarChannelId}`, ); - await this.calendarChannelRepository.update(calendarChannelId, { + await calendarChannelRepository.update(calendarChannelId, { syncStatus: CalendarChannelSyncStatus.FAILED_UNKNOWN, syncStage: CalendarChannelSyncStage.FAILED, }); @@ -106,11 +144,16 @@ export class CalendarChannelSyncStatusService { calendarChannelId: string, workspaceId: string, ) { + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + await this.cacheStorage.del( `calendar-events-to-import:${workspaceId}:google-calendar:${calendarChannelId}`, ); - await this.calendarChannelRepository.update(calendarChannelId, { + await calendarChannelRepository.update(calendarChannelId, { syncStatus: CalendarChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS, syncStage: CalendarChannelSyncStage.FAILED, }); diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-event-import-error-handling.service.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-event-import-error-handling.service.ts index 93c8b9238..c6fbd93ec 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-event-import-error-handling.service.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-event-import-error-handling.service.ts @@ -1,7 +1,6 @@ import { Injectable } from '@nestjs/common'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { CALENDAR_THROTTLE_MAX_ATTEMPTS } from 'src/modules/calendar/calendar-event-import-manager/constants/calendar-throttle-max-attempts'; import { CalendarChannelSyncStatusService } from 'src/modules/calendar/calendar-event-import-manager/services/calendar-channel-sync-status.service'; import { CalendarEventError } from 'src/modules/calendar/calendar-event-import-manager/types/calendar-event-error.type'; @@ -16,9 +15,8 @@ export enum CalendarEventImportSyncStep { @Injectable() export class CalendarEventImportErrorHandlerService { constructor( + private readonly twentyORMManager: TwentyORMManager, private readonly calendarChannelSyncStatusService: CalendarChannelSyncStatusService, - @InjectWorkspaceRepository(CalendarChannelWorkspaceEntity) - private readonly calendarChannelRepository: WorkspaceRepository, ) {} public async handleError( @@ -68,7 +66,12 @@ export class CalendarEventImportErrorHandlerService { return; } - await this.calendarChannelRepository.increment( + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + + await calendarChannelRepository.increment( { id: calendarChannel.id, }, diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service.ts index da1dfdddb..d2dd7c90a 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-events-import.service.ts @@ -3,8 +3,7 @@ import { Injectable } from '@nestjs/common'; import { Any } from 'typeorm'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { BlocklistRepository } from 'src/modules/blocklist/repositories/blocklist.repository'; import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity'; import { CalendarEventCleanerService } from 'src/modules/calendar/calendar-event-cleaner/services/calendar-event-cleaner.service'; @@ -29,10 +28,7 @@ import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/s @Injectable() export class CalendarEventsImportService { constructor( - @InjectWorkspaceRepository(CalendarChannelWorkspaceEntity) - private readonly calendarChannelRepository: WorkspaceRepository, - @InjectWorkspaceRepository(CalendarChannelEventAssociationWorkspaceEntity) - private readonly calendarChannelEventAssociationRepository: WorkspaceRepository, + private readonly twentyORMManager: TwentyORMManager, @InjectObjectMetadataRepository(BlocklistWorkspaceEntity) private readonly blocklistRepository: BlocklistRepository, private readonly calendarEventCleanerService: CalendarEventCleanerService, @@ -79,8 +75,13 @@ export class CalendarEventsImportService { return; } + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + if (!calendarEvents || calendarEvents?.length === 0) { - await this.calendarChannelRepository.update( + await calendarChannelRepository.update( { id: calendarChannel.id, }, @@ -117,7 +118,12 @@ export class CalendarEventsImportService { workspaceId, ); - await this.calendarChannelEventAssociationRepository.delete({ + const calendarChannelEventAssociationRepository = + await this.twentyORMManager.getRepository( + 'calendarChannelEventAssociation', + ); + + await calendarChannelEventAssociationRepository.delete({ eventExternalId: Any(cancelledEventExternalIds), calendarChannel: { id: calendarChannel.id, @@ -128,7 +134,7 @@ export class CalendarEventsImportService { workspaceId, ); - await this.calendarChannelRepository.update( + await calendarChannelRepository.update( { id: calendarChannel.id, }, diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-save-events.service.ts b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-save-events.service.ts index 52ea33388..3702ad2d3 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-save-events.service.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-import-manager/services/calendar-save-events.service.ts @@ -8,8 +8,7 @@ import { MessageQueue } from 'src/engine/integrations/message-queue/message-queu import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource'; import { InjectWorkspaceDatasource } from 'src/engine/twenty-orm/decorators/inject-workspace-datasource.decorator'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { injectIdsInCalendarEvents } from 'src/modules/calendar/calendar-event-import-manager/utils/inject-ids-in-calendar-events.util'; import { CalendarEventParticipantService } from 'src/modules/calendar/calendar-event-participant-manager/services/calendar-event-participant.service'; import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity'; @@ -26,10 +25,7 @@ import { @Injectable() export class CalendarSaveEventsService { constructor( - @InjectWorkspaceRepository(CalendarEventWorkspaceEntity) - private readonly calendarEventRepository: WorkspaceRepository, - @InjectWorkspaceRepository(CalendarChannelEventAssociationWorkspaceEntity) - private readonly calendarChannelEventAssociationRepository: WorkspaceRepository, + private readonly twentyORMManager: TwentyORMManager, @InjectWorkspaceDatasource() private readonly workspaceDataSource: WorkspaceDataSource, private readonly calendarEventParticipantService: CalendarEventParticipantService, @@ -44,7 +40,12 @@ export class CalendarSaveEventsService { connectedAccount: ConnectedAccountWorkspaceEntity, workspaceId: string, ): Promise { - const existingCalendarEvents = await this.calendarEventRepository.find({ + const calendarEventRepository = + await this.twentyORMManager.getRepository( + 'calendarEvent', + ); + + const existingCalendarEvents = await calendarEventRepository.find({ where: { iCalUID: Any(filteredEvents.map((event) => event.iCalUID as string)), }, @@ -77,8 +78,13 @@ export class CalendarSaveEventsService { existingEventsICalUIDs.includes(calendarEvent.iCalUID), ); + const calendarChannelEventAssociationRepository = + await this.twentyORMManager.getRepository( + 'calendarChannelEventAssociation', + ); + const existingCalendarChannelEventAssociations = - await this.calendarChannelEventAssociationRepository.find({ + await calendarChannelEventAssociationRepository.find({ where: { eventExternalId: Any( calendarEventsWithIds.map((calendarEvent) => calendarEvent.id), @@ -114,19 +120,15 @@ export class CalendarSaveEventsService { []; await this.workspaceDataSource?.transaction(async (transactionManager) => { - await this.calendarEventRepository.save( - eventsToSave, - {}, - transactionManager, - ); + await calendarEventRepository.save(eventsToSave, {}, transactionManager); - await this.calendarEventRepository.save( + await calendarEventRepository.save( eventsToUpdate, {}, transactionManager, ); - await this.calendarChannelEventAssociationRepository.save( + await calendarChannelEventAssociationRepository.save( calendarChannelEventAssociationsToSave, {}, transactionManager, diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-create-company-and-contact-after-sync.job.ts b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-create-company-and-contact-after-sync.job.ts index 372dde104..61d12ab39 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-create-company-and-contact-after-sync.job.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/jobs/calendar-create-company-and-contact-after-sync.job.ts @@ -5,8 +5,7 @@ import { IsNull } from 'typeorm'; import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity'; import { CreateCompanyAndContactService } from 'src/modules/contact-creation-manager/services/create-company-and-contact.service'; @@ -25,11 +24,8 @@ export class CalendarCreateCompanyAndContactAfterSyncJob { CalendarCreateCompanyAndContactAfterSyncJob.name, ); constructor( + private readonly twentyORMManager: TwentyORMManager, private readonly createCompanyAndContactService: CreateCompanyAndContactService, - @InjectWorkspaceRepository(CalendarChannelWorkspaceEntity) - private readonly calendarChannelRepository: WorkspaceRepository, - @InjectWorkspaceRepository(CalendarEventParticipantWorkspaceEntity) - private readonly calendarEventParticipantRepository: WorkspaceRepository, ) {} @Process(CalendarCreateCompanyAndContactAfterSyncJob.name) @@ -41,7 +37,12 @@ export class CalendarCreateCompanyAndContactAfterSyncJob { ); const { workspaceId, calendarChannelId } = data; - const calendarChannel = await this.calendarChannelRepository.findOne({ + const calendarChannelRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + + const calendarChannel = await calendarChannelRepository.findOne({ where: { id: calendarChannelId, }, @@ -67,8 +68,13 @@ export class CalendarCreateCompanyAndContactAfterSyncJob { ); } + const calendarEventParticipantRepository = + await this.twentyORMManager.getRepository( + 'calendarEventParticipant', + ); + const calendarEventParticipantsWithoutPersonIdAndWorkspaceMemberId = - await this.calendarEventParticipantRepository.find({ + await calendarEventParticipantRepository.find({ where: { calendarEvent: { calendarChannelEventAssociations: { diff --git a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/services/calendar-event-participant.service.ts b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/services/calendar-event-participant.service.ts index 346e727d9..31ee08c19 100644 --- a/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/services/calendar-event-participant.service.ts +++ b/packages/twenty-server/src/modules/calendar/calendar-event-participant-manager/services/calendar-event-participant.service.ts @@ -5,16 +5,14 @@ import { isDefined } from 'class-validator'; import differenceWith from 'lodash.differencewith'; import { Any } from 'typeorm'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity'; import { CalendarEventParticipantWithCalendarEventId } from 'src/modules/calendar/common/types/calendar-event'; @Injectable() export class CalendarEventParticipantService { constructor( - @InjectWorkspaceRepository(CalendarEventParticipantWorkspaceEntity) - private readonly calendarEventParticipantRepository: WorkspaceRepository, + private readonly twentyORMManager: TwentyORMManager, private readonly eventEmitter: EventEmitter2, ) {} @@ -23,8 +21,13 @@ export class CalendarEventParticipantService { participantsToUpdate: CalendarEventParticipantWithCalendarEventId[], transactionManager?: any, ): Promise { + const calendarEventParticipantRepository = + await this.twentyORMManager.getRepository( + 'calendarEventParticipant', + ); + const existingCalendarEventParticipants = - await this.calendarEventParticipantRepository.find({ + await calendarEventParticipantRepository.find({ where: { calendarEventId: Any( participantsToUpdate @@ -74,7 +77,7 @@ export class CalendarEventParticipantService { participantToUpdate.calendarEventId, ); - await this.calendarEventParticipantRepository.delete( + await calendarEventParticipantRepository.delete( { id: Any( calendarEventParticipantsToDelete.map( @@ -86,7 +89,7 @@ export class CalendarEventParticipantService { ); for (const calendarEventParticipantToUpdate of calendarEventParticipantsToUpdate) { - await this.calendarEventParticipantRepository.update( + await calendarEventParticipantRepository.update( { calendarEventId: calendarEventParticipantToUpdate.calendarEventId, handle: calendarEventParticipantToUpdate.handle, @@ -100,7 +103,7 @@ export class CalendarEventParticipantService { participantsToSave.push(...newCalendarEventParticipants); - await this.calendarEventParticipantRepository.save( + await calendarEventParticipantRepository.save( participantsToSave, {}, transactionManager, @@ -113,8 +116,13 @@ export class CalendarEventParticipantService { personId?: string, workspaceMemberId?: string, ) { + const calendarEventParticipantRepository = + await this.twentyORMManager.getRepository( + 'calendarEventParticipant', + ); + const calendarEventParticipantsToUpdate = - await this.calendarEventParticipantRepository.find({ + await calendarEventParticipantRepository.find({ where: { handle: email, }, @@ -124,7 +132,7 @@ export class CalendarEventParticipantService { calendarEventParticipantsToUpdate.map((participant) => participant.id); if (personId) { - await this.calendarEventParticipantRepository.update( + await calendarEventParticipantRepository.update( { id: Any(calendarEventParticipantIdsToUpdate), }, @@ -136,7 +144,7 @@ export class CalendarEventParticipantService { ); const updatedCalendarEventParticipants = - await this.calendarEventParticipantRepository.find({ + await calendarEventParticipantRepository.find({ where: { id: Any(calendarEventParticipantIdsToUpdate), }, @@ -149,7 +157,7 @@ export class CalendarEventParticipantService { }); } if (workspaceMemberId) { - await this.calendarEventParticipantRepository.update( + await calendarEventParticipantRepository.update( { id: Any(calendarEventParticipantIdsToUpdate), }, @@ -168,8 +176,13 @@ export class CalendarEventParticipantService { personId?: string, workspaceMemberId?: string, ) { + const calendarEventParticipantRepository = + await this.twentyORMManager.getRepository( + 'calendarEventParticipant', + ); + if (personId) { - await this.calendarEventParticipantRepository.update( + await calendarEventParticipantRepository.update( { handle, }, @@ -179,7 +192,7 @@ export class CalendarEventParticipantService { ); } if (workspaceMemberId) { - await this.calendarEventParticipantRepository.update( + await calendarEventParticipantRepository.update( { handle, }, diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts index 8660401f1..e1135b914 100644 --- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts @@ -1,11 +1,10 @@ import { BadRequestException, NotFoundException, Scope } from '@nestjs/common'; -import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface'; +import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { CanAccessCalendarEventService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service'; import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity'; @@ -17,8 +16,7 @@ export class CalendarEventFindManyPreQueryHook implements WorkspaceQueryHookInstance { constructor( - @InjectWorkspaceRepository(CalendarChannelEventAssociationWorkspaceEntity) - private readonly calendarChannelEventAssociationRepository: WorkspaceRepository, + private readonly twentyORMManager: TwentyORMManager, private readonly canAccessCalendarEventService: CanAccessCalendarEventService, ) {} @@ -31,8 +29,13 @@ export class CalendarEventFindManyPreQueryHook throw new BadRequestException('id filter is required'); } + const calendarChannelEventAssociationRepository = + await this.twentyORMManager.getRepository( + 'calendarChannelEventAssociation', + ); + const calendarChannelCalendarEventAssociations = - await this.calendarChannelEventAssociationRepository.find({ + await calendarChannelEventAssociationRepository.find({ where: { calendarEventId: payload?.filter?.id?.eq, }, diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts index add123542..1dd82f205 100644 --- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts +++ b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts @@ -4,8 +4,7 @@ import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-que import { FindOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { CanAccessCalendarEventService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service'; import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity'; @@ -17,8 +16,7 @@ export class CalendarEventFindOnePreQueryHook implements WorkspaceQueryHookInstance { constructor( - @InjectWorkspaceRepository(CalendarChannelEventAssociationWorkspaceEntity) - private readonly calendarChannelEventAssociationRepository: WorkspaceRepository, + private readonly twentyORMManager: TwentyORMManager, private readonly canAccessCalendarEventService: CanAccessCalendarEventService, ) {} @@ -31,9 +29,14 @@ export class CalendarEventFindOnePreQueryHook throw new BadRequestException('id filter is required'); } + const calendarChannelEventAssociationRepository = + await this.twentyORMManager.getRepository( + 'calendarChannelEventAssociation', + ); + // TODO: Re-implement this using twenty ORM const calendarChannelCalendarEventAssociations = - await this.calendarChannelEventAssociationRepository.find({ + await calendarChannelEventAssociationRepository.find({ where: { calendarEventId: payload?.filter?.id?.eq, }, diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service.ts index fcd05354a..1b083eaa4 100644 --- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service.ts +++ b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service.ts @@ -4,23 +4,21 @@ import groupBy from 'lodash.groupby'; import { Any } from 'typeorm'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity'; +import { + CalendarChannelVisibility, + CalendarChannelWorkspaceEntity, +} from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; 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 { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; -import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity'; -import { - CalendarChannelWorkspaceEntity, - CalendarChannelVisibility, -} from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; @Injectable() export class CanAccessCalendarEventService { constructor( - @InjectWorkspaceRepository(CalendarChannelWorkspaceEntity) - private readonly calendarChannelRepository: WorkspaceRepository, + private readonly twentyORMManager: TwentyORMManager, @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) private readonly connectedAccountRepository: ConnectedAccountRepository, @InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity) @@ -32,7 +30,12 @@ export class CanAccessCalendarEventService { workspaceId: string, calendarChannelCalendarEventAssociations: CalendarChannelEventAssociationWorkspaceEntity[], ) { - const calendarChannels = await this.calendarChannelRepository.find({ + const calendarRepository = + await this.twentyORMManager.getRepository( + 'calendarChannel', + ); + + const calendarChannels = await calendarRepository.find({ where: { id: Any( calendarChannelCalendarEventAssociations.map( diff --git a/packages/twenty-server/src/modules/connected-account/query-hooks/connected-account-delete-one.pre-query.hook.ts b/packages/twenty-server/src/modules/connected-account/query-hooks/connected-account-delete-one.pre-query.hook.ts index 9296263df..b2d81a670 100644 --- a/packages/twenty-server/src/modules/connected-account/query-hooks/connected-account-delete-one.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/connected-account/query-hooks/connected-account-delete-one.pre-query.hook.ts @@ -4,18 +4,16 @@ import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-que import { DeleteOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; @WorkspaceQueryHook(`connectedAccount.deleteOne`) export class ConnectedAccountDeleteOnePreQueryHook implements WorkspaceQueryHookInstance { constructor( - @InjectWorkspaceRepository(MessageChannelWorkspaceEntity) - private readonly messageChannelRepository: WorkspaceRepository, + private readonly twentyORMManager: TwentyORMManager, private eventEmitter: EventEmitter2, ) {} @@ -26,7 +24,12 @@ export class ConnectedAccountDeleteOnePreQueryHook ): Promise { const connectedAccountId = payload.id; - const messageChannels = await this.messageChannelRepository.findBy({ + const messageChannelRepository = + await this.twentyORMManager.getRepository( + 'messageChannel', + ); + + const messageChannels = await messageChannelRepository.findBy({ connectedAccountId, }); diff --git a/packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts index 21b9f5b28..bb9524b41 100644 --- a/packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts @@ -2,22 +2,26 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; 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 { deleteUsingPagination } from 'src/modules/messaging/message-cleaner/utils/delete-using-pagination.util'; @Injectable() export class MessagingMessageCleanerService { - constructor( - @InjectWorkspaceRepository(MessageWorkspaceEntity) - private readonly messageRepository: WorkspaceRepository, - @InjectWorkspaceRepository(MessageThreadWorkspaceEntity) - private readonly messageThreadRepository: WorkspaceRepository, - ) {} + constructor(private readonly twentyORMManager: TwentyORMManager) {} public async cleanWorkspaceThreads(workspaceId: string) { + const messageThreadRepository = + await this.twentyORMManager.getRepository( + 'messageThread', + ); + + const messageRepository = + await this.twentyORMManager.getRepository( + 'message', + ); + await deleteUsingPagination( workspaceId, 500, @@ -27,7 +31,7 @@ export class MessagingMessageCleanerService { workspaceId: string, transactionManager?: EntityManager, ) => { - const nonAssociatedMessages = await this.messageRepository.find( + const nonAssociatedMessages = await messageRepository.find( { where: { messageChannelMessageAssociations: [], @@ -46,7 +50,7 @@ export class MessagingMessageCleanerService { workspaceId: string, transactionManager?: EntityManager, ) => { - await this.messageRepository.delete(ids, transactionManager); + await messageRepository.delete(ids, transactionManager); }, ); @@ -59,7 +63,7 @@ export class MessagingMessageCleanerService { workspaceId: string, transactionManager?: EntityManager, ) => { - const orphanThreads = await this.messageThreadRepository.find( + const orphanThreads = await messageThreadRepository.find( { where: { messages: [], @@ -77,7 +81,7 @@ export class MessagingMessageCleanerService { workspaceId: string, transactionManager?: EntityManager, ) => { - await this.messageThreadRepository.delete(ids, transactionManager); + await messageThreadRepository.delete(ids, transactionManager); }, ); } diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-ongoing-stale.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-ongoing-stale.job.ts index 0eb3c2aa1..45e2b4ec2 100644 --- a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-ongoing-stale.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-ongoing-stale.job.ts @@ -5,14 +5,13 @@ import { In } from 'typeorm'; import { Process } from 'src/engine/integrations/message-queue/decorators/process.decorator'; import { Processor } from 'src/engine/integrations/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; +import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; import { MessageChannelSyncStage, MessageChannelWorkspaceEntity, } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { isSyncStale } from 'src/modules/messaging/message-import-manager/utils/is-sync-stale.util'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; export type MessagingOngoingStaleJobData = { workspaceId: string; @@ -25,8 +24,7 @@ export type MessagingOngoingStaleJobData = { export class MessagingOngoingStaleJob { private readonly logger = new Logger(MessagingOngoingStaleJob.name); constructor( - @InjectWorkspaceRepository(MessageChannelWorkspaceEntity) - private readonly messageChannelRepository: WorkspaceRepository, + private readonly twentyORMManager: TwentyORMManager, private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService, ) {} @@ -34,7 +32,12 @@ export class MessagingOngoingStaleJob { async handle(data: MessagingOngoingStaleJobData): Promise { const { workspaceId } = data; - const messageChannels = await this.messageChannelRepository.find({ + const messageChannelRepository = + await this.twentyORMManager.getRepository( + 'messageChannel', + ); + + const messageChannels = await messageChannelRepository.find({ where: { syncStage: In([ MessageChannelSyncStage.MESSAGES_IMPORT_ONGOING, 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 e068da436..235da83ef 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 @@ -2,8 +2,7 @@ import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-que import { DeleteOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator'; -import { InjectWorkspaceRepository } from 'src/engine/twenty-orm/decorators/inject-workspace-repository.decorator'; -import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; +import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; import { CommentWorkspaceEntity } from 'src/modules/activity/standard-objects/comment.workspace-entity'; import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity'; @@ -11,12 +10,7 @@ import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objec export class WorkspaceMemberDeleteOnePreQueryHook implements WorkspaceQueryHookInstance { - constructor( - @InjectWorkspaceRepository(AttachmentWorkspaceEntity) - private readonly attachmentRepository: WorkspaceRepository, - @InjectWorkspaceRepository(CommentWorkspaceEntity) - private readonly commentRepository: WorkspaceRepository, - ) {} + constructor(private readonly twentyORMManager: TwentyORMManager) {} // There is no need to validate the user's access to the workspace member since we don't have permission yet. async execute( @@ -24,13 +18,23 @@ export class WorkspaceMemberDeleteOnePreQueryHook workspaceId: string, payload: DeleteOneResolverArgs, ): Promise { + const attachmentRepository = + await this.twentyORMManager.getRepository( + 'attachment', + ); + + const commentRepository = + await this.twentyORMManager.getRepository( + 'comment', + ); + const authorId = payload.id; - await this.attachmentRepository.delete({ + await attachmentRepository.delete({ authorId, }); - await this.commentRepository.delete({ + await commentRepository.delete({ authorId, }); }