@nestjs/core 8.4.6 → 9.0.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/Readme.md +4 -3
  2. package/adapters/http-adapter.d.ts +5 -2
  3. package/errors/messages.js +3 -4
  4. package/exceptions/base-exception-filter.js +14 -2
  5. package/helpers/context-id-factory.d.ts +18 -1
  6. package/helpers/context-id-factory.js +14 -1
  7. package/helpers/is-durable.d.ts +2 -0
  8. package/helpers/is-durable.js +9 -0
  9. package/index.d.ts +1 -0
  10. package/index.js +1 -0
  11. package/injector/index.d.ts +1 -1
  12. package/injector/injector.d.ts +2 -1
  13. package/injector/injector.js +36 -18
  14. package/injector/instance-wrapper.d.ts +20 -2
  15. package/injector/instance-wrapper.js +61 -20
  16. package/injector/module-ref.js +2 -0
  17. package/injector/module.js +11 -2
  18. package/middleware/container.js +3 -1
  19. package/nest-application.d.ts +0 -2
  20. package/nest-application.js +0 -8
  21. package/package.json +2 -2
  22. package/repl/assign-to-object.util.d.ts +5 -0
  23. package/repl/assign-to-object.util.js +15 -0
  24. package/repl/constants.d.ts +1 -0
  25. package/repl/constants.js +4 -0
  26. package/repl/index.d.ts +1 -0
  27. package/repl/index.js +4 -0
  28. package/repl/native-functions/debug-repl-fn.d.ts +9 -0
  29. package/repl/native-functions/debug-repl-fn.js +46 -0
  30. package/repl/native-functions/get-relp-fn.d.ts +7 -0
  31. package/repl/native-functions/get-relp-fn.js +19 -0
  32. package/repl/native-functions/help-repl-fn.d.ts +7 -0
  33. package/repl/native-functions/help-repl-fn.js +29 -0
  34. package/repl/native-functions/index.d.ts +6 -0
  35. package/repl/native-functions/index.js +9 -0
  36. package/repl/native-functions/methods-repl-fn.d.ts +8 -0
  37. package/repl/native-functions/methods-repl-fn.js +28 -0
  38. package/repl/native-functions/resolve-repl-fn.d.ts +7 -0
  39. package/repl/native-functions/resolve-repl-fn.js +18 -0
  40. package/repl/native-functions/select-relp-fn.d.ts +7 -0
  41. package/repl/native-functions/select-relp-fn.js +18 -0
  42. package/repl/repl-context.d.ts +26 -0
  43. package/repl/repl-context.js +124 -0
  44. package/repl/repl-function.d.ts +18 -0
  45. package/repl/repl-function.js +19 -0
  46. package/repl/repl-logger.d.ts +5 -0
  47. package/repl/repl-logger.js +22 -0
  48. package/repl/repl.d.ts +4 -0
  49. package/repl/repl.interfaces.d.ts +16 -0
  50. package/repl/repl.interfaces.js +2 -0
  51. package/repl/repl.js +27 -0
  52. package/router/router-explorer.js +1 -101
  53. package/router/router-response-controller.js +3 -3
  54. package/scanner.d.ts +1 -2
  55. package/scanner.js +9 -11
package/Readme.md CHANGED
@@ -65,19 +65,20 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
65
65
  <td>
66
66
  <a href="https://nx.dev" target="_blank"><img src="https://nestjs.com/img/nx-logo.png" height="45" valign="middle" /></a></td>
67
67
  <td>
68
- <a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td>
68
+ <a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td><td>
69
+ <a href="https://amplication.com/" target="_blank"><img src="https://nestjs.com/img/amplication-logo.svg" width="190" valign="middle" /></a></td>
69
70
  </tr></table>
70
71
 
71
72
  #### Gold Sponsors
72
73
 
73
74
  <table style="text-align:center;"><tr><td>
74
- <a href="https://careers.labster.com/departments/platform" target="_blank"><img src="https://nestjs.com/img/labster-logo.png" width="170" valign="middle" /></a></td><td>
75
75
  <a href="https://weld.app/" target="_blank"><img src="https://nestjs.com/img/weld-logo.svg" width="140" valign="middle" /></a></td>
76
76
  <td>
77
77
  <a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/intrinisic-logo.png" width="210" valign="middle" /></a></td>
78
78
  <td>
79
79
  <a href="https://jetbrains.com/" target="_blank"><img src="https://nestjs.com/img/jetbrains-logo.svg" width="110" valign="middle" /></a></td><td>
80
- <a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/snyk-logo-black.png" width="185" valign="middle" /></a></td></</tr></table>
80
+ <a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/snyk-logo-black.png" width="185" valign="middle" /></a></td><td>
81
+ <a href="https://fuseautotech.com/" target="_blank"><img src="https://nestjs.com/img/fuse-logo.svg" width="105" valign="middle" /></a></td></</tr></table>
81
82
 
82
83
  #### Silver Sponsors
83
84
 
@@ -1,5 +1,5 @@
1
- import { HttpServer, RequestMethod } from '@nestjs/common';
2
- import { RequestHandler } from '@nestjs/common/interfaces';
1
+ import { HttpServer, RequestMethod, VersioningOptions } from '@nestjs/common';
2
+ import { RequestHandler, VersionValue } from '@nestjs/common/interfaces';
3
3
  import { CorsOptions, CorsOptionsDelegate } from '@nestjs/common/interfaces/external/cors-options.interface';
4
4
  import { NestApplicationOptions } from '@nestjs/common/interfaces/nest-application-options.interface';
5
5
  /**
@@ -42,13 +42,16 @@ export declare abstract class AbstractHttpAdapter<TServer = any, TRequest = any,
42
42
  abstract getRequestUrl(request: any): any;
43
43
  abstract status(response: any, statusCode: number): any;
44
44
  abstract reply(response: any, body: any, statusCode?: number): any;
45
+ abstract end(response: any, message?: string): any;
45
46
  abstract render(response: any, view: string, options: any): any;
46
47
  abstract redirect(response: any, statusCode: number, url: string): any;
47
48
  abstract setErrorHandler(handler: Function, prefix?: string): any;
48
49
  abstract setNotFoundHandler(handler: Function, prefix?: string): any;
50
+ abstract isHeadersSent(response: any): any;
49
51
  abstract setHeader(response: any, name: string, value: string): any;
50
52
  abstract registerParserMiddleware(prefix?: string, rawBody?: boolean): any;
51
53
  abstract enableCors(options: CorsOptions | CorsOptionsDelegate<TRequest>, prefix?: string): any;
52
54
  abstract createMiddlewareFactory(requestMethod: RequestMethod): ((path: string, callback: Function) => any) | Promise<(path: string, callback: Function) => any>;
53
55
  abstract getType(): string;
56
+ abstract applyVersionFilter(handler: Function, version: VersionValue, versioningOptions: VersioningOptions): (req: TRequest, res: TResponse, next: () => void) => Function;
54
57
  }
@@ -81,10 +81,9 @@ Scope [${stringifyScope(scope)}]`;
81
81
  };
82
82
  exports.INVALID_MODULE_MESSAGE = INVALID_MODULE_MESSAGE;
83
83
  const USING_INVALID_CLASS_AS_A_MODULE_MESSAGE = (metatypeUsedAsAModule, scope) => {
84
- const metatypeName = getInstanceName(metatypeUsedAsAModule) || 'found';
85
- // TODO(v9): Edit the message below:
86
- return `In the next major version, Nest will not allow classes annotated with @Injectable(), @Catch(), and @Controller() decorators to appear in the "imports" array of a module.
87
- Please remove "${metatypeName}" (including forwarded occurrences, if any) from all of the "imports" arrays.
84
+ const metatypeNameQuote = `"${getInstanceName(metatypeUsedAsAModule)}"` || 'that class';
85
+ return `Classes annotated with @Injectable(), @Catch(), and @Controller() decorators must not appear in the "imports" array of a module.
86
+ Please remove ${metatypeNameQuote} (including forwarded occurrences, if any) from all of the "imports" arrays.
88
87
 
89
88
  Scope [${stringifyScope(scope)}]
90
89
  `;
@@ -23,7 +23,13 @@ class BaseExceptionFilter {
23
23
  statusCode: exception.getStatus(),
24
24
  message: res,
25
25
  };
26
- applicationRef.reply(host.getArgByIndex(1), message, exception.getStatus());
26
+ const response = host.getArgByIndex(1);
27
+ if (!applicationRef.isHeadersSent(response)) {
28
+ applicationRef.reply(response, message, exception.getStatus());
29
+ }
30
+ else {
31
+ applicationRef.end(response);
32
+ }
27
33
  }
28
34
  handleUnknownError(exception, host, applicationRef) {
29
35
  const body = this.isHttpError(exception)
@@ -35,7 +41,13 @@ class BaseExceptionFilter {
35
41
  statusCode: common_1.HttpStatus.INTERNAL_SERVER_ERROR,
36
42
  message: constants_1.MESSAGES.UNKNOWN_EXCEPTION_MESSAGE,
37
43
  };
38
- applicationRef.reply(host.getArgByIndex(1), body, body.statusCode);
44
+ const response = host.getArgByIndex(1);
45
+ if (!applicationRef.isHeadersSent(response)) {
46
+ applicationRef.reply(response, body, body.statusCode);
47
+ }
48
+ else {
49
+ applicationRef.end(response);
50
+ }
39
51
  if (this.isExceptionObject(exception)) {
40
52
  return BaseExceptionFilter.logger.error(exception.message, exception.stack);
41
53
  }
@@ -1,6 +1,17 @@
1
- import { ContextId } from '../injector/instance-wrapper';
1
+ import { ContextId, HostComponentInfo } from '../injector/instance-wrapper';
2
2
  export declare function createContextId(): ContextId;
3
+ export interface ContextIdStrategy<T = any> {
4
+ /**
5
+ * Allows to attach a parent context id to the existing child context id.
6
+ * This lets you construct durable DI sub-trees that can be shared between contexts.
7
+ * @param contextId auto-generated child context id
8
+ * @param request request object
9
+ * @returns a context id resolver function
10
+ */
11
+ attach(contextId: ContextId, request: T): ((info: HostComponentInfo) => ContextId) | undefined;
12
+ }
3
13
  export declare class ContextIdFactory {
14
+ private static strategy?;
4
15
  /**
5
16
  * Generates a context identifier based on the request object.
6
17
  */
@@ -10,4 +21,10 @@ export declare class ContextIdFactory {
10
21
  * @param request request object
11
22
  */
12
23
  static getByRequest<T extends Record<any, any> = any>(request: T, propsToInspect?: string[]): ContextId;
24
+ /**
25
+ * Registers a custom context id strategy that lets you attach
26
+ * a parent context id to the existing context id object.
27
+ * @param strategy strategy instance
28
+ */
29
+ static apply(strategy: ContextIdStrategy): void;
13
30
  }
@@ -38,7 +38,20 @@ class ContextIdFactory {
38
38
  return request[key][request_constants_1.REQUEST_CONTEXT_ID];
39
39
  }
40
40
  }
41
- return ContextIdFactory.create();
41
+ if (!this.strategy) {
42
+ return ContextIdFactory.create();
43
+ }
44
+ const contextId = createContextId();
45
+ contextId.getParent = this.strategy.attach(contextId, request);
46
+ return contextId;
47
+ }
48
+ /**
49
+ * Registers a custom context id strategy that lets you attach
50
+ * a parent context id to the existing context id object.
51
+ * @param strategy strategy instance
52
+ */
53
+ static apply(strategy) {
54
+ this.strategy = strategy;
42
55
  }
43
56
  }
44
57
  exports.ContextIdFactory = ContextIdFactory;
@@ -0,0 +1,2 @@
1
+ import { Type } from '@nestjs/common/interfaces/type.interface';
2
+ export declare function isDurable(provider: Type<unknown>): boolean | undefined;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isDurable = void 0;
4
+ const constants_1 = require("@nestjs/common/constants");
5
+ function isDurable(provider) {
6
+ const metadata = Reflect.getMetadata(constants_1.SCOPE_OPTIONS_METADATA, provider);
7
+ return metadata && metadata.durable;
8
+ }
9
+ exports.isDurable = isDurable;
package/index.d.ts CHANGED
@@ -11,5 +11,6 @@ export * from './middleware';
11
11
  export * from './nest-application';
12
12
  export * from './nest-application-context';
13
13
  export { NestFactory } from './nest-factory';
14
+ export * from './repl';
14
15
  export * from './router';
15
16
  export * from './services';
package/index.js CHANGED
@@ -26,5 +26,6 @@ tslib_1.__exportStar(require("./nest-application"), exports);
26
26
  tslib_1.__exportStar(require("./nest-application-context"), exports);
27
27
  var nest_factory_1 = require("./nest-factory");
28
28
  Object.defineProperty(exports, "NestFactory", { enumerable: true, get: function () { return nest_factory_1.NestFactory; } });
29
+ tslib_1.__exportStar(require("./repl"), exports);
29
30
  tslib_1.__exportStar(require("./router"), exports);
30
31
  tslib_1.__exportStar(require("./services"), exports);
@@ -1,6 +1,6 @@
1
1
  export * from './container';
2
2
  export * from './inquirer';
3
- export { ContextId } from './instance-wrapper';
3
+ export { ContextId, HostComponentInfo } from './instance-wrapper';
4
4
  export * from './lazy-module-loader';
5
5
  export * from './module-ref';
6
6
  export * from './modules-container';
@@ -48,7 +48,7 @@ export declare class Injector {
48
48
  loadController(wrapper: InstanceWrapper<Controller>, moduleRef: Module, contextId?: ContextId): Promise<void>;
49
49
  loadInjectable<T = any>(wrapper: InstanceWrapper<T>, moduleRef: Module, contextId?: ContextId, inquirer?: InstanceWrapper): Promise<void>;
50
50
  loadProvider(wrapper: InstanceWrapper<Injectable>, moduleRef: Module, contextId?: ContextId, inquirer?: InstanceWrapper): Promise<void>;
51
- applyDoneHook<T>(wrapper: InstancePerContext<T>): () => void;
51
+ applyDoneHook<T>(wrapper: InstancePerContext<T>): (err?: unknown) => void;
52
52
  resolveConstructorParams<T>(wrapper: InstanceWrapper<T>, moduleRef: Module, inject: InjectorDependency[], callback: (args: unknown[]) => void | Promise<void>, contextId?: ContextId, inquirer?: InstanceWrapper, parentInquirer?: InstanceWrapper): Promise<void>;
53
53
  getClassDependencies<T>(wrapper: InstanceWrapper<T>): [InjectorDependency[], number[]];
54
54
  getFactoryProviderDependencies<T>(wrapper: InstanceWrapper<T>): [InjectorDependency[], number[]];
@@ -80,4 +80,5 @@ export declare class Injector {
80
80
  private printLookingForProviderLog;
81
81
  private printFoundInModuleLog;
82
82
  private isDebugMode;
83
+ private getContextId;
83
84
  }
@@ -29,9 +29,13 @@ class Injector {
29
29
  }
30
30
  async loadInstance(wrapper, collection, moduleRef, contextId = constants_2.STATIC_CONTEXT, inquirer) {
31
31
  const inquirerId = this.getInquirerId(inquirer);
32
- const instanceHost = wrapper.getInstanceByContextId(contextId, inquirerId);
32
+ const instanceHost = wrapper.getInstanceByContextId(this.getContextId(contextId, wrapper), inquirerId);
33
33
  if (instanceHost.isPending) {
34
- return instanceHost.donePromise;
34
+ return instanceHost.donePromise.then((err) => {
35
+ if (err) {
36
+ throw err;
37
+ }
38
+ });
35
39
  }
36
40
  const done = this.applyDoneHook(instanceHost);
37
41
  const token = wrapper.token || wrapper.name;
@@ -43,13 +47,19 @@ class Injector {
43
47
  if (instanceHost.isResolved) {
44
48
  return done();
45
49
  }
46
- const callback = async (instances) => {
47
- const properties = await this.resolveProperties(wrapper, moduleRef, inject, contextId, wrapper, inquirer);
48
- const instance = await this.instantiateClass(instances, wrapper, targetWrapper, contextId, inquirer);
49
- this.applyProperties(instance, properties);
50
- done();
51
- };
52
- await this.resolveConstructorParams(wrapper, moduleRef, inject, callback, contextId, wrapper, inquirer);
50
+ try {
51
+ const callback = async (instances) => {
52
+ const properties = await this.resolveProperties(wrapper, moduleRef, inject, contextId, wrapper, inquirer);
53
+ const instance = await this.instantiateClass(instances, wrapper, targetWrapper, contextId, inquirer);
54
+ this.applyProperties(instance, properties);
55
+ done();
56
+ };
57
+ await this.resolveConstructorParams(wrapper, moduleRef, inject, callback, contextId, wrapper, inquirer);
58
+ }
59
+ catch (err) {
60
+ done(err);
61
+ throw err;
62
+ }
53
63
  }
54
64
  async loadMiddleware(wrapper, collection, moduleRef, contextId = constants_2.STATIC_CONTEXT, inquirer) {
55
65
  const { metatype, token } = wrapper;
@@ -104,7 +114,7 @@ class Injector {
104
114
  inquirerId = this.getInquirerId(parentInquirer);
105
115
  }
106
116
  const paramWrapper = await this.resolveSingleParam(wrapper, param, { index, dependencies }, moduleRef, contextId, inquirer, index);
107
- const instanceHost = paramWrapper.getInstanceByContextId(contextId, inquirerId);
117
+ const instanceHost = paramWrapper.getInstanceByContextId(this.getContextId(contextId, paramWrapper), inquirerId);
108
118
  if (!instanceHost.isResolved && !paramWrapper.forwardRef) {
109
119
  isResolved = false;
110
120
  }
@@ -187,7 +197,7 @@ class Injector {
187
197
  async resolveComponentHost(moduleRef, instanceWrapper, contextId = constants_2.STATIC_CONTEXT, inquirer) {
188
198
  var _a;
189
199
  const inquirerId = this.getInquirerId(inquirer);
190
- const instanceHost = instanceWrapper.getInstanceByContextId(contextId, inquirerId);
200
+ const instanceHost = instanceWrapper.getInstanceByContextId(this.getContextId(contextId, instanceWrapper), inquirerId);
191
201
  if (!instanceHost.isResolved && !instanceWrapper.forwardRef) {
192
202
  await this.loadProvider(instanceWrapper, (_a = instanceWrapper.host) !== null && _a !== void 0 ? _a : moduleRef, contextId, inquirer);
193
203
  }
@@ -205,7 +215,7 @@ class Injector {
205
215
  instanceHost.donePromise.then(() => this.loadProvider(instanceWrapper, moduleRef, contextId, inquirer));
206
216
  }
207
217
  if (instanceWrapper.async) {
208
- const host = instanceWrapper.getInstanceByContextId(contextId, inquirerId);
218
+ const host = instanceWrapper.getInstanceByContextId(this.getContextId(contextId, instanceWrapper), inquirerId);
209
219
  host.instance = await host.instance;
210
220
  instanceWrapper.setInstanceByContextId(contextId, host, inquirerId);
211
221
  }
@@ -260,7 +270,7 @@ class Injector {
260
270
  instanceWrapperRef = providers.get(name);
261
271
  this.addDependencyMetadata(keyOrIndex, wrapper, instanceWrapperRef);
262
272
  const inquirerId = this.getInquirerId(inquirer);
263
- const instanceHost = instanceWrapperRef.getInstanceByContextId(contextId, inquirerId);
273
+ const instanceHost = instanceWrapperRef.getInstanceByContextId(this.getContextId(contextId, instanceWrapperRef), inquirerId);
264
274
  if (!instanceHost.isResolved && !instanceWrapperRef.forwardRef) {
265
275
  await this.loadProvider(instanceWrapperRef, relatedModule, contextId, wrapper);
266
276
  break;
@@ -291,7 +301,7 @@ class Injector {
291
301
  return undefined;
292
302
  }
293
303
  const inquirerId = this.getInquirerId(inquirer);
294
- const instanceHost = paramWrapper.getInstanceByContextId(contextId, inquirerId);
304
+ const instanceHost = paramWrapper.getInstanceByContextId(this.getContextId(contextId, paramWrapper), inquirerId);
295
305
  return instanceHost.instance;
296
306
  }
297
307
  catch (err) {
@@ -319,7 +329,7 @@ class Injector {
319
329
  async instantiateClass(instances, wrapper, targetMetatype, contextId = constants_2.STATIC_CONTEXT, inquirer) {
320
330
  const { metatype, inject } = wrapper;
321
331
  const inquirerId = this.getInquirerId(inquirer);
322
- const instanceHost = targetMetatype.getInstanceByContextId(contextId, inquirerId);
332
+ const instanceHost = targetMetatype.getInstanceByContextId(this.getContextId(contextId, targetMetatype), inquirerId);
323
333
  const isInContext = wrapper.isStatic(contextId, inquirer) ||
324
334
  wrapper.isInRequestScope(contextId, inquirer) ||
325
335
  wrapper.isLazyTransient(contextId, inquirer) ||
@@ -343,7 +353,7 @@ class Injector {
343
353
  }
344
354
  await this.loadInstance(wrapper, collection, moduleRef, ctx, wrapper);
345
355
  await this.loadEnhancersPerContext(wrapper, ctx, wrapper);
346
- const host = wrapper.getInstanceByContextId(ctx, wrapper.id);
356
+ const host = wrapper.getInstanceByContextId(this.getContextId(ctx, wrapper), wrapper.id);
347
357
  return host && host.instance;
348
358
  }
349
359
  async loadEnhancersPerContext(wrapper, ctx, inquirer) {
@@ -357,7 +367,7 @@ class Injector {
357
367
  async loadCtorMetadata(metadata, contextId, inquirer, parentInquirer) {
358
368
  const hosts = await Promise.all(metadata.map(async (item) => this.resolveScopedComponentHost(item, contextId, inquirer, parentInquirer)));
359
369
  const inquirerId = this.getInquirerId(inquirer);
360
- return hosts.map(item => item.getInstanceByContextId(contextId, inquirerId).instance);
370
+ return hosts.map(item => item.getInstanceByContextId(this.getContextId(contextId, item), inquirerId).instance);
361
371
  }
362
372
  async loadPropertiesMetadata(metadata, contextId, inquirer) {
363
373
  const dependenciesHosts = await Promise.all(metadata.map(async ({ wrapper: item, key }) => ({
@@ -368,7 +378,7 @@ class Injector {
368
378
  return dependenciesHosts.map(({ key, host }) => ({
369
379
  key,
370
380
  name: key,
371
- instance: host.getInstanceByContextId(contextId, inquirerId).instance,
381
+ instance: host.getInstanceByContextId(this.getContextId(contextId, host), inquirerId).instance,
372
382
  }));
373
383
  }
374
384
  getInquirerId(inquirer) {
@@ -428,5 +438,13 @@ class Injector {
428
438
  isDebugMode() {
429
439
  return !!process.env.NEST_DEBUG;
430
440
  }
441
+ getContextId(contextId, instanceWrapper) {
442
+ return contextId.getParent
443
+ ? contextId.getParent({
444
+ token: instanceWrapper.token,
445
+ isTreeDurable: instanceWrapper.isDependencyTreeDurable(),
446
+ })
447
+ : contextId;
448
+ }
431
449
  }
432
450
  exports.Injector = Injector;
@@ -3,14 +3,25 @@ import { FactoryProvider } from '@nestjs/common/interfaces';
3
3
  import { InstanceToken, Module } from './module';
4
4
  export declare const INSTANCE_METADATA_SYMBOL: unique symbol;
5
5
  export declare const INSTANCE_ID_SYMBOL: unique symbol;
6
+ export interface HostComponentInfo {
7
+ /**
8
+ * Injection token (or class reference)
9
+ */
10
+ token: InstanceToken;
11
+ /**
12
+ * Flag that indicates whether DI subtree is durable
13
+ */
14
+ isTreeDurable: boolean;
15
+ }
6
16
  export interface ContextId {
7
17
  readonly id: number;
18
+ getParent?(info: HostComponentInfo): ContextId;
8
19
  }
9
20
  export interface InstancePerContext<T> {
10
21
  instance: T;
11
22
  isResolved?: boolean;
12
23
  isPending?: boolean;
13
- donePromise?: Promise<void>;
24
+ donePromise?: Promise<unknown>;
14
25
  }
15
26
  export interface PropertyMetadata {
16
27
  key: symbol | string;
@@ -26,11 +37,14 @@ export declare class InstanceWrapper<T = any> {
26
37
  metatype: Type<T> | Function;
27
38
  inject?: FactoryProvider['inject'];
28
39
  forwardRef?: boolean;
40
+ durable?: boolean;
41
+ private static logger;
29
42
  private readonly values;
30
43
  private readonly [INSTANCE_METADATA_SYMBOL];
31
44
  private readonly [INSTANCE_ID_SYMBOL];
32
45
  private transientMap?;
33
46
  private isTreeStatic;
47
+ private isTreeDurable;
34
48
  constructor(metadata?: Partial<InstanceWrapper<T>> & Partial<InstancePerContext<T>>);
35
49
  get id(): string;
36
50
  set instance(value: T);
@@ -47,6 +61,8 @@ export declare class InstanceWrapper<T = any> {
47
61
  getPropertiesMetadata(): PropertyMetadata[];
48
62
  addEnhancerMetadata(wrapper: InstanceWrapper): void;
49
63
  getEnhancersMetadata(): InstanceWrapper[];
64
+ isDependencyTreeDurable(lookupRegistry?: string[]): boolean;
65
+ introspectDepsAttribute(callback: (collection: InstanceWrapper[], lookupRegistry: string[]) => boolean, lookupRegistry?: string[]): boolean;
50
66
  isDependencyTreeStatic(lookupRegistry?: string[]): boolean;
51
67
  cloneStaticInstance(contextId: ContextId): InstancePerContext<T>;
52
68
  cloneTransientInstance(contextId: ContextId, inquirerId: string): InstancePerContext<T>;
@@ -58,6 +74,8 @@ export declare class InstanceWrapper<T = any> {
58
74
  getStaticTransientInstances(): InstancePerContext<T>[];
59
75
  mergeWith(provider: Provider): void;
60
76
  private isNewable;
61
- private isWrapperListStatic;
62
77
  private initialize;
78
+ private printIntrospectedAsRequestScoped;
79
+ private printIntrospectedAsDurable;
80
+ private isDebugMode;
63
81
  }
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.InstanceWrapper = exports.INSTANCE_ID_SYMBOL = exports.INSTANCE_METADATA_SYMBOL = void 0;
5
5
  const tslib_1 = require("tslib");
6
6
  const common_1 = require("@nestjs/common");
7
+ const cli_colors_util_1 = require("@nestjs/common/utils/cli-colors.util");
7
8
  const random_string_generator_util_1 = require("@nestjs/common/utils/random-string-generator.util");
8
9
  const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
9
10
  const iterare_1 = require("iterare");
@@ -100,34 +101,57 @@ class InstanceWrapper {
100
101
  getEnhancersMetadata() {
101
102
  return this[exports.INSTANCE_METADATA_SYMBOL].enhancers;
102
103
  }
103
- isDependencyTreeStatic(lookupRegistry = []) {
104
- if (!(0, shared_utils_1.isUndefined)(this.isTreeStatic)) {
105
- return this.isTreeStatic;
104
+ isDependencyTreeDurable(lookupRegistry = []) {
105
+ if (!(0, shared_utils_1.isUndefined)(this.isTreeDurable)) {
106
+ return this.isTreeDurable;
106
107
  }
107
- if (this.scope === common_1.Scope.REQUEST) {
108
- this.isTreeStatic = false;
109
- return this.isTreeStatic;
108
+ if (this.durable === true) {
109
+ this.isTreeDurable = true;
110
+ this.printIntrospectedAsDurable();
111
+ return this.isTreeDurable;
112
+ }
113
+ const isStatic = this.isDependencyTreeStatic();
114
+ if (isStatic) {
115
+ return false;
116
+ }
117
+ const isTreeNonDurable = this.introspectDepsAttribute((collection, registry) => collection.every((item) => !item.isDependencyTreeDurable(registry)), lookupRegistry);
118
+ this.isTreeDurable = !isTreeNonDurable && this.durable !== false;
119
+ if (this.isTreeDurable) {
120
+ this.printIntrospectedAsDurable();
110
121
  }
122
+ return this.isTreeDurable;
123
+ }
124
+ introspectDepsAttribute(callback, lookupRegistry = []) {
111
125
  if (lookupRegistry.includes(this[exports.INSTANCE_ID_SYMBOL])) {
112
126
  return true;
113
127
  }
114
128
  lookupRegistry = lookupRegistry.concat(this[exports.INSTANCE_ID_SYMBOL]);
115
129
  const { dependencies, properties, enhancers } = this[exports.INSTANCE_METADATA_SYMBOL];
116
- let isStatic = (dependencies &&
117
- this.isWrapperListStatic(dependencies, lookupRegistry)) ||
118
- !dependencies;
119
- if (!isStatic || !(properties || enhancers)) {
120
- this.isTreeStatic = isStatic;
121
- return this.isTreeStatic;
130
+ let introspectionResult = (dependencies && callback(dependencies, lookupRegistry)) || !dependencies;
131
+ if (!introspectionResult || !(properties || enhancers)) {
132
+ return introspectionResult;
122
133
  }
123
134
  const propertiesHosts = (properties || []).map(item => item.wrapper);
124
- isStatic =
125
- isStatic && this.isWrapperListStatic(propertiesHosts, lookupRegistry);
126
- if (!isStatic || !enhancers) {
127
- this.isTreeStatic = isStatic;
135
+ introspectionResult =
136
+ introspectionResult && callback(propertiesHosts, lookupRegistry);
137
+ if (!introspectionResult || !enhancers) {
138
+ return introspectionResult;
139
+ }
140
+ return callback(enhancers, lookupRegistry);
141
+ }
142
+ isDependencyTreeStatic(lookupRegistry = []) {
143
+ if (!(0, shared_utils_1.isUndefined)(this.isTreeStatic)) {
128
144
  return this.isTreeStatic;
129
145
  }
130
- this.isTreeStatic = this.isWrapperListStatic(enhancers, lookupRegistry);
146
+ if (this.scope === common_1.Scope.REQUEST) {
147
+ this.isTreeStatic = false;
148
+ this.printIntrospectedAsRequestScoped();
149
+ return this.isTreeStatic;
150
+ }
151
+ this.isTreeStatic = this.introspectDepsAttribute((collection, registry) => collection.every((item) => item.isDependencyTreeStatic(registry)), lookupRegistry);
152
+ if (!this.isTreeStatic) {
153
+ this.printIntrospectedAsRequestScoped();
154
+ }
131
155
  return this.isTreeStatic;
132
156
  }
133
157
  cloneStaticInstance(contextId) {
@@ -218,9 +242,6 @@ class InstanceWrapper {
218
242
  isNewable() {
219
243
  return (0, shared_utils_1.isNil)(this.inject) && this.metatype && this.metatype.prototype;
220
244
  }
221
- isWrapperListStatic(tree, lookupRegistry) {
222
- return tree.every((item) => item.isDependencyTreeStatic(lookupRegistry));
223
- }
224
245
  initialize(metadata) {
225
246
  const { instance, isResolved } = metadata, wrapperPartial = tslib_1.__rest(metadata, ["instance", "isResolved"]);
226
247
  Object.assign(this, wrapperPartial);
@@ -230,6 +251,26 @@ class InstanceWrapper {
230
251
  });
231
252
  this.scope === common_1.Scope.TRANSIENT && (this.transientMap = new Map());
232
253
  }
254
+ printIntrospectedAsRequestScoped() {
255
+ if (!this.isDebugMode() || this.name === 'REQUEST') {
256
+ return;
257
+ }
258
+ if ((0, shared_utils_1.isString)(this.name)) {
259
+ InstanceWrapper.logger.log(`${cli_colors_util_1.clc.cyanBright(this.name)}${cli_colors_util_1.clc.green(' introspected as ')}${cli_colors_util_1.clc.magentaBright('request-scoped')}`);
260
+ }
261
+ }
262
+ printIntrospectedAsDurable() {
263
+ if (!this.isDebugMode()) {
264
+ return;
265
+ }
266
+ if ((0, shared_utils_1.isString)(this.name)) {
267
+ InstanceWrapper.logger.log(`${cli_colors_util_1.clc.cyanBright(this.name)}${cli_colors_util_1.clc.green(' introspected as ')}${cli_colors_util_1.clc.magentaBright('durable')}`);
268
+ }
269
+ }
270
+ isDebugMode() {
271
+ return !!process.env.NEST_DEBUG;
272
+ }
233
273
  }
234
274
  exports.InstanceWrapper = InstanceWrapper;
235
275
  _a = exports.INSTANCE_METADATA_SYMBOL;
276
+ InstanceWrapper.logger = new common_1.Logger(InstanceWrapper.name);
@@ -5,6 +5,7 @@ const common_1 = require("@nestjs/common");
5
5
  const invalid_class_scope_exception_1 = require("../errors/exceptions/invalid-class-scope.exception");
6
6
  const unknown_element_exception_1 = require("../errors/exceptions/unknown-element.exception");
7
7
  const get_class_scope_1 = require("../helpers/get-class-scope");
8
+ const is_durable_1 = require("../helpers/is-durable");
8
9
  const injector_1 = require("./injector");
9
10
  const instance_links_host_1 = require("./instance-links-host");
10
11
  const instance_wrapper_1 = require("./instance-wrapper");
@@ -64,6 +65,7 @@ class ModuleRef {
64
65
  metatype: type,
65
66
  isResolved: false,
66
67
  scope: (0, get_class_scope_1.getClassScope)(type),
68
+ durable: (0, is_durable_1.isDurable)(type),
67
69
  host: moduleRef,
68
70
  });
69
71
  return new Promise(async (resolve, reject) => {
@@ -10,6 +10,7 @@ const runtime_exception_1 = require("../errors/exceptions/runtime.exception");
10
10
  const unknown_export_exception_1 = require("../errors/exceptions/unknown-export.exception");
11
11
  const context_id_factory_1 = require("../helpers/context-id-factory");
12
12
  const get_class_scope_1 = require("../helpers/get-class-scope");
13
+ const is_durable_1 = require("../helpers/is-durable");
13
14
  const constants_1 = require("./constants");
14
15
  const instance_wrapper_1 = require("./instance-wrapper");
15
16
  const module_ref_1 = require("./module-ref");
@@ -136,6 +137,7 @@ class Module {
136
137
  instance: null,
137
138
  isResolved: false,
138
139
  scope: (0, get_class_scope_1.getClassScope)(injectable),
140
+ durable: (0, is_durable_1.isDurable)(injectable),
139
141
  host: this,
140
142
  });
141
143
  this._injectables.set(injectable, instanceWrapper);
@@ -156,6 +158,7 @@ class Module {
156
158
  instance: null,
157
159
  isResolved: false,
158
160
  scope: (0, get_class_scope_1.getClassScope)(provider),
161
+ durable: (0, is_durable_1.isDurable)(provider),
159
162
  host: this,
160
163
  }));
161
164
  return provider;
@@ -194,11 +197,14 @@ class Module {
194
197
  return exported && exported.module;
195
198
  }
196
199
  addCustomClass(provider, collection) {
197
- let { scope } = provider;
200
+ let { scope, durable } = provider;
198
201
  const { useClass } = provider;
199
202
  if ((0, shared_utils_1.isUndefined)(scope)) {
200
203
  scope = (0, get_class_scope_1.getClassScope)(useClass);
201
204
  }
205
+ if ((0, shared_utils_1.isUndefined)(durable)) {
206
+ durable = (0, is_durable_1.isDurable)(useClass);
207
+ }
202
208
  collection.set(provider.provide, new instance_wrapper_1.InstanceWrapper({
203
209
  token: provider.provide,
204
210
  name: (useClass === null || useClass === void 0 ? void 0 : useClass.name) || useClass,
@@ -206,6 +212,7 @@ class Module {
206
212
  instance: null,
207
213
  isResolved: false,
208
214
  scope,
215
+ durable,
209
216
  host: this,
210
217
  }));
211
218
  }
@@ -222,7 +229,7 @@ class Module {
222
229
  }));
223
230
  }
224
231
  addCustomFactory(provider, collection) {
225
- const { useFactory: factory, inject, scope, provide: providerToken, } = provider;
232
+ const { useFactory: factory, inject, scope, durable, provide: providerToken, } = provider;
226
233
  collection.set(providerToken, new instance_wrapper_1.InstanceWrapper({
227
234
  token: providerToken,
228
235
  name: (providerToken === null || providerToken === void 0 ? void 0 : providerToken.name) || providerToken,
@@ -231,6 +238,7 @@ class Module {
231
238
  isResolved: false,
232
239
  inject: inject || [],
233
240
  scope,
241
+ durable,
234
242
  host: this,
235
243
  }));
236
244
  }
@@ -292,6 +300,7 @@ class Module {
292
300
  instance: null,
293
301
  isResolved: false,
294
302
  scope: (0, get_class_scope_1.getClassScope)(controller),
303
+ durable: (0, is_durable_1.isDurable)(controller),
295
304
  host: this,
296
305
  }));
297
306
  this.assignControllerUniqueId(controller);
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MiddlewareContainer = void 0;
4
- const instance_wrapper_1 = require("../injector/instance-wrapper");
5
4
  const get_class_scope_1 = require("../helpers/get-class-scope");
5
+ const is_durable_1 = require("../helpers/is-durable");
6
+ const instance_wrapper_1 = require("../injector/instance-wrapper");
6
7
  class MiddlewareContainer {
7
8
  constructor(container) {
8
9
  this.container = container;
@@ -27,6 +28,7 @@ class MiddlewareContainer {
27
28
  const token = metatype;
28
29
  middleware.set(token, new instance_wrapper_1.InstanceWrapper({
29
30
  scope: (0, get_class_scope_1.getClassScope)(metatype),
31
+ durable: (0, is_durable_1.isDurable)(metatype),
30
32
  name: token,
31
33
  metatype,
32
34
  token,
@@ -39,13 +39,11 @@ export declare class NestApplication extends NestApplicationContext implements I
39
39
  getMicroservices(): INestMicroservice[];
40
40
  getHttpServer(): any;
41
41
  startAllMicroservices(): Promise<this>;
42
- startAllMicroservicesAsync(): Promise<this>;
43
42
  use(...args: [any, any?]): this;
44
43
  enableCors(options?: CorsOptions | CorsOptionsDelegate<any>): void;
45
44
  enableVersioning(options?: VersioningOptions): this;
46
45
  listen(port: number | string): Promise<any>;
47
46
  listen(port: number | string, hostname: string): Promise<any>;
48
- listenAsync(port: number | string, ...args: any[]): Promise<any>;
49
47
  getUrl(): Promise<string>;
50
48
  private formatAddress;
51
49
  setGlobalPrefix(prefix: string, options?: GlobalPrefixOptions): this;