From 4a363ce656e933d355f1a2ed27b7586ef05bff6c Mon Sep 17 00:00:00 2001 From: Adam Chmara Date: Thu, 8 Aug 2024 10:15:27 +0200 Subject: [PATCH] refactor(api,application-generic,ws,worker,webhook): resolve circular dependencies; import refactor (#6268) --- .source | 2 +- apps/api/src/app.module.ts | 6 - .../app/auth/community.auth.module.config.ts | 4 +- .../api/src/app/auth/ee.auth.module.config.ts | 16 +- apps/api/src/app/shared/shared.module.ts | 16 +- apps/webhook/package.json | 3 + apps/webhook/src/shared/shared.module.ts | 15 +- apps/worker/src/app/shared/shared.module.ts | 16 +- apps/ws/package.json | 3 + apps/ws/src/shared/shared.module.ts | 16 +- enterprise/packages/auth/package.json | 1 + enterprise/packages/billing/package.json | 3 + enterprise/packages/translation/package.json | 3 + libs/application-generic/package.json | 1 - libs/application-generic/src/index.ts | 2 +- .../src/utils/inject-auth-providers.ts | 108 +++++++++ .../src/utils/inject-repositories.ts | 225 ------------------ libs/testing/src/ee/ee.repository.factory.ts | 10 + pnpm-lock.yaml | 22 +- 19 files changed, 214 insertions(+), 258 deletions(-) create mode 100644 libs/application-generic/src/utils/inject-auth-providers.ts delete mode 100644 libs/application-generic/src/utils/inject-repositories.ts diff --git a/.source b/.source index 0187967d66d..6e18f2eaed7 160000 --- a/.source +++ b/.source @@ -1 +1 @@ -Subproject commit 0187967d66de0637f5948f6be1227e054c59f970 +Subproject commit 6e18f2eaed7d98558faa9eea2503f24cd3c84403 diff --git a/apps/api/src/app.module.ts b/apps/api/src/app.module.ts index 95a1c2a24e3..b757a201466 100644 --- a/apps/api/src/app.module.ts +++ b/apps/api/src/app.module.ts @@ -59,12 +59,6 @@ const enterpriseImports = (): Array injectEEAuthProviders() + * + */ +export function injectCommunityAuthProviders( + { repositoriesOnly }: { repositoriesOnly?: boolean } = { + repositoriesOnly: true, + } +) { + const userRepositoryProvider = { + provide: 'USER_REPOSITORY', + useClass: CommunityUserRepository, + }; + + const memberRepositoryProvider = { + provide: 'MEMBER_REPOSITORY', + useClass: CommunityMemberRepository, + }; + + const organizationRepositoryProvider = { + provide: 'ORGANIZATION_REPOSITORY', + useClass: CommunityOrganizationRepository, + }; + + const authServiceProvider = { + provide: 'AUTH_SERVICE', + useFactory: ( + userRepository: UserRepository, + subscriberRepository: SubscriberRepository, + createUserUsecase: CreateUser, + jwtService: JwtService, + analyticsService: AnalyticsService, + organizationRepository: OrganizationRepository, + environmentRepository: EnvironmentRepository, + memberRepository: MemberRepository, + switchOrganizationUsecase: SwitchOrganization + ) => { + return new CommunityAuthService( + userRepository, + subscriberRepository, + createUserUsecase, + jwtService, + analyticsService, + organizationRepository, + environmentRepository, + memberRepository, + switchOrganizationUsecase + ); + }, + inject: [ + UserRepository, + SubscriberRepository, + CreateUser, + JwtService, + AnalyticsService, + OrganizationRepository, + EnvironmentRepository, + MemberRepository, + SwitchOrganization, + ], + }; + + const userAuthGuardProvider = { + provide: 'USER_AUTH_GUARD', + useFactory: (reflector: Reflector) => { + return new CommunityUserAuthGuard(reflector); + }, + inject: [Reflector], + }; + + if (repositoriesOnly) { + return [ + userRepositoryProvider, + memberRepositoryProvider, + organizationRepositoryProvider, + ]; + } + + return [ + userRepositoryProvider, + memberRepositoryProvider, + organizationRepositoryProvider, + authServiceProvider, + userAuthGuardProvider, + ]; +} diff --git a/libs/application-generic/src/utils/inject-repositories.ts b/libs/application-generic/src/utils/inject-repositories.ts deleted file mode 100644 index f32d8f7f512..00000000000 --- a/libs/application-generic/src/utils/inject-repositories.ts +++ /dev/null @@ -1,225 +0,0 @@ -import { Reflector } from '@nestjs/core'; -import { JwtService } from '@nestjs/jwt'; -import { - CommunityUserRepository, - CommunityMemberRepository, - CommunityOrganizationRepository, - EnvironmentRepository, - SubscriberRepository, - UserRepository, - MemberRepository, - OrganizationRepository, -} from '@novu/dal'; -import { isClerkEnabled } from '@novu/shared'; -import { - AnalyticsService, - CommunityAuthService, - CommunityUserAuthGuard, -} from '../services'; -import { CreateUser, SwitchOrganization } from '../usecases'; - -class PlatformException extends Error {} - -function injectClerkClientMock() { - if (process.env.NODE_ENV === 'test') { - const clerkClientMock = require('@novu/ee-auth').ClerkClientMock; - - return new clerkClientMock(); - } -} - -export function injectRepositories( - { repositoriesOnly }: { repositoriesOnly?: boolean } = { - repositoriesOnly: true, - } -) { - if (!isClerkEnabled()) { - const userRepositoryProvider = { - provide: 'USER_REPOSITORY', - useClass: CommunityUserRepository, - }; - - const memberRepositoryProvider = { - provide: 'MEMBER_REPOSITORY', - useClass: CommunityMemberRepository, - }; - - const organizationRepositoryProvider = { - provide: 'ORGANIZATION_REPOSITORY', - useClass: CommunityOrganizationRepository, - }; - - const authServiceProvider = { - provide: 'AUTH_SERVICE', - useFactory: ( - userRepository: UserRepository, - subscriberRepository: SubscriberRepository, - createUserUsecase: CreateUser, - jwtService: JwtService, - analyticsService: AnalyticsService, - organizationRepository: OrganizationRepository, - environmentRepository: EnvironmentRepository, - memberRepository: MemberRepository, - switchOrganizationUsecase: SwitchOrganization - ) => { - return new CommunityAuthService( - userRepository, - subscriberRepository, - createUserUsecase, - jwtService, - analyticsService, - organizationRepository, - environmentRepository, - memberRepository, - switchOrganizationUsecase - ); - }, - inject: [ - UserRepository, - SubscriberRepository, - CreateUser, - JwtService, - AnalyticsService, - OrganizationRepository, - EnvironmentRepository, - MemberRepository, - SwitchOrganization, - ], - }; - - const userAuthGuardProvider = { - provide: 'USER_AUTH_GUARD', - useFactory: (reflector: Reflector) => { - return new CommunityUserAuthGuard(reflector); - }, - inject: [Reflector], - }; - - if (repositoriesOnly) { - return [ - userRepositoryProvider, - memberRepositoryProvider, - organizationRepositoryProvider, - ]; - } - - return [ - userRepositoryProvider, - memberRepositoryProvider, - organizationRepositoryProvider, - authServiceProvider, - userAuthGuardProvider, - ]; - } - - const eeUserRepositoryProvider = { - provide: 'USER_REPOSITORY', - useFactory: (userRepository: CommunityUserRepository) => { - const eeAuthPackage = require('@novu/ee-auth'); - if (!eeAuthPackage?.EEUserRepository) { - throw new PlatformException('EEUserRepository is not loaded'); - } - - return new eeAuthPackage.EEUserRepository( - userRepository, - injectClerkClientMock() - ); - }, - inject: [CommunityUserRepository], - }; - - const eeMemberRepositoryProvider = { - provide: 'MEMBER_REPOSITORY', - useFactory: (organizationRepository: CommunityOrganizationRepository) => { - const eeAuthPackage = require('@novu/ee-auth'); - if (!eeAuthPackage?.EEMemberRepository) { - throw new PlatformException('EEMemberRepository is not loaded'); - } - - return new eeAuthPackage.EEMemberRepository( - organizationRepository, - injectClerkClientMock() - ); - }, - inject: [CommunityOrganizationRepository], - }; - - const eeOrganizationRepositoryProvider = { - provide: 'ORGANIZATION_REPOSITORY', - useFactory: (organizationRepository: CommunityOrganizationRepository) => { - const eeAuthPackage = require('@novu/ee-auth'); - if (!eeAuthPackage?.EEOrganizationRepository) { - throw new PlatformException('EEOrganizationRepository is not loaded'); - } - - return new eeAuthPackage.EEOrganizationRepository( - organizationRepository, - injectClerkClientMock() - ); - }, - inject: [CommunityOrganizationRepository], - }; - - const eeAuthServiceProvider = { - provide: 'AUTH_SERVICE', - useFactory: ( - userRepository: CommunityUserRepository, - environmentRepository: EnvironmentRepository, - subscriberRepository: SubscriberRepository, - jwtService: JwtService - ) => { - const eeAuthPackage = require('@novu/ee-auth'); - if (!eeAuthPackage?.EEAuthService) { - throw new PlatformException('EEAuthService is not loaded'); - } - - return new eeAuthPackage.EEAuthService( - userRepository, - environmentRepository, - subscriberRepository, - jwtService - ); - }, - inject: [ - CommunityUserRepository, - EnvironmentRepository, - SubscriberRepository, - JwtService, - ], - }; - - const eeUserAuthGuard = { - provide: 'USER_AUTH_GUARD', - useFactory: (reflector: Reflector) => { - const eeAuthPackage = require('@novu/ee-auth'); - if (!eeAuthPackage?.EEUserAuthGuard) { - throw new PlatformException('EEUserAuthGuard is not loaded'); - } - - return new eeAuthPackage.EEUserAuthGuard(reflector); - }, - inject: [Reflector], - }; - - if (repositoriesOnly) { - return [ - eeUserRepositoryProvider, - CommunityUserRepository, - eeMemberRepositoryProvider, - CommunityMemberRepository, - eeOrganizationRepositoryProvider, - CommunityOrganizationRepository, - ]; - } - - return [ - eeUserRepositoryProvider, - CommunityUserRepository, - eeMemberRepositoryProvider, - CommunityMemberRepository, - eeOrganizationRepositoryProvider, - CommunityOrganizationRepository, - eeAuthServiceProvider, - eeUserAuthGuard, - ]; -} diff --git a/libs/testing/src/ee/ee.repository.factory.ts b/libs/testing/src/ee/ee.repository.factory.ts index ecbf3f1c1c0..18366f8fb0c 100644 --- a/libs/testing/src/ee/ee.repository.factory.ts +++ b/libs/testing/src/ee/ee.repository.factory.ts @@ -1,6 +1,13 @@ import { CommunityOrganizationRepository, CommunityUserRepository, CommunityMemberRepository } from '@novu/dal'; import { isClerkEnabled } from '@novu/shared'; +/** + * We are using nx-ignore-next-line as a workaround here to avoid following circular dependency error: + * @novu/application-generic:build --> @novu/testing:build --> @novu/ee-auth:build --> @novu/application-generic:build + * + * When revising EE testing, we should consider refactoring the code to potentially avoid this circular dependency. + * + */ export function getEERepository(className: 'OrganizationRepository' | 'MemberRepository' | 'UserRepository'): T { if (isClerkEnabled()) { switch (className) { @@ -24,6 +31,7 @@ export function getEERepository(className: 'OrganizationRepository' | 'Member } function getEEUserRepository() { + // nx-ignore-next-line const enterpriseModule = require('@novu/ee-auth'); const enterpriseUserRepository = enterpriseModule?.EEUserRepository; const clerkClientMock = enterpriseModule?.ClerkClientMock; @@ -32,6 +40,7 @@ function getEEUserRepository() { } function getEEOrganizationRepository() { + // nx-ignore-next-line const enterpriseModule = require('@novu/ee-auth'); const enterpriseOrganizationRepository = enterpriseModule?.EEOrganizationRepository; const clerkClientMock = enterpriseModule?.ClerkClientMock; @@ -40,6 +49,7 @@ function getEEOrganizationRepository() { } function getEEMemberRepository() { + // nx-ignore-next-line const enterpriseModule = require('@novu/ee-auth'); const enterpriseMemberRepository = enterpriseModule?.EEMemberRepository; const clerkClientMock = enterpriseModule?.ClerkClientMock; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f93a843f4b5..ce8e0f644bd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1235,6 +1235,10 @@ importers: rxjs: specifier: 7.8.1 version: 7.8.1 + optionalDependencies: + '@novu/ee-auth': + specifier: workspace:* + version: link:../../enterprise/packages/auth devDependencies: '@nestjs/cli': specifier: ^10.1.16 @@ -1767,6 +1771,10 @@ importers: socket.io: specifier: ^4.7.2 version: 4.7.2 + optionalDependencies: + '@novu/ee-auth': + specifier: workspace:* + version: link:../../enterprise/packages/auth devDependencies: '@nestjs/cli': specifier: ^10.1.16 @@ -1846,6 +1854,9 @@ importers: '@nestjs/swagger': specifier: ^7.1.9 version: 7.1.9(@nestjs/common@10.2.2(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1))(@nestjs/core@10.2.2(@nestjs/common@10.2.2(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1))(@nestjs/platform-express@10.2.2)(@nestjs/websockets@10.2.2)(encoding@0.1.13)(reflect-metadata@0.1.13)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13) + '@novu/application-generic': + specifier: workspace:* + version: link:../../../libs/application-generic '@novu/dal': specifier: workspace:* version: link:../../../libs/dal @@ -1967,6 +1978,10 @@ importers: stripe-event-types: specifier: ^3.1.0 version: 3.1.0(stripe@11.18.0) + optionalDependencies: + '@novu/ee-auth': + specifier: workspace:* + version: link:../auth devDependencies: '@types/chai': specifier: ^4.2.11 @@ -2123,6 +2138,10 @@ importers: slugify: specifier: ^1.4.6 version: 1.6.6 + optionalDependencies: + '@novu/ee-auth': + specifier: workspace:* + version: link:../auth devDependencies: '@types/chai': specifier: ^4.2.11 @@ -2353,9 +2372,6 @@ importers: specifier: ^1.4.6 version: 1.6.6 optionalDependencies: - '@novu/ee-auth': - specifier: workspace:* - version: link:../../enterprise/packages/auth '@novu/ee-shared-services': specifier: workspace:* version: link:../../enterprise/packages/shared-services