From 715453adc35fa5b9bb2b6a3ba55f15828917a490 Mon Sep 17 00:00:00 2001 From: martmull Date: Thu, 2 May 2024 10:11:45 +0200 Subject: [PATCH 1/5] Rename method --- .../core-modules/workspace/services/workspace.service.ts | 4 ++-- .../commands/delete-incomplete-workspaces.command.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts index 532ae2fa6eaf..d6747cd22608 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts @@ -49,7 +49,7 @@ export class WorkspaceService extends TypeOrmQueryService { return await this.workspaceManagerService.doesDataSourceExist(id); } - async solfDeleteWorkspace(id: string) { + async softDeleteWorkspace(id: string) { const workspace = await this.workspaceRepository.findOneBy({ id }); assert(workspace, 'Workspace not found'); @@ -67,7 +67,7 @@ export class WorkspaceService extends TypeOrmQueryService { workspaceId: id, }); - const workspace = await this.solfDeleteWorkspace(id); + const workspace = await this.softDeleteWorkspace(id); for (const userWorkspace of userWorkspaces) { await this.userService.handleRemoveWorkspaceMember( diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/delete-incomplete-workspaces.command.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/delete-incomplete-workspaces.command.ts index 372968b1c8a5..30c980c4e0c1 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/delete-incomplete-workspaces.command.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/commands/delete-incomplete-workspaces.command.ts @@ -83,7 +83,7 @@ export class DeleteIncompleteWorkspacesCommand extends CommandRunner { } name: '${incompleteWorkspace.displayName}'`, ); if (!options.dryRun) { - await this.workspaceService.solfDeleteWorkspace(incompleteWorkspace.id); + await this.workspaceService.softDeleteWorkspace(incompleteWorkspace.id); } } } From e1530be64f664233d800c258907e9f0566532400 Mon Sep 17 00:00:00 2001 From: martmull Date: Thu, 2 May 2024 13:54:57 +0200 Subject: [PATCH 2/5] Fix delete user --- .../core-modules/billing/billing.service.ts | 8 ++ .../user/services/user.service.ts | 80 ++++++++----------- .../engine/core-modules/user/user.module.ts | 7 +- .../handle-workspace-member-deleted.job.ts | 9 ++- .../workspace/services/workspace.service.ts | 51 ++++++++++-- .../workspace/workspace.module.ts | 5 +- .../integrations/message-queue/jobs.module.ts | 2 + 7 files changed, 99 insertions(+), 63 deletions(-) diff --git a/packages/twenty-server/src/engine/core-modules/billing/billing.service.ts b/packages/twenty-server/src/engine/core-modules/billing/billing.service.ts index add42ae0b6a9..276989eaaa45 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/billing.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/billing.service.ts @@ -274,6 +274,14 @@ export class BillingService { }, ); + const workspace = this.workspaceRepository.find({ + where: { id: workspaceId }, + }); + + if (!workspace) { + return; + } + await this.workspaceRepository.update(workspaceId, { subscriptionStatus: data.object.status, }); 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 998066e0b6ff..f3128670bbe5 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 @@ -1,4 +1,5 @@ import { InjectRepository } from '@nestjs/typeorm'; +import { EventEmitter2 } from '@nestjs/event-emitter'; import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import { Repository } from 'typeorm'; @@ -8,17 +9,20 @@ import { User } from 'src/engine/core-modules/user/user.entity'; import { WorkspaceMember } from 'src/engine/core-modules/user/dtos/workspace-member.dto'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { TypeORMService } from 'src/database/typeorm/typeorm.service'; -import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; +import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; +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 { constructor( @InjectRepository(User, 'core') private readonly userRepository: Repository, - @InjectRepository(UserWorkspace, 'core') - private readonly userWorkspaceRepository: Repository, private readonly dataSourceService: DataSourceService, private readonly typeORMService: TypeORMService, + private readonly eventEmitter: EventEmitter2, + private readonly workspaceService: WorkspaceService, ) { super(userRepository); } @@ -95,64 +99,46 @@ export class UserService extends TypeOrmQueryService { assert(user, 'User not found'); + const workspaceId = user.defaultWorkspaceId; + const dataSourceMetadata = await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail( - user.defaultWorkspace.id, + workspaceId, ); const workspaceDataSource = await this.typeORMService.connectToDataSource(dataSourceMetadata); - await workspaceDataSource?.query( - `DELETE FROM ${dataSourceMetadata.schema}."workspaceMember" WHERE "userId" = '${userId}'`, + const workspaceMembers = await workspaceDataSource?.query( + `SELECT * FROM ${dataSourceMetadata.schema}."workspaceMember"`, ); + const workspaceMember = workspaceMembers.filter( + (member: ObjectRecord) => + member.userId === userId, + )?.[0]; - await this.userWorkspaceRepository.delete({ userId }); - - await this.userRepository.delete(user.id); - - return user; - } - - async handleRemoveWorkspaceMember(workspaceId: string, userId: string) { - await this.userWorkspaceRepository.delete({ - userId, - workspaceId, - }); - await this.reassignOrRemoveUserDefaultWorkspace(workspaceId, userId); - } - - private async reassignOrRemoveUserDefaultWorkspace( - workspaceId: string, - userId: string, - ) { - const userWorkspaces = await this.userWorkspaceRepository.find({ - where: { userId: userId }, - }); + assert(workspaceMember, 'WorkspaceMember not found'); - if (userWorkspaces.length === 0) { - await this.userRepository.delete({ id: userId }); + if (workspaceMembers.length === 1) { + await this.workspaceService.deleteWorkspace(workspaceId); - return; + return user; } - const user = await this.userRepository.findOne({ - where: { - id: userId, - }, - }); + await workspaceDataSource?.query( + `DELETE FROM ${dataSourceMetadata.schema}."workspaceMember" WHERE "userId" = '${userId}'`, + ); + const payload = + new ObjectRecordDeleteEvent(); - if (!user) { - throw new Error(`User ${userId} not found in workspace ${workspaceId}`); - } + payload.workspaceId = workspaceId; + payload.properties = { + before: workspaceMember, + }; + payload.recordId = workspaceMember.id; - if (user.defaultWorkspaceId === workspaceId) { - await this.userRepository.update( - { id: userId }, - { - defaultWorkspaceId: userWorkspaces[0].workspaceId, - }, - ); - } + this.eventEmitter.emit('workspaceMember.deleted', payload); + + return user; } } diff --git a/packages/twenty-server/src/engine/core-modules/user/user.module.ts b/packages/twenty-server/src/engine/core-modules/user/user.module.ts index 81b3a708347c..37b92b46bcb0 100644 --- a/packages/twenty-server/src/engine/core-modules/user/user.module.ts +++ b/packages/twenty-server/src/engine/core-modules/user/user.module.ts @@ -9,9 +9,8 @@ import { UserResolver } from 'src/engine/core-modules/user/user.resolver'; import { TypeORMService } from 'src/database/typeorm/typeorm.service'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; -import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user-workspace.module'; -import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module'; +import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; import { userAutoResolverOpts } from './user.auto-resolver-opts'; @@ -21,14 +20,14 @@ import { UserService } from './services/user.service'; imports: [ NestjsQueryGraphQLModule.forFeature({ imports: [ - NestjsQueryTypeOrmModule.forFeature([User, UserWorkspace], 'core'), + NestjsQueryTypeOrmModule.forFeature([User], 'core'), TypeORMModule, ], resolvers: userAutoResolverOpts, }), DataSourceModule, FileUploadModule, - UserWorkspaceModule, + WorkspaceModule, ], exports: [UserService], providers: [UserService, UserResolver, TypeORMService], diff --git a/packages/twenty-server/src/engine/core-modules/workspace/handle-workspace-member-deleted.job.ts b/packages/twenty-server/src/engine/core-modules/workspace/handle-workspace-member-deleted.job.ts index 7f36247c1eb1..8ec5dad7ded7 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/handle-workspace-member-deleted.job.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/handle-workspace-member-deleted.job.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; -import { UserService } from 'src/engine/core-modules/user/services/user.service'; +import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service'; export type HandleWorkspaceMemberDeletedJobData = { workspaceId: string; @@ -12,11 +12,14 @@ export type HandleWorkspaceMemberDeletedJobData = { export class HandleWorkspaceMemberDeletedJob implements MessageQueueJob { - constructor(private readonly userService: UserService) {} + constructor(private readonly workspaceService: WorkspaceService) {} async handle(data: HandleWorkspaceMemberDeletedJobData): Promise { const { workspaceId, userId } = data; - await this.userService.handleRemoveWorkspaceMember(workspaceId, userId); + await this.workspaceService.handleRemoveWorkspaceMember( + workspaceId, + userId, + ); } } diff --git a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts index d6747cd22608..d490f9c04625 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts @@ -13,18 +13,18 @@ import { ActivateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/a import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service'; import { BillingService } from 'src/engine/core-modules/billing/billing.service'; -import { UserService } from 'src/engine/core-modules/user/services/user.service'; export class WorkspaceService extends TypeOrmQueryService { constructor( @InjectRepository(Workspace, 'core') private readonly workspaceRepository: Repository, + @InjectRepository(User, 'core') + private readonly userRepository: Repository, @InjectRepository(UserWorkspace, 'core') private readonly userWorkspaceRepository: Repository, private readonly workspaceManagerService: WorkspaceManagerService, private readonly userWorkspaceService: UserWorkspaceService, private readonly billingService: BillingService, - private readonly userService: UserService, ) { super(workspaceRepository); } @@ -70,10 +70,7 @@ export class WorkspaceService extends TypeOrmQueryService { const workspace = await this.softDeleteWorkspace(id); for (const userWorkspace of userWorkspaces) { - await this.userService.handleRemoveWorkspaceMember( - id, - userWorkspace.userId, - ); + await this.handleRemoveWorkspaceMember(id, userWorkspace.userId); } await this.workspaceRepository.delete(id); @@ -85,4 +82,46 @@ export class WorkspaceService extends TypeOrmQueryService { .find() .then((workspaces) => workspaces.map((workspace) => workspace.id)); } + + async handleRemoveWorkspaceMember(workspaceId: string, userId: string) { + await this.userWorkspaceRepository.delete({ + userId, + workspaceId, + }); + await this.reassignOrRemoveUserDefaultWorkspace(workspaceId, userId); + } + + private async reassignOrRemoveUserDefaultWorkspace( + workspaceId: string, + userId: string, + ) { + const userWorkspaces = await this.userWorkspaceRepository.find({ + where: { userId: userId }, + }); + + if (userWorkspaces.length === 0) { + await this.userRepository.delete({ id: userId }); + + return; + } + + const user = await this.userRepository.findOne({ + where: { + id: userId, + }, + }); + + if (!user) { + throw new Error(`User ${userId} not found in workspace ${workspaceId}`); + } + + if (user.defaultWorkspaceId === workspaceId) { + await this.userRepository.update( + { id: userId }, + { + defaultWorkspaceId: userWorkspaces[0].workspaceId, + }, + ); + } + } } diff --git a/packages/twenty-server/src/engine/core-modules/workspace/workspace.module.ts b/packages/twenty-server/src/engine/core-modules/workspace/workspace.module.ts index 63b821476948..ad5ad20ed2fe 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/workspace.module.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/workspace.module.ts @@ -12,9 +12,9 @@ import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user import { BillingModule } from 'src/engine/core-modules/billing/billing.module'; import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; -import { UserModule } from 'src/engine/core-modules/user/user.module'; import { WorkspaceWorkspaceMemberListener } from 'src/engine/core-modules/workspace/workspace-workspace-member.listener'; import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module'; +import { User } from 'src/engine/core-modules/user/user.entity'; import { workspaceAutoResolverOpts } from './workspace.auto-resolver-opts'; import { Workspace } from './workspace.entity'; @@ -30,14 +30,13 @@ import { WorkspaceService } from './services/workspace.service'; FileUploadModule, WorkspaceCacheVersionModule, NestjsQueryTypeOrmModule.forFeature( - [Workspace, UserWorkspace, FeatureFlagEntity], + [User, Workspace, UserWorkspace, FeatureFlagEntity], 'core', ), UserWorkspaceModule, WorkspaceManagerModule, DataSourceModule, TypeORMModule, - UserModule, ], services: [WorkspaceService], resolvers: workspaceAutoResolverOpts, diff --git a/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts b/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts index 8227eb7b1e29..ad3c11410d19 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts +++ b/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts @@ -61,6 +61,7 @@ import { MessageChannelMessageAssociationObjectMetadata } from 'src/modules/mess import { MessageChannelObjectMetadata } from 'src/modules/messaging/standard-objects/message-channel.object-metadata'; import { BlocklistItemDeleteCalendarEventsJob } from 'src/modules/calendar/jobs/blocklist-item-delete-calendar-events.job'; import { BlocklistReimportCalendarEventsJob } from 'src/modules/calendar/jobs/blocklist-reimport-calendar-events.job'; +import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; @Module({ imports: [ @@ -81,6 +82,7 @@ import { BlocklistReimportCalendarEventsJob } from 'src/modules/calendar/jobs/bl TypeOrmModule.forFeature([DataSourceEntity], 'metadata'), UserModule, UserWorkspaceModule, + WorkspaceModule, WorkspaceDataSourceModule, RecordPositionBackfillModule, GoogleAPIRefreshAccessTokenModule, From d3d4310b8acddbc37edef48287d4074a01c13b10 Mon Sep 17 00:00:00 2001 From: martmull Date: Thu, 2 May 2024 16:23:04 +0200 Subject: [PATCH 3/5] Fix tests --- .../core-modules/user/services/user.service.spec.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/twenty-server/src/engine/core-modules/user/services/user.service.spec.ts b/packages/twenty-server/src/engine/core-modules/user/services/user.service.spec.ts index 64228c0eaf20..d7bef57c1bbb 100644 --- a/packages/twenty-server/src/engine/core-modules/user/services/user.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/user/services/user.service.spec.ts @@ -1,10 +1,12 @@ import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; +import { EventEmitter2 } from '@nestjs/event-emitter'; import { User } from 'src/engine/core-modules/user/user.entity'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { TypeORMService } from 'src/database/typeorm/typeorm.service'; import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; +import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service'; import { UserService } from './user.service'; @@ -31,6 +33,14 @@ describe('UserService', () => { provide: TypeORMService, useValue: {}, }, + { + provide: EventEmitter2, + useValue: {}, + }, + { + provide: WorkspaceService, + useValue: {}, + }, ], }).compile(); From d3c6689df605faaf844f63e0962eb0e3086d66fa Mon Sep 17 00:00:00 2001 From: martmull Date: Thu, 2 May 2024 21:53:24 +0200 Subject: [PATCH 4/5] Handle stripe webhook error --- .../core-modules/billing/billing.service.ts | 28 +++++++++---------- .../workspace/services/workspace.service.ts | 1 + 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/twenty-server/src/engine/core-modules/billing/billing.service.ts b/packages/twenty-server/src/engine/core-modules/billing/billing.service.ts index 276989eaaa45..c192e2e07b86 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/billing.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/billing.service.ts @@ -260,20 +260,6 @@ export class BillingService { | Stripe.CustomerSubscriptionCreatedEvent.Data | Stripe.CustomerSubscriptionDeletedEvent.Data, ) { - await this.billingSubscriptionRepository.upsert( - { - workspaceId: workspaceId, - stripeCustomerId: data.object.customer as string, - stripeSubscriptionId: data.object.id, - status: data.object.status, - interval: data.object.items.data[0].plan.interval, - }, - { - conflictPaths: ['stripeSubscriptionId'], - skipUpdateIfNoValuesChanged: true, - }, - ); - const workspace = this.workspaceRepository.find({ where: { id: workspaceId }, }); @@ -294,6 +280,20 @@ export class BillingService { return; } + await this.billingSubscriptionRepository.upsert( + { + workspaceId: workspaceId, + stripeCustomerId: data.object.customer as string, + stripeSubscriptionId: data.object.id, + status: data.object.status, + interval: data.object.items.data[0].plan.interval, + }, + { + conflictPaths: ['stripeSubscriptionId'], + skipUpdateIfNoValuesChanged: true, + }, + ); + await this.billingSubscriptionItemRepository.upsert( data.object.items.data.map((item) => { return { diff --git a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts index d490f9c04625..f4248d467743 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/services/workspace.service.ts @@ -72,6 +72,7 @@ export class WorkspaceService extends TypeOrmQueryService { for (const userWorkspace of userWorkspaces) { await this.handleRemoveWorkspaceMember(id, userWorkspace.userId); } + await this.workspaceRepository.delete(id); return workspace; From a7590ee4f004b8ef4e607979883bf1f0a1968910 Mon Sep 17 00:00:00 2001 From: martmull Date: Fri, 3 May 2024 15:41:24 +0200 Subject: [PATCH 5/5] Fix useless error --- .../core-modules/billing/billing.service.ts | 15 +++-------- .../billing/jobs/update-subscription.job.ts | 2 +- .../user-workspace/user-workspace.service.ts | 26 ++++++++++++------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/packages/twenty-server/src/engine/core-modules/billing/billing.service.ts b/packages/twenty-server/src/engine/core-modules/billing/billing.service.ts index c192e2e07b86..356cdec4e7fd 100644 --- a/packages/twenty-server/src/engine/core-modules/billing/billing.service.ts +++ b/packages/twenty-server/src/engine/core-modules/billing/billing.service.ts @@ -196,7 +196,10 @@ export class BillingService { ? frontBaseUrl + successUrlPath : frontBaseUrl; - let quantity = 1; + const quantity = + (await this.userWorkspaceService.getWorkspaceMemberCount( + user.defaultWorkspaceId, + )) || 1; const stripeCustomerId = ( await this.billingSubscriptionRepository.findOneBy({ @@ -204,16 +207,6 @@ export class BillingService { }) )?.stripeCustomerId; - try { - quantity = await this.userWorkspaceService.getWorkspaceMemberCount( - user.defaultWorkspaceId, - ); - } catch (e) { - this.logger.error( - `Failed to get workspace member count for workspace ${user.defaultWorkspaceId}`, - ); - } - const session = await this.stripeService.createCheckoutSession( user, priceId, 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 8dc74ab6c66f..cf3ff0367a8d 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 @@ -21,7 +21,7 @@ export class UpdateSubscriptionJob const workspaceMembersCount = await this.userWorkspaceService.getWorkspaceMemberCount(data.workspaceId); - if (workspaceMembersCount <= 0) { + if (!workspaceMembersCount || workspaceMembersCount <= 0) { return; } 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 e61d1337f176..0e8fc4c6f738 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 @@ -70,17 +70,23 @@ export class UserWorkspaceService extends TypeOrmQueryService { this.eventEmitter.emit('workspaceMember.created', payload); } - public async getWorkspaceMemberCount(workspaceId: string): Promise { - const dataSourceSchema = - this.workspaceDataSourceService.getSchemaName(workspaceId); + public async getWorkspaceMemberCount( + workspaceId: string, + ): Promise { + try { + const dataSourceSchema = + this.workspaceDataSourceService.getSchemaName(workspaceId); - return ( - await this.workspaceDataSourceService.executeRawQuery( - `SELECT * FROM ${dataSourceSchema}."workspaceMember"`, - [], - workspaceId, - ) - ).length; + return ( + await this.workspaceDataSourceService.executeRawQuery( + `SELECT * FROM ${dataSourceSchema}."workspaceMember"`, + [], + workspaceId, + ) + ).length; + } catch { + return undefined; + } } async checkUserWorkspaceExists(