From d23511ea5e5af2987b3fff60c343b27e4f353443 Mon Sep 17 00:00:00 2001 From: Abdul Rahman <81605929+abdulrahmancodes@users.noreply.github.com> Date: Fri, 10 Jul 2026 16:59:58 +0530 Subject: [PATCH] remove nestjs-query from user and workspace resolvers (#22766) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What Migrates the `user` and `workspace` core modules off `@ptc-org/nestjs-query`. Both used `NestjsQueryGraphQLModule` only as scaffolding — all CRUD was disabled and the real GraphQL API is already served by the hand-written `UserResolver` / `WorkspaceResolver`. Review in cubic --------- Co-authored-by: Weiko --- .../user/services/user.service.ts | 11 ++- .../user/user.auto-resolver-opts.ts | 41 ---------- .../engine/core-modules/user/user.entity.ts | 3 +- .../engine/core-modules/user/user.module.ts | 18 +---- .../workspace/services/workspace.service.ts | 7 +- .../workspace/workspace.auto-resolver-opts.ts | 43 ---------- .../workspace/workspace.entity.ts | 3 +- .../workspace/workspace.module.ts | 78 ++++++++----------- .../workspace/workspace.resolver.ts | 2 +- 9 files changed, 45 insertions(+), 161 deletions(-) delete mode 100644 packages/twenty-server/src/engine/core-modules/user/user.auto-resolver-opts.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/workspace/workspace.auto-resolver-opts.ts diff --git a/packages/twenty-server/src/engine/core-modules/user/services/user.service.ts b/packages/twenty-server/src/engine/core-modules/user/services/user.service.ts index 69d2406d29..a111e102ea 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 @@ -3,7 +3,6 @@ import { InjectRepository } from '@nestjs/typeorm'; import assert from 'assert'; import { msg } from '@lingui/core/macro'; -import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import { isNonEmptyString } from '@sniptt/guards'; import { SOURCE_LOCALE } from 'twenty-shared/translations'; import { assertIsDefinedOrThrow, isDefined } from 'twenty-shared/utils'; @@ -52,7 +51,7 @@ import { STANDARD_ROLE } from 'src/engine/workspace-manager/twenty-standard-appl import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; // oxlint-disable-next-line twenty/inject-workspace-repository -export class UserService extends TypeOrmQueryService { +export class UserService { constructor( @InjectRepository(UserEntity) private readonly userRepository: Repository, @@ -70,9 +69,7 @@ export class UserService extends TypeOrmQueryService { private readonly coreEntityCacheService: CoreEntityCacheService, private readonly workspaceMemberTranspiler: WorkspaceMemberTranspiler, private readonly twentyConfigService: TwentyConfigService, - ) { - super(userRepository); - } + ) {} async refreshWorkspaceIfPendingOrOngoingCreation< TWorkspace extends Pick, @@ -86,7 +83,9 @@ export class UserService extends TypeOrmQueryService { return workspace; } - const freshWorkspace = await this.workspaceService.findById(workspace.id); + const freshWorkspace = await this.workspaceService.findOneWorkspaceById( + workspace.id, + ); return freshWorkspace ?? workspace; } diff --git a/packages/twenty-server/src/engine/core-modules/user/user.auto-resolver-opts.ts b/packages/twenty-server/src/engine/core-modules/user/user.auto-resolver-opts.ts deleted file mode 100644 index 2542a7c328..0000000000 --- a/packages/twenty-server/src/engine/core-modules/user/user.auto-resolver-opts.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { - type AutoResolverOpts, - PagingStrategies, - type ReadResolverOpts, -} from '@ptc-org/nestjs-query-graphql'; - -import { UserEntity } from 'src/engine/core-modules/user/user.entity'; -import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; - -export const userAutoResolverOpts: AutoResolverOpts< - // oxlint-disable-next-line typescript/no-explicit-any - any, - // oxlint-disable-next-line typescript/no-explicit-any - any, - unknown, - unknown, - // oxlint-disable-next-line typescript/no-explicit-any - ReadResolverOpts, - PagingStrategies ->[] = [ - { - EntityClass: UserEntity, - DTOClass: UserEntity, - enableTotalCount: true, - pagingStrategy: PagingStrategies.CURSOR, - read: { - many: { disabled: true }, - one: { disabled: true }, - }, - create: { - many: { disabled: true }, - one: { disabled: true }, - }, - update: { - many: { disabled: true }, - one: { disabled: true }, - }, - delete: { many: { disabled: true }, one: { disabled: true } }, - guards: [WorkspaceAuthGuard], - }, -]; diff --git a/packages/twenty-server/src/engine/core-modules/user/user.entity.ts b/packages/twenty-server/src/engine/core-modules/user/user.entity.ts index 718ca98758..897fd2ac46 100644 --- a/packages/twenty-server/src/engine/core-modules/user/user.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/user/user.entity.ts @@ -1,6 +1,5 @@ import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; -import { IDField } from '@ptc-org/nestjs-query-graphql'; import { APP_LOCALES, SOURCE_LOCALE } from 'twenty-shared/translations'; import { BeforeInsert, @@ -36,7 +35,7 @@ registerEnumType(OnboardingStatus, { where: '"deletedAt" IS NULL', }) export class UserEntity { - @IDField(() => UUIDScalarType) + @Field(() => UUIDScalarType) @PrimaryGeneratedColumn('uuid') id: string; 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 08768da2a0..6961440b04 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 @@ -1,9 +1,6 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'; -import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; - import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { CoreEntityCacheModule } from 'src/engine/core-entity-cache/core-entity-cache.module'; import { WorkspaceDomainsModule } from 'src/engine/core-modules/domain/workspace-domains/workspace-domains.module'; @@ -23,26 +20,17 @@ import { UserEntity } from 'src/engine/core-modules/user/user.entity'; import { UserResolver } from 'src/engine/core-modules/user/user.resolver'; import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; import { ConnectedAccountMetadataModule } from 'src/engine/metadata-modules/connected-account/connected-account-metadata.module'; -import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module'; import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module'; import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module'; -import { userAutoResolverOpts } from './user.auto-resolver-opts'; - import { UserService } from './services/user.service'; @Module({ imports: [ - NestjsQueryGraphQLModule.forFeature({ - imports: [ - NestjsQueryTypeOrmModule.forFeature([UserEntity]), - TypeORMModule, - FileModule, - ], - resolvers: userAutoResolverOpts, - }), - NestjsQueryTypeOrmModule.forFeature([ObjectMetadataEntity]), + TypeOrmModule.forFeature([UserEntity]), + TypeORMModule, + FileModule, WorkspaceModule, OnboardingModule, TypeOrmModule.forFeature([KeyValuePairEntity, UserWorkspaceEntity]), 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 980154c48c..aa3f03aba4 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 @@ -4,7 +4,6 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import assert from 'assert'; import { msg } from '@lingui/core/macro'; -import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import { PermissionFlagType } from 'twenty-shared/constants'; import { assertIsDefinedOrThrow, isDefined } from 'twenty-shared/utils'; import { WorkspaceActivationStatus } from 'twenty-shared/workspace'; @@ -83,7 +82,7 @@ const WORKSPACE_ACTIVATION_STALE_LOCK_TIMEOUT_MS = 5 * 60 * 1000; @Injectable() // oxlint-disable-next-line twenty/inject-workspace-repository -export class WorkspaceService extends TypeOrmQueryService { +export class WorkspaceService { protected readonly logger = new Logger(WorkspaceService.name); private readonly WORKSPACE_FIELD_PERMISSIONS: Record< @@ -149,9 +148,7 @@ export class WorkspaceService extends TypeOrmQueryService { private readonly upgradeMigrationService: UpgradeMigrationService, private readonly upgradeSequenceReaderService: UpgradeSequenceReaderService, private readonly sdkClientGenerationService: SdkClientGenerationService, - ) { - super(workspaceRepository); - } + ) {} async updateWorkspaceById({ payload, diff --git a/packages/twenty-server/src/engine/core-modules/workspace/workspace.auto-resolver-opts.ts b/packages/twenty-server/src/engine/core-modules/workspace/workspace.auto-resolver-opts.ts deleted file mode 100644 index 9b0bad2cac..0000000000 --- a/packages/twenty-server/src/engine/core-modules/workspace/workspace.auto-resolver-opts.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { - type AutoResolverOpts, - PagingStrategies, - type ReadResolverOpts, -} from '@ptc-org/nestjs-query-graphql'; - -import { UpdateWorkspaceInput } from 'src/engine/core-modules/workspace/dtos/update-workspace-input'; -import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; -import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity'; - -export const workspaceAutoResolverOpts: AutoResolverOpts< - // oxlint-disable-next-line typescript/no-explicit-any - any, - // oxlint-disable-next-line typescript/no-explicit-any - any, - unknown, - unknown, - // oxlint-disable-next-line typescript/no-explicit-any - ReadResolverOpts, - PagingStrategies ->[] = [ - { - EntityClass: WorkspaceEntity, - DTOClass: WorkspaceEntity, - UpdateDTOClass: UpdateWorkspaceInput, - enableTotalCount: true, - pagingStrategy: PagingStrategies.CURSOR, - read: { - many: { disabled: true }, - one: { disabled: true }, - }, - create: { - many: { disabled: true }, - one: { disabled: true }, - }, - update: { - one: { disabled: true }, - many: { disabled: true }, - }, - delete: { many: { disabled: true }, one: { disabled: true } }, - guards: [WorkspaceAuthGuard], - }, -]; diff --git a/packages/twenty-server/src/engine/core-modules/workspace/workspace.entity.ts b/packages/twenty-server/src/engine/core-modules/workspace/workspace.entity.ts index 4093c2041c..829298caa1 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/workspace.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/workspace.entity.ts @@ -1,6 +1,5 @@ import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; -import { IDField } from '@ptc-org/nestjs-query-graphql'; import { type Application } from 'cloudflare/resources/zero-trust/access/applications/applications'; import { WorkspaceActivationStatus } from 'twenty-shared/workspace'; import { @@ -70,7 +69,7 @@ registerEnumType(WorkspaceDiscoverability, { @ObjectType('Workspace') export class WorkspaceEntity { // Fields - @IDField(() => UUIDScalarType) + @Field(() => UUIDScalarType) @PrimaryGeneratedColumn('uuid') id: string; 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 b06ddfb685..b8365fc978 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 @@ -1,9 +1,6 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'; -import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; - import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { ApplicationModule } from 'src/engine/core-modules/application/application.module'; import { PreInstalledAppsModule } from 'src/engine/core-modules/application/pre-installed-apps/pre-installed-apps.module'; @@ -19,7 +16,6 @@ import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature- import { FileModule } from 'src/engine/core-modules/file/file.module'; import { MetricsModule } from 'src/engine/core-modules/metrics/metrics.module'; import { OnboardingModule } from 'src/engine/core-modules/onboarding/onboarding.module'; -import { PublicDomainEntity } from 'src/engine/core-modules/public-domain/public-domain.entity'; import { SdkClientModule } from 'src/engine/core-modules/sdk-client/sdk-client.module'; import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity'; import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user-workspace.module'; @@ -31,7 +27,6 @@ import { CoreEntityCacheModule } from 'src/engine/core-entity-cache/core-entity- import { WorkspaceEntityCacheProviderService } from 'src/engine/core-modules/workspace/services/workspace-entity-cache-provider.service'; import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service'; import { WorkspaceGaugeService } from 'src/engine/core-modules/workspace/workspace-gauge.service'; -import { workspaceAutoResolverOpts } from 'src/engine/core-modules/workspace/workspace.auto-resolver-opts'; import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceResolver } from 'src/engine/core-modules/workspace/workspace.resolver'; import { BillingDisabledGuard } from 'src/engine/guards/billing-disabled.guard'; @@ -50,49 +45,40 @@ import { StandardObjectsPrefillModule } from 'src/engine/workspace-manager/stand @Module({ imports: [ TypeORMModule, - TypeOrmModule.forFeature([BillingSubscriptionEntity, WorkspaceEntity]), + TypeOrmModule.forFeature([ + BillingSubscriptionEntity, + WorkspaceEntity, + UserEntity, + UserWorkspaceEntity, + ]), MetricsModule, StandardObjectsPrefillModule, - NestjsQueryGraphQLModule.forFeature({ - imports: [ - BillingModule, - FileModule, - TokenModule, - NestjsQueryTypeOrmModule.forFeature([ - UserEntity, - WorkspaceEntity, - UserWorkspaceEntity, - PublicDomainEntity, - ]), - ObjectMetadataModule, - UserWorkspaceModule, - WorkspaceManagerModule, - FeatureFlagModule, - OnboardingModule, - WorkspaceDataSourceModule, - TypeORMModule, - PermissionsModule, - WorkspaceCacheStorageModule, - RoleModule, - AiAgentModule, - DnsManagerModule, - WorkspaceDomainsModule, - SubdomainManagerModule, - CustomDomainManagerModule, - ViewModule, - WorkspaceManyOrAllFlatEntityMapsCacheModule, - ApplicationModule, - PreInstalledAppsModule, - EnterpriseModule, - StandardObjectsPrefillModule, - WorkspaceMigrationModule, - CoreEntityCacheModule, - UpgradeModule, - SdkClientModule, - ], - services: [WorkspaceService], - resolvers: workspaceAutoResolverOpts, - }), + BillingModule, + FileModule, + TokenModule, + ObjectMetadataModule, + UserWorkspaceModule, + WorkspaceManagerModule, + FeatureFlagModule, + OnboardingModule, + WorkspaceDataSourceModule, + PermissionsModule, + WorkspaceCacheStorageModule, + RoleModule, + AiAgentModule, + DnsManagerModule, + WorkspaceDomainsModule, + SubdomainManagerModule, + CustomDomainManagerModule, + ViewModule, + WorkspaceManyOrAllFlatEntityMapsCacheModule, + ApplicationModule, + PreInstalledAppsModule, + EnterpriseModule, + WorkspaceMigrationModule, + CoreEntityCacheModule, + UpgradeModule, + SdkClientModule, ], exports: [WorkspaceService, CheckCustomDomainValidRecordsCronCommand], providers: [ 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 121e663f97..872a4287b6 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 @@ -105,7 +105,7 @@ export class WorkspaceResolver { @Query(() => WorkspaceEntity) @UseGuards(WorkspaceAuthGuard, NoPermissionGuard) async currentWorkspace(@AuthWorkspace() { id }: WorkspaceEntity) { - const workspace = await this.workspaceService.findById(id); + const workspace = await this.workspaceService.findOneWorkspaceById(id); assert(workspace, 'Workspace not found');