Skip to content

Commit 578603e

Browse files
feat(core): request-scoped custom providers improvements
1 parent 9a0efc1 commit 578603e

7 files changed

Lines changed: 52 additions & 17 deletions

File tree

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
import { Injectable, Scope } from '@nestjs/common';
1+
import { Inject, Injectable, Scope } from '@nestjs/common';
2+
import { REQUEST } from '@nestjs/core';
23

34
@Injectable({ scope: Scope.REQUEST })
45
export class HelperService {
6+
constructor(@Inject(REQUEST) public readonly request) {}
7+
58
public noop() {}
69
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {
2+
CallHandler,
3+
ExecutionContext,
4+
Injectable,
5+
NestInterceptor,
6+
} from '@nestjs/common';
7+
import { Observable } from 'rxjs';
8+
import { HelperService } from '../helper/helper.service';
9+
10+
@Injectable()
11+
export class LoggingInterceptor implements NestInterceptor {
12+
constructor(private readonly helperSvc: HelperService) {}
13+
14+
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
15+
this.helperSvc.noop();
16+
if (!this.helperSvc.request) {
17+
throw new Error('error');
18+
}
19+
return next.handle();
20+
}
21+
}

integration/scopes/src/request-chain/request-chain.controller.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
import { Controller, Get } from '@nestjs/common';
1+
import { Controller, Get, UseInterceptors } from '@nestjs/common';
2+
import { LoggingInterceptor } from './interceptors/logging.interceptor';
23
import { RequestChainService } from './request-chain.service';
34

45
@Controller('hello')
56
export class RequestChainController {
67
constructor(private readonly chainService: RequestChainService) {}
78

9+
@UseInterceptors(LoggingInterceptor)
810
@Get()
911
greeting(): void {
1012
this.chainService.call();
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Scope } from '@nestjs/common';
2+
import { SCOPE_OPTIONS_METADATA } from '@nestjs/common/constants';
3+
import { Type } from '@nestjs/common/interfaces/type.interface';
4+
5+
export function getClassScope(provider: Type<unknown>): Scope {
6+
const metadata = Reflect.getMetadata(SCOPE_OPTIONS_METADATA, provider);
7+
return metadata && metadata.scope;
8+
}

packages/core/injector/injector.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ export class Injector {
194194
if (instanceHost.isResolved) {
195195
return done();
196196
}
197-
const callback = async (instances: any[]) => {
197+
const callback = async (instances: unknown[]) => {
198198
const properties = await this.resolveProperties(
199199
wrapper,
200200
module,
@@ -228,7 +228,7 @@ export class Injector {
228228
wrapper: InstanceWrapper<T>,
229229
module: Module,
230230
inject: InjectorDependency[],
231-
callback: (args: any[]) => void,
231+
callback: (args: unknown[]) => void,
232232
contextId = STATIC_CONTEXT,
233233
inquirer?: InstanceWrapper,
234234
parentInquirer?: InstanceWrapper,

packages/core/injector/module.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { Scope } from '@nestjs/common';
2-
import { SCOPE_OPTIONS_METADATA } from '@nestjs/common/constants';
31
import {
42
Abstract,
53
ClassProvider,
@@ -26,6 +24,7 @@ import { InvalidClassException } from '../errors/exceptions/invalid-class.except
2624
import { RuntimeException } from '../errors/exceptions/runtime.exception';
2725
import { UnknownExportException } from '../errors/exceptions/unknown-export.exception';
2826
import { createContextId } from '../helpers';
27+
import { getClassScope } from '../helpers/get-class-scope';
2928
import { CONTROLLER_ID_KEY } from './constants';
3029
import { NestContainer } from './container';
3130
import { InstanceWrapper } from './instance-wrapper';
@@ -184,7 +183,7 @@ export class Module {
184183
metatype: injectable,
185184
instance: null,
186185
isResolved: false,
187-
scope: this.getClassScope(injectable),
186+
scope: getClassScope(injectable),
188187
host: this,
189188
});
190189
this._injectables.set(injectable.name, instanceWrapper);
@@ -208,7 +207,7 @@ export class Module {
208207
metatype: provider as Type<Injectable>,
209208
instance: null,
210209
isResolved: false,
211-
scope: this.getClassScope(provider),
210+
scope: getClassScope(provider),
212211
host: this,
213212
}),
214213
);
@@ -286,7 +285,7 @@ export class Module {
286285

287286
let { scope } = provider;
288287
if (isUndefined(scope)) {
289-
scope = this.getClassScope(useClass);
288+
scope = getClassScope(useClass);
290289
}
291290
collection.set(
292291
name as string,
@@ -413,7 +412,7 @@ export class Module {
413412
metatype: controller,
414413
instance: null,
415414
isResolved: false,
416-
scope: this.getClassScope(controller),
415+
scope: getClassScope(controller),
417416
host: this,
418417
}),
419418
);
@@ -506,9 +505,4 @@ export class Module {
506505
}
507506
};
508507
}
509-
510-
private getClassScope(provider: Type<unknown>): Scope {
511-
const metadata = Reflect.getMetadata(SCOPE_OPTIONS_METADATA, provider);
512-
return metadata && metadata.scope;
513-
}
514508
}

packages/core/scanner.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
import { ApplicationConfig } from './application-config';
3737
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from './constants';
3838
import { CircularDependencyException } from './errors/exceptions/circular-dependency.exception';
39+
import { getClassScope } from './helpers/get-class-scope';
3940
import { ModulesContainer } from './injector';
4041
import { NestContainer } from './injector/container';
4142
import { InstanceWrapper } from './injector/instance-wrapper';
@@ -311,21 +312,27 @@ export class DependenciesScanner {
311312
return this.container.addProvider(provider as any, token);
312313
}
313314
const providerToken = `${type as string} (UUID: ${randomStringGenerator()})`;
315+
316+
let scope = (provider as ClassProvider | FactoryProvider).scope;
317+
if (isNil(scope) && (provider as ClassProvider).useClass) {
318+
scope = getClassScope((provider as ClassProvider).useClass);
319+
}
314320
this.applicationProvidersApplyMap.push({
315321
type,
316322
moduleKey: token,
317323
providerKey: providerToken,
318-
scope: (provider as ClassProvider | FactoryProvider).scope,
324+
scope,
319325
});
320326

321327
const newProvider = {
322328
...provider,
323329
provide: providerToken,
330+
scope,
324331
} as Provider;
325332

326333
if (
327334
this.isRequestOrTransient(
328-
(provider as FactoryProvider | ClassProvider).scope,
335+
(newProvider as FactoryProvider | ClassProvider).scope,
329336
)
330337
) {
331338
return this.container.addInjectable(newProvider, token);

0 commit comments

Comments
 (0)