diff --git a/src/lib/cls.guard.ts b/src/lib/cls.guard.ts index 195ab466..6368611a 100644 --- a/src/lib/cls.guard.ts +++ b/src/lib/cls.guard.ts @@ -10,9 +10,11 @@ import { ClsGuardOptions } from './cls.interfaces'; @Injectable() export class ClsGuard implements CanActivate { + private readonly options: Omit; + constructor( @Inject(CLS_GUARD_OPTIONS) - private readonly options?: ClsGuardOptions, + options: Omit, ) { this.options = { ...new ClsGuardOptions(), ...options }; } @@ -22,7 +24,7 @@ export class ClsGuard implements CanActivate { return cls.exit(async () => { cls.enter(); if (this.options.generateId) { - const id = await this.options.idGenerator(context); + const id = await this.options.idGenerator?.(context); cls.set(CLS_ID, id); } if (this.options.setup) { diff --git a/src/lib/cls.interceptor.ts b/src/lib/cls.interceptor.ts index fab905ec..d26e2c88 100644 --- a/src/lib/cls.interceptor.ts +++ b/src/lib/cls.interceptor.ts @@ -12,9 +12,11 @@ import { ClsInterceptorOptions } from './cls.interfaces'; @Injectable() export class ClsInterceptor implements NestInterceptor { + private readonly options: Omit; + constructor( @Inject(CLS_INTERCEPTOR_OPTIONS) - private readonly options?: Omit, + options?: Omit, ) { this.options = { ...new ClsInterceptorOptions(), ...options }; } @@ -24,7 +26,7 @@ export class ClsInterceptor implements NestInterceptor { return new Observable((subscriber) => { cls.run(async () => { if (this.options.generateId) { - const id = await this.options.idGenerator(context); + const id = await this.options.idGenerator?.(context); cls.set(CLS_ID, id); } if (this.options.setup) { diff --git a/src/lib/cls.interfaces.ts b/src/lib/cls.interfaces.ts index 02e6e04c..240477e6 100644 --- a/src/lib/cls.interfaces.ts +++ b/src/lib/cls.interfaces.ts @@ -11,20 +11,20 @@ export class ClsModuleOptions { /** * An object with additional options for the `ClsMiddleware` */ - middleware?: ClsMiddlewareOptions = null; + middleware?: ClsMiddlewareOptions; /** * An object with additional options for the `ClsGuard` */ - guard?: ClsGuardOptions = null; + guard?: ClsGuardOptions; /** * An object with additional options for the `ClsInterceptor` */ - interceptor?: ClsInterceptorOptions = null; + interceptor?: ClsInterceptorOptions; /** - * + * Array of Proxy Provider classes to register */ proxyProviders?: Type[]; } @@ -35,7 +35,7 @@ export type ClsModuleFactoryOptions = Omit< >; export interface ClsModuleAsyncOptions extends Pick { inject?: any[]; - useFactory?: ( + useFactory: ( ...args: any[] ) => Promise | ClsModuleFactoryOptions; /** @@ -45,9 +45,9 @@ export interface ClsModuleAsyncOptions extends Pick { global?: boolean; /** - * + * Array of Proxy Provider classes to register */ - providers?: Type[]; + proxyProviders?: Type[]; } export class ClsMiddlewareOptions { diff --git a/src/lib/cls.middleware.ts b/src/lib/cls.middleware.ts index 4c39404d..e004601e 100644 --- a/src/lib/cls.middleware.ts +++ b/src/lib/cls.middleware.ts @@ -12,10 +12,11 @@ import { ClsService } from './cls.service'; @Injectable() export class ClsMiddleware implements NestMiddleware { private readonly cls: ClsService; + private readonly options: Omit; constructor( @Inject(CLS_MIDDLEWARE_OPTIONS) - private readonly options?: Omit, + options?: Omit, ) { this.options = { ...new ClsMiddlewareOptions(), ...options }; } @@ -24,7 +25,7 @@ export class ClsMiddleware implements NestMiddleware { const callback = async () => { this.options.useEnterWith && cls.enter(); if (this.options.generateId) { - const id = await this.options.idGenerator(req); + const id = await this.options.idGenerator?.(req); cls.set(CLS_ID, id); } if (this.options.saveReq) cls.set(CLS_REQ, req); diff --git a/src/lib/cls.module.ts b/src/lib/cls.module.ts index 8efbc6d3..6b626791 100644 --- a/src/lib/cls.module.ts +++ b/src/lib/cls.module.ts @@ -88,12 +88,9 @@ export class ClsModule implements NestModule { static forRoot(options?: ClsModuleOptions): DynamicModule { options = { ...new ClsModuleOptions(), ...options }; const { providers, exports } = this.getProviders(); - const proxyProviders = - options.proxyProviders?.map((providerClass) => - ProxyProviderManager.createProxyProvider({ - useClass: providerClass, - }), - ) ?? []; + const proxyProviders = this.createProxyClassProviders( + options.proxyProviders, + ); return { module: ClsModule, @@ -112,6 +109,9 @@ export class ClsModule implements NestModule { static forRootAsync(asyncOptions: ClsModuleAsyncOptions): DynamicModule { const { providers, exports } = this.getProviders(); + const proxyProviders = this.createProxyClassProviders( + asyncOptions.proxyProviders, + ); return { module: ClsModule, @@ -123,8 +123,9 @@ export class ClsModule implements NestModule { useFactory: asyncOptions.useFactory, }, ...providers, + ...proxyProviders, ], - exports, + exports: [...exports, ...proxyProviders.map((p) => p.provide)], global: asyncOptions.global, }; } @@ -133,14 +134,10 @@ export class ClsModule implements NestModule { * Registers the `ClsService` provider in the module */ static forFeature(): DynamicModule; - static forFeature(...requestScopedProviders: Array): DynamicModule; - static forFeature(...requestScopedProviders: Array): DynamicModule { + static forFeature(...proxyProviderClasses: Array): DynamicModule; + static forFeature(...proxyProviderClasses: Array): DynamicModule { const proxyProviders = - requestScopedProviders.map((providerClass) => - ProxyProviderManager.createProxyProvider({ - useClass: providerClass, - }), - ) ?? []; + this.createProxyClassProviders(proxyProviderClasses); const providers = [...commonProviders]; return { module: ClsModule, @@ -165,6 +162,18 @@ export class ClsModule implements NestModule { }; } + private static createProxyClassProviders( + proxyProviderClasses?: Array, + ) { + return ( + proxyProviderClasses?.map((providerClass) => + ProxyProviderManager.createProxyProvider({ + useClass: providerClass, + }), + ) ?? [] + ); + } + private static getProviders() { const providers: Provider[] = [ ...commonProviders, diff --git a/src/lib/proxy-provider/proxy-provider-manager.ts b/src/lib/proxy-provider/proxy-provider-manager.ts index 5f4e88db..ed0b41db 100644 --- a/src/lib/proxy-provider/proxy-provider-manager.ts +++ b/src/lib/proxy-provider/proxy-provider-manager.ts @@ -125,7 +125,9 @@ export class ProxyProviderManager { } private static async resolveProxyProvider(providerSymbol: symbol) { - const provider = this.proxyProviderMap.get(providerSymbol); + const provider = this.proxyProviderMap.get( + providerSymbol, + ) as ProxyProvider; if (isProxyClassProvider(provider)) { await this.resolveProxyClassProvider(providerSymbol, provider); } else { diff --git a/src/lib/proxy-provider/proxy-provider.exceptions.ts b/src/lib/proxy-provider/proxy-provider.exceptions.ts index 13383514..4f144a33 100644 --- a/src/lib/proxy-provider/proxy-provider.exceptions.ts +++ b/src/lib/proxy-provider/proxy-provider.exceptions.ts @@ -32,7 +32,7 @@ export class UnknownProxyDependenciesException extends Error { // matches the parameters from NestJS's error message: // e.g: "Nest can't resolve dependencies of the Something (Cats, ?). [...]" // returns ['Cats', '?'] - return error.message.match(/\w+ \((.*?)\)./)[1].split(', '); + return error.message.match(/\w+ \((.*?)\)./)?.[1].split(', ') ?? []; } private static composeMessage( diff --git a/src/utils/value-from-path.ts b/src/utils/value-from-path.ts index 721912e3..6703a5f0 100644 --- a/src/utils/value-from-path.ts +++ b/src/utils/value-from-path.ts @@ -5,7 +5,7 @@ import { export function getValueFromPath & string>( obj: T, - path?: TP, + path: TP, ): DeepPropertyType { const pathSegments = path.split('.'); return pathSegments.reduce((acc, curr) => acc?.[curr], obj); diff --git a/test/proxy-providers/for-feature.spec.ts b/test/proxy-providers/for-feature.spec.ts index f1833d71..fe3b6123 100644 --- a/test/proxy-providers/for-feature.spec.ts +++ b/test/proxy-providers/for-feature.spec.ts @@ -20,7 +20,7 @@ async function createAndInitTestingApp(imports: ModuleMetadata['imports']) { const moduleFixture: TestingModule = await Test.createTestingModule({ imports: [ ClsModule.forRoot({ middleware: { mount: true } }), - ...imports, + ...(imports ?? []), ], }).compile(); const app = moduleFixture.createNestApplication(); diff --git a/tsconfig.json b/tsconfig.json index d57ad3e1..e225fd6e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,24 +1,24 @@ { - "compilerOptions": { - "module": "commonjs", - "esModuleInterop": true, - "declaration": true, - "removeComments": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "allowSyntheticDefaultImports": true, - "target": "es2017", - "sourceMap": true, - "rootDir": ".", - "outDir": "./dist", - "baseUrl": "./", - "incremental": true, - "skipLibCheck": true, - "strictNullChecks": false, - "noImplicitAny": false, - "strictBindCallApply": false, - "forceConsistentCasingInFileNames": false, - "noFallthroughCasesInSwitch": false, - }, - "include": ["src/**/*.ts", "test/**/*.ts"] + "compilerOptions": { + "module": "commonjs", + "esModuleInterop": true, + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "es2017", + "sourceMap": true, + "rootDir": ".", + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": true, + "noImplicitAny": false, + "strictBindCallApply": false, + "forceConsistentCasingInFileNames": false, + "noFallthroughCasesInSwitch": false + }, + "include": ["src/**/*.ts", "test/**/*.ts"] }