@nestjs/core 9.2.1 → 9.3.0-beta.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 (58) hide show
  1. package/LICENSE +1 -1
  2. package/Readme.md +6 -3
  3. package/constants.d.ts +2 -0
  4. package/constants.js +7 -1
  5. package/injector/container.d.ts +9 -5
  6. package/injector/container.js +14 -9
  7. package/injector/injector.d.ts +4 -0
  8. package/injector/injector.js +7 -1
  9. package/injector/instance-loader.d.ts +6 -4
  10. package/injector/instance-loader.js +17 -7
  11. package/injector/instance-wrapper.d.ts +3 -0
  12. package/injector/instance-wrapper.js +10 -1
  13. package/injector/internal-core-module/internal-core-module-factory.d.ts +2 -1
  14. package/injector/internal-core-module/internal-core-module-factory.js +16 -8
  15. package/injector/module.d.ts +18 -7
  16. package/injector/module.js +50 -13
  17. package/injector/modules-container.d.ts +1 -0
  18. package/injector/modules-container.js +3 -0
  19. package/inspector/deterministic-uuid-registry.d.ts +5 -0
  20. package/inspector/deterministic-uuid-registry.js +20 -0
  21. package/inspector/graph-inspector.d.ts +25 -0
  22. package/inspector/graph-inspector.js +136 -0
  23. package/inspector/interfaces/edge.interface.d.ts +28 -0
  24. package/inspector/interfaces/edge.interface.js +2 -0
  25. package/inspector/interfaces/enhancer-metadata-cache-entry.interface.d.ts +12 -0
  26. package/inspector/interfaces/enhancer-metadata-cache-entry.interface.js +2 -0
  27. package/inspector/interfaces/entrypoint.interface.d.ts +23 -0
  28. package/inspector/interfaces/entrypoint.interface.js +2 -0
  29. package/inspector/interfaces/extras.interface.d.ts +18 -0
  30. package/inspector/interfaces/extras.interface.js +2 -0
  31. package/inspector/interfaces/node.interface.d.ts +47 -0
  32. package/inspector/interfaces/node.interface.js +2 -0
  33. package/inspector/noop-graph-inspector.d.ts +2 -0
  34. package/inspector/noop-graph-inspector.js +8 -0
  35. package/inspector/serialized-graph.d.ts +56 -0
  36. package/inspector/serialized-graph.js +104 -0
  37. package/middleware/container.js +2 -1
  38. package/middleware/middleware-module.d.ts +3 -1
  39. package/middleware/middleware-module.js +18 -2
  40. package/middleware/resolver.d.ts +3 -2
  41. package/middleware/resolver.js +7 -8
  42. package/middleware/routes-mapper.d.ts +1 -1
  43. package/middleware/routes-mapper.js +3 -3
  44. package/nest-application-context.d.ts +10 -5
  45. package/nest-application-context.js +39 -4
  46. package/nest-application.d.ts +6 -4
  47. package/nest-application.js +28 -8
  48. package/nest-factory.d.ts +5 -4
  49. package/nest-factory.js +27 -14
  50. package/package.json +2 -2
  51. package/router/paths-explorer.d.ts +18 -0
  52. package/router/paths-explorer.js +37 -0
  53. package/router/router-explorer.d.ts +8 -9
  54. package/router/router-explorer.js +22 -31
  55. package/router/routes-resolver.d.ts +3 -2
  56. package/router/routes-resolver.js +2 -2
  57. package/scanner.d.ts +14 -8
  58. package/scanner.js +67 -36
package/nest-factory.js CHANGED
@@ -10,7 +10,10 @@ const exceptions_zone_1 = require("./errors/exceptions-zone");
10
10
  const load_adapter_1 = require("./helpers/load-adapter");
11
11
  const rethrow_1 = require("./helpers/rethrow");
12
12
  const container_1 = require("./injector/container");
13
+ const injector_1 = require("./injector/injector");
13
14
  const instance_loader_1 = require("./injector/instance-loader");
15
+ const graph_inspector_1 = require("./inspector/graph-inspector");
16
+ const noop_graph_inspector_1 = require("./inspector/noop-graph-inspector");
14
17
  const metadata_scanner_1 = require("./metadata-scanner");
15
18
  const nest_application_1 = require("./nest-application");
16
19
  const nest_application_context_1 = require("./nest-application-context");
@@ -26,54 +29,58 @@ class NestFactoryStatic {
26
29
  this.abortOnError = true;
27
30
  this.autoFlushLogs = false;
28
31
  }
29
- async create(module, serverOrOptions, options) {
32
+ async create(moduleCls, serverOrOptions, options) {
30
33
  const [httpServer, appOptions] = this.isHttpServer(serverOrOptions)
31
34
  ? [serverOrOptions, options]
32
35
  : [this.createHttpAdapter(), serverOrOptions];
33
36
  const applicationConfig = new application_config_1.ApplicationConfig();
34
37
  const container = new container_1.NestContainer(applicationConfig);
38
+ const graphInspector = this.createGraphInspector(appOptions, container);
35
39
  this.setAbortOnError(serverOrOptions, options);
36
40
  this.registerLoggerConfiguration(appOptions);
37
- await this.initialize(module, container, applicationConfig, httpServer);
38
- const instance = new nest_application_1.NestApplication(container, httpServer, applicationConfig, appOptions);
41
+ await this.initialize(moduleCls, container, graphInspector, applicationConfig, appOptions, httpServer);
42
+ const instance = new nest_application_1.NestApplication(container, httpServer, applicationConfig, graphInspector, appOptions);
39
43
  const target = this.createNestInstance(instance);
40
44
  return this.createAdapterProxy(target, httpServer);
41
45
  }
42
46
  /**
43
47
  * Creates an instance of NestMicroservice.
44
48
  *
45
- * @param module Entry (root) application module class
49
+ * @param moduleCls Entry (root) application module class
46
50
  * @param options Optional microservice configuration
47
51
  *
48
52
  * @returns A promise that, when resolved,
49
53
  * contains a reference to the NestMicroservice instance.
50
54
  */
51
- async createMicroservice(module, options) {
55
+ async createMicroservice(moduleCls, options) {
52
56
  const { NestMicroservice } = (0, load_package_util_1.loadPackage)('@nestjs/microservices', 'NestFactory', () => require('@nestjs/microservices'));
53
57
  const applicationConfig = new application_config_1.ApplicationConfig();
54
58
  const container = new container_1.NestContainer(applicationConfig);
59
+ const graphInspector = this.createGraphInspector(options, container);
55
60
  this.setAbortOnError(options);
56
61
  this.registerLoggerConfiguration(options);
57
- await this.initialize(module, container, applicationConfig);
58
- return this.createNestInstance(new NestMicroservice(container, options, applicationConfig));
62
+ await this.initialize(moduleCls, container, graphInspector, applicationConfig, options);
63
+ return this.createNestInstance(new NestMicroservice(container, options, graphInspector, applicationConfig));
59
64
  }
60
65
  /**
61
66
  * Creates an instance of NestApplicationContext.
62
67
  *
63
- * @param module Entry (root) application module class
68
+ * @param moduleCls Entry (root) application module class
64
69
  * @param options Optional Nest application configuration
65
70
  *
66
71
  * @returns A promise that, when resolved,
67
72
  * contains a reference to the NestApplicationContext instance.
68
73
  */
69
- async createApplicationContext(module, options) {
74
+ async createApplicationContext(moduleCls, options) {
70
75
  const container = new container_1.NestContainer();
76
+ const graphInspector = this.createGraphInspector(options, container);
71
77
  this.setAbortOnError(options);
72
78
  this.registerLoggerConfiguration(options);
73
- await this.initialize(module, container);
79
+ const applicationConfig = undefined;
80
+ await this.initialize(moduleCls, container, graphInspector, applicationConfig, options);
74
81
  const modules = container.getModules().values();
75
82
  const root = modules.next().value;
76
- const context = this.createNestInstance(new nest_application_context_1.NestApplicationContext(container, [], root));
83
+ const context = this.createNestInstance(new nest_application_context_1.NestApplicationContext(container, options, root));
77
84
  if (this.autoFlushLogs) {
78
85
  context.flushLogsOnOverride();
79
86
  }
@@ -82,10 +89,11 @@ class NestFactoryStatic {
82
89
  createNestInstance(instance) {
83
90
  return this.createProxy(instance);
84
91
  }
85
- async initialize(module, container, config = new application_config_1.ApplicationConfig(), httpServer = null) {
86
- const instanceLoader = new instance_loader_1.InstanceLoader(container);
92
+ async initialize(module, container, graphInspector, config = new application_config_1.ApplicationConfig(), options = {}, httpServer = null) {
93
+ const injector = new injector_1.Injector({ preview: options.preview });
94
+ const instanceLoader = new instance_loader_1.InstanceLoader(container, injector, graphInspector);
87
95
  const metadataScanner = new metadata_scanner_1.MetadataScanner();
88
- const dependenciesScanner = new scanner_1.DependenciesScanner(container, metadataScanner, config);
96
+ const dependenciesScanner = new scanner_1.DependenciesScanner(container, metadataScanner, graphInspector, config);
89
97
  container.setHttpAdapter(httpServer);
90
98
  const teardown = this.abortOnError === false ? rethrow_1.rethrow : undefined;
91
99
  await (httpServer === null || httpServer === void 0 ? void 0 : httpServer.init());
@@ -187,6 +195,11 @@ class NestFactoryStatic {
187
195
  });
188
196
  return proxy;
189
197
  }
198
+ createGraphInspector(appOptions, container) {
199
+ return (appOptions === null || appOptions === void 0 ? void 0 : appOptions.snapshot)
200
+ ? new graph_inspector_1.GraphInspector(container)
201
+ : noop_graph_inspector_1.NoopGraphInspector;
202
+ }
190
203
  }
191
204
  exports.NestFactoryStatic = NestFactoryStatic;
192
205
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestjs/core",
3
- "version": "9.2.1",
3
+ "version": "9.3.0-beta.2",
4
4
  "description": "Nest - modern, fast, powerful node.js web framework (@core)",
5
5
  "author": "Kamil Mysliwiec",
6
6
  "license": "MIT",
@@ -36,7 +36,7 @@
36
36
  "uuid": "9.0.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@nestjs/common": "9.2.1"
39
+ "@nestjs/common": "^9.3.0-beta.2"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@nestjs/common": "^9.0.0",
@@ -0,0 +1,18 @@
1
+ import { RequestMethod } from '@nestjs/common/enums';
2
+ import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
3
+ import { VersionValue } from '@nestjs/common/interfaces/version-options.interface';
4
+ import { MetadataScanner } from '../metadata-scanner';
5
+ import { RouterProxyCallback } from './router-proxy';
6
+ export interface RouteDefinition {
7
+ path: string[];
8
+ requestMethod: RequestMethod;
9
+ targetCallback: RouterProxyCallback;
10
+ methodName: string;
11
+ version?: VersionValue;
12
+ }
13
+ export declare class PathsExplorer {
14
+ private readonly metadataScanner;
15
+ constructor(metadataScanner: MetadataScanner);
16
+ scanForPaths(instance: Controller, prototype?: object): RouteDefinition[];
17
+ exploreMethodMetadata(instance: Controller, prototype: object, methodName: string): RouteDefinition;
18
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PathsExplorer = void 0;
4
+ const constants_1 = require("@nestjs/common/constants");
5
+ const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
6
+ class PathsExplorer {
7
+ constructor(metadataScanner) {
8
+ this.metadataScanner = metadataScanner;
9
+ }
10
+ scanForPaths(instance, prototype) {
11
+ const instancePrototype = (0, shared_utils_1.isUndefined)(prototype)
12
+ ? Object.getPrototypeOf(instance)
13
+ : prototype;
14
+ return this.metadataScanner.scanFromPrototype(instance, instancePrototype, method => this.exploreMethodMetadata(instance, instancePrototype, method));
15
+ }
16
+ exploreMethodMetadata(instance, prototype, methodName) {
17
+ const instanceCallback = instance[methodName];
18
+ const prototypeCallback = prototype[methodName];
19
+ const routePath = Reflect.getMetadata(constants_1.PATH_METADATA, prototypeCallback);
20
+ if ((0, shared_utils_1.isUndefined)(routePath)) {
21
+ return null;
22
+ }
23
+ const requestMethod = Reflect.getMetadata(constants_1.METHOD_METADATA, prototypeCallback);
24
+ const version = Reflect.getMetadata(constants_1.VERSION_METADATA, prototypeCallback);
25
+ const path = (0, shared_utils_1.isString)(routePath)
26
+ ? [(0, shared_utils_1.addLeadingSlash)(routePath)]
27
+ : routePath.map((p) => (0, shared_utils_1.addLeadingSlash)(p));
28
+ return {
29
+ path,
30
+ requestMethod,
31
+ targetCallback: instanceCallback,
32
+ methodName,
33
+ version,
34
+ };
35
+ }
36
+ }
37
+ exports.PathsExplorer = PathsExplorer;
@@ -8,6 +8,7 @@ import { NestContainer } from '../injector/container';
8
8
  import { Injector } from '../injector/injector';
9
9
  import { InstanceWrapper } from '../injector/instance-wrapper';
10
10
  import { Module } from '../injector/module';
11
+ import { GraphInspector } from '../inspector/graph-inspector';
11
12
  import { MetadataScanner } from '../metadata-scanner';
12
13
  import { ExceptionsFilter } from './interfaces/exceptions-filter.interface';
13
14
  import { RoutePathMetadata } from './interfaces/route-path-metadata.interface';
@@ -21,22 +22,20 @@ export interface RouteDefinition {
21
22
  version?: VersionValue;
22
23
  }
23
24
  export declare class RouterExplorer {
24
- private readonly metadataScanner;
25
25
  private readonly container;
26
- private readonly injector?;
27
- private readonly routerProxy?;
28
- private readonly exceptionsFilter?;
29
- private readonly config?;
30
- private readonly routePathFactory?;
26
+ private readonly injector;
27
+ private readonly routerProxy;
28
+ private readonly exceptionsFilter;
29
+ private readonly routePathFactory;
30
+ private readonly graphInspector;
31
31
  private readonly executionContextCreator;
32
+ private readonly pathsExplorer;
32
33
  private readonly routerMethodFactory;
33
34
  private readonly logger;
34
35
  private readonly exceptionFiltersCache;
35
- constructor(metadataScanner: MetadataScanner, container: NestContainer, injector?: Injector, routerProxy?: RouterProxy, exceptionsFilter?: ExceptionsFilter, config?: ApplicationConfig, routePathFactory?: RoutePathFactory);
36
+ constructor(metadataScanner: MetadataScanner, container: NestContainer, injector: Injector, routerProxy: RouterProxy, exceptionsFilter: ExceptionsFilter, config: ApplicationConfig, routePathFactory: RoutePathFactory, graphInspector: GraphInspector);
36
37
  explore<T extends HttpServer = any>(instanceWrapper: InstanceWrapper, moduleKey: string, applicationRef: T, host: string | RegExp | Array<string | RegExp>, routePathMetadata: RoutePathMetadata): void;
37
38
  extractRouterPath(metatype: Type<Controller>): string[];
38
- scanForPaths(instance: Controller, prototype?: object): RouteDefinition[];
39
- exploreMethodMetadata(instance: Controller, prototype: object, methodName: string): RouteDefinition;
40
39
  applyPathsToRouterProxy<T extends HttpServer>(router: T, routeDefinitions: RouteDefinition[], instanceWrapper: InstanceWrapper, moduleKey: string, routePathMetadata: RoutePathMetadata, host: string | RegExp | Array<string | RegExp>): void;
41
40
  private applyCallbackToRouter;
42
41
  private applyHostFilter;
@@ -19,23 +19,24 @@ const interceptors_consumer_1 = require("../interceptors/interceptors-consumer")
19
19
  const interceptors_context_creator_1 = require("../interceptors/interceptors-context-creator");
20
20
  const pipes_consumer_1 = require("../pipes/pipes-consumer");
21
21
  const pipes_context_creator_1 = require("../pipes/pipes-context-creator");
22
+ const paths_explorer_1 = require("./paths-explorer");
22
23
  const request_constants_1 = require("./request/request-constants");
23
24
  const route_params_factory_1 = require("./route-params-factory");
24
25
  const router_execution_context_1 = require("./router-execution-context");
25
26
  class RouterExplorer {
26
- constructor(metadataScanner, container, injector, routerProxy, exceptionsFilter, config, routePathFactory) {
27
- this.metadataScanner = metadataScanner;
27
+ constructor(metadataScanner, container, injector, routerProxy, exceptionsFilter, config, routePathFactory, graphInspector) {
28
28
  this.container = container;
29
29
  this.injector = injector;
30
30
  this.routerProxy = routerProxy;
31
31
  this.exceptionsFilter = exceptionsFilter;
32
- this.config = config;
33
32
  this.routePathFactory = routePathFactory;
33
+ this.graphInspector = graphInspector;
34
34
  this.routerMethodFactory = new router_method_factory_1.RouterMethodFactory();
35
35
  this.logger = new logger_service_1.Logger(RouterExplorer.name, {
36
36
  timestamp: true,
37
37
  });
38
38
  this.exceptionFiltersCache = new WeakMap();
39
+ this.pathsExplorer = new paths_explorer_1.PathsExplorer(metadataScanner);
39
40
  const routeParamsFactory = new route_params_factory_1.RouteParamsFactory();
40
41
  const pipesContextCreator = new pipes_context_creator_1.PipesContextCreator(container, config);
41
42
  const pipesConsumer = new pipes_consumer_1.PipesConsumer();
@@ -47,7 +48,7 @@ class RouterExplorer {
47
48
  }
48
49
  explore(instanceWrapper, moduleKey, applicationRef, host, routePathMetadata) {
49
50
  const { instance } = instanceWrapper;
50
- const routerPaths = this.scanForPaths(instance);
51
+ const routerPaths = this.pathsExplorer.scanForPaths(instance);
51
52
  this.applyPathsToRouterProxy(applicationRef, routerPaths, instanceWrapper, moduleKey, routePathMetadata, host);
52
53
  }
53
54
  extractRouterPath(metatype) {
@@ -60,32 +61,6 @@ class RouterExplorer {
60
61
  }
61
62
  return [(0, shared_utils_1.addLeadingSlash)(path)];
62
63
  }
63
- scanForPaths(instance, prototype) {
64
- const instancePrototype = (0, shared_utils_1.isUndefined)(prototype)
65
- ? Object.getPrototypeOf(instance)
66
- : prototype;
67
- return this.metadataScanner.scanFromPrototype(instance, instancePrototype, method => this.exploreMethodMetadata(instance, instancePrototype, method));
68
- }
69
- exploreMethodMetadata(instance, prototype, methodName) {
70
- const instanceCallback = instance[methodName];
71
- const prototypeCallback = prototype[methodName];
72
- const routePath = Reflect.getMetadata(constants_1.PATH_METADATA, prototypeCallback);
73
- if ((0, shared_utils_1.isUndefined)(routePath)) {
74
- return null;
75
- }
76
- const requestMethod = Reflect.getMetadata(constants_1.METHOD_METADATA, prototypeCallback);
77
- const version = Reflect.getMetadata(constants_1.VERSION_METADATA, prototypeCallback);
78
- const path = (0, shared_utils_1.isString)(routePath)
79
- ? [(0, shared_utils_1.addLeadingSlash)(routePath)]
80
- : routePath.map((p) => (0, shared_utils_1.addLeadingSlash)(p));
81
- return {
82
- path,
83
- requestMethod,
84
- targetCallback: instanceCallback,
85
- methodName,
86
- version,
87
- };
88
- }
89
64
  applyPathsToRouterProxy(router, routeDefinitions, instanceWrapper, moduleKey, routePathMetadata, host) {
90
65
  (routeDefinitions || []).forEach(routeDefinition => {
91
66
  const { version: methodVersion } = routeDefinition;
@@ -115,7 +90,23 @@ class RouterExplorer {
115
90
  }
116
91
  routePathMetadata.methodPath = path;
117
92
  const pathsToRegister = this.routePathFactory.create(routePathMetadata, requestMethod);
118
- pathsToRegister.forEach(path => routerMethodRef(path, routeHandler));
93
+ pathsToRegister.forEach(path => {
94
+ const entrypointDefinition = {
95
+ type: 'http-endpoint',
96
+ methodName,
97
+ className: instanceWrapper.name,
98
+ classNodeId: instanceWrapper.id,
99
+ metadata: {
100
+ key: path,
101
+ path,
102
+ requestMethod: enums_1.RequestMethod[requestMethod],
103
+ methodVersion: routePathMetadata.methodVersion,
104
+ controllerVersion: routePathMetadata.controllerVersion,
105
+ },
106
+ };
107
+ routerMethodRef(path, routeHandler);
108
+ this.graphInspector.insertEntrypointDefinition(entrypointDefinition, instanceWrapper.id);
109
+ });
119
110
  const pathsToLog = this.routePathFactory.create(Object.assign(Object.assign({}, routePathMetadata), { versioningOptions: undefined }), requestMethod);
120
111
  pathsToLog.forEach(path => {
121
112
  if (isVersioned) {
@@ -1,8 +1,9 @@
1
- import { HttpServer, Controller } from '@nestjs/common/interfaces';
1
+ import { Controller, HttpServer } from '@nestjs/common/interfaces';
2
2
  import { ApplicationConfig } from '../application-config';
3
3
  import { NestContainer } from '../injector/container';
4
4
  import { Injector } from '../injector/injector';
5
5
  import { InstanceWrapper } from '../injector/instance-wrapper';
6
+ import { GraphInspector } from '../inspector/graph-inspector';
6
7
  import { Resolver } from './interfaces/resolver.interface';
7
8
  export declare class RoutesResolver implements Resolver {
8
9
  private readonly container;
@@ -13,7 +14,7 @@ export declare class RoutesResolver implements Resolver {
13
14
  private readonly routePathFactory;
14
15
  private readonly routerExceptionsFilter;
15
16
  private readonly routerExplorer;
16
- constructor(container: NestContainer, applicationConfig: ApplicationConfig, injector: Injector);
17
+ constructor(container: NestContainer, applicationConfig: ApplicationConfig, injector: Injector, graphInspector: GraphInspector);
17
18
  resolve<T extends HttpServer>(applicationRef: T, globalPrefix: string): void;
18
19
  registerRouters(routes: Map<string | symbol | Function, InstanceWrapper<Controller>>, moduleName: string, globalPrefix: string, modulePath: string, applicationRef: HttpServer): void;
19
20
  registerNotFoundHandler(): void;
@@ -11,7 +11,7 @@ const router_exception_filters_1 = require("./router-exception-filters");
11
11
  const router_explorer_1 = require("./router-explorer");
12
12
  const router_proxy_1 = require("./router-proxy");
13
13
  class RoutesResolver {
14
- constructor(container, applicationConfig, injector) {
14
+ constructor(container, applicationConfig, injector, graphInspector) {
15
15
  this.container = container;
16
16
  this.applicationConfig = applicationConfig;
17
17
  this.injector = injector;
@@ -23,7 +23,7 @@ class RoutesResolver {
23
23
  this.routerExceptionsFilter = new router_exception_filters_1.RouterExceptionFilters(container, applicationConfig, httpAdapterRef);
24
24
  this.routePathFactory = new route_path_factory_1.RoutePathFactory(this.applicationConfig);
25
25
  const metadataScanner = new metadata_scanner_1.MetadataScanner();
26
- this.routerExplorer = new router_explorer_1.RouterExplorer(metadataScanner, this.container, this.injector, this.routerProxy, this.routerExceptionsFilter, this.applicationConfig, this.routePathFactory);
26
+ this.routerExplorer = new router_explorer_1.RouterExplorer(metadataScanner, this.container, this.injector, this.routerProxy, this.routerExceptionsFilter, this.applicationConfig, this.routePathFactory, graphInspector);
27
27
  }
28
28
  resolve(applicationRef, globalPrefix) {
29
29
  const modules = this.container.getModules();
package/scanner.d.ts CHANGED
@@ -1,18 +1,22 @@
1
1
  import { DynamicModule, ForwardReference, Provider } from '@nestjs/common';
2
+ import { EnhancerSubtype } from '@nestjs/common/constants';
2
3
  import { ClassProvider, ExistingProvider, FactoryProvider, ValueProvider } from '@nestjs/common/interfaces';
3
4
  import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
4
5
  import { Injectable } from '@nestjs/common/interfaces/injectable.interface';
5
6
  import { Type } from '@nestjs/common/interfaces/type.interface';
6
7
  import { ApplicationConfig } from './application-config';
7
8
  import { NestContainer } from './injector/container';
9
+ import { InstanceWrapper } from './injector/instance-wrapper';
8
10
  import { Module } from './injector/module';
11
+ import { GraphInspector } from './inspector/graph-inspector';
9
12
  import { MetadataScanner } from './metadata-scanner';
10
13
  export declare class DependenciesScanner {
11
14
  private readonly container;
12
15
  private readonly metadataScanner;
16
+ private readonly graphInspector;
13
17
  private readonly applicationConfig;
14
18
  private readonly applicationProvidersApplyMap;
15
- constructor(container: NestContainer, metadataScanner: MetadataScanner, applicationConfig?: ApplicationConfig);
19
+ constructor(container: NestContainer, metadataScanner: MetadataScanner, graphInspector: GraphInspector, applicationConfig?: ApplicationConfig);
16
20
  scan(module: Type<any>): Promise<void>;
17
21
  scanForModules(moduleDefinition: ForwardReference | Type<unknown> | DynamicModule | Promise<DynamicModule>, scope?: Type<unknown>[], ctxRegistry?: (ForwardReference | DynamicModule | Type<unknown>)[]): Promise<Module[]>;
18
22
  insertModule(moduleDefinition: any, scope: Type<unknown>[]): Promise<Module | undefined>;
@@ -20,19 +24,22 @@ export declare class DependenciesScanner {
20
24
  reflectImports(module: Type<unknown>, token: string, context: string): Promise<void>;
21
25
  reflectProviders(module: Type<any>, token: string): void;
22
26
  reflectControllers(module: Type<any>, token: string): void;
23
- reflectDynamicMetadata(obj: Type<Injectable>, token: string): void;
27
+ reflectDynamicMetadata(cls: Type<Injectable>, token: string): void;
24
28
  reflectExports(module: Type<unknown>, token: string): void;
25
29
  reflectInjectables(component: Type<Injectable>, token: string, metadataKey: string): void;
26
30
  reflectParamInjectables(component: Type<Injectable>, token: string, metadataKey: string): void;
27
- reflectKeyMetadata(component: Type<Injectable>, key: string, method: string): any;
28
- calculateModulesDistance(): Promise<void>;
31
+ reflectKeyMetadata(component: Type<Injectable>, key: string, methodKey: string): {
32
+ methodKey: string;
33
+ metadata: any;
34
+ };
35
+ calculateModulesDistance(): void;
29
36
  insertImport(related: any, token: string, context: string): Promise<void>;
30
37
  isCustomProvider(provider: Provider): provider is ClassProvider | ValueProvider | FactoryProvider | ExistingProvider;
31
- insertProvider(provider: Provider, token: string): string | symbol | void | Function;
32
- insertInjectable(injectable: Type<Injectable>, token: string, host: Type<Injectable>): void;
38
+ insertProvider(provider: Provider, token: string): string | symbol | Function | InstanceWrapper<unknown>;
39
+ insertInjectable(injectable: Type<Injectable> | object, token: string, host: Type<Injectable>, subtype: EnhancerSubtype, methodKey?: string): InstanceWrapper<any>;
33
40
  insertExportedProvider(exportedProvider: Type<Injectable>, token: string): void;
34
41
  insertController(controller: Type<Controller>, token: string): void;
35
- reflectMetadata(metadataKey: string, metatype: Type<any>): any;
42
+ reflectMetadata<T = any>(metadataKey: string, metatype: Type<any>): T[];
36
43
  registerCoreModule(): Promise<void>;
37
44
  /**
38
45
  * Add either request or transient globally scoped enhancers
@@ -63,6 +70,5 @@ export declare class DependenciesScanner {
63
70
  */
64
71
  private isExceptionFilter;
65
72
  private isForwardReference;
66
- private flatten;
67
73
  private isRequestOrTransient;
68
74
  }
package/scanner.js CHANGED
@@ -1,10 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DependenciesScanner = void 0;
4
- const common_1 = require("@nestjs/common");
5
4
  const constants_1 = require("@nestjs/common/constants");
6
5
  const interfaces_1 = require("@nestjs/common/interfaces");
7
- const random_string_generator_util_1 = require("@nestjs/common/utils/random-string-generator.util");
8
6
  const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
9
7
  const iterare_1 = require("iterare");
10
8
  const application_config_1 = require("./application-config");
@@ -15,10 +13,12 @@ const invalid_module_exception_1 = require("./errors/exceptions/invalid-module.e
15
13
  const undefined_module_exception_1 = require("./errors/exceptions/undefined-module.exception");
16
14
  const get_class_scope_1 = require("./helpers/get-class-scope");
17
15
  const internal_core_module_factory_1 = require("./injector/internal-core-module/internal-core-module-factory");
16
+ const deterministic_uuid_registry_1 = require("./inspector/deterministic-uuid-registry");
18
17
  class DependenciesScanner {
19
- constructor(container, metadataScanner, applicationConfig = new application_config_1.ApplicationConfig()) {
18
+ constructor(container, metadataScanner, graphInspector, applicationConfig = new application_config_1.ApplicationConfig()) {
20
19
  this.container = container;
21
20
  this.metadataScanner = metadataScanner;
21
+ this.graphInspector = graphInspector;
22
22
  this.applicationConfig = applicationConfig;
23
23
  this.applicationProvidersApplyMap = [];
24
24
  }
@@ -114,15 +114,15 @@ class DependenciesScanner {
114
114
  this.reflectDynamicMetadata(item, token);
115
115
  });
116
116
  }
117
- reflectDynamicMetadata(obj, token) {
118
- if (!obj || !obj.prototype) {
117
+ reflectDynamicMetadata(cls, token) {
118
+ if (!cls || !cls.prototype) {
119
119
  return;
120
120
  }
121
- this.reflectInjectables(obj, token, constants_1.GUARDS_METADATA);
122
- this.reflectInjectables(obj, token, constants_1.INTERCEPTORS_METADATA);
123
- this.reflectInjectables(obj, token, constants_1.EXCEPTION_FILTERS_METADATA);
124
- this.reflectInjectables(obj, token, constants_1.PIPES_METADATA);
125
- this.reflectParamInjectables(obj, token, constants_1.ROUTE_ARGS_METADATA);
121
+ this.reflectInjectables(cls, token, constants_1.GUARDS_METADATA);
122
+ this.reflectInjectables(cls, token, constants_1.INTERCEPTORS_METADATA);
123
+ this.reflectInjectables(cls, token, constants_1.EXCEPTION_FILTERS_METADATA);
124
+ this.reflectInjectables(cls, token, constants_1.PIPES_METADATA);
125
+ this.reflectParamInjectables(cls, token, constants_1.ROUTE_ARGS_METADATA);
126
126
  }
127
127
  reflectExports(module, token) {
128
128
  const exports = [
@@ -133,40 +133,50 @@ class DependenciesScanner {
133
133
  }
134
134
  reflectInjectables(component, token, metadataKey) {
135
135
  const controllerInjectables = this.reflectMetadata(metadataKey, component);
136
- const methodsInjectables = this.metadataScanner.scanFromPrototype(null, component.prototype, this.reflectKeyMetadata.bind(this, component, metadataKey));
137
- const flattenMethodsInjectables = this.flatten(methodsInjectables);
138
- const combinedInjectables = [
139
- ...controllerInjectables,
140
- ...flattenMethodsInjectables,
141
- ].filter(shared_utils_1.isFunction);
142
- const injectables = Array.from(new Set(combinedInjectables));
143
- injectables.forEach(injectable => this.insertInjectable(injectable, token, component));
136
+ const methodInjectables = this.metadataScanner.scanFromPrototype(null, component.prototype, this.reflectKeyMetadata.bind(this, component, metadataKey));
137
+ controllerInjectables.forEach(injectable => this.insertInjectable(injectable, token, component, constants_1.ENHANCER_KEY_TO_SUBTYPE_MAP[metadataKey]));
138
+ methodInjectables.forEach(({ methodKey, metadata }) => metadata.forEach(injectable => this.insertInjectable(injectable, token, component, constants_1.ENHANCER_KEY_TO_SUBTYPE_MAP[metadataKey], methodKey)));
144
139
  }
145
140
  reflectParamInjectables(component, token, metadataKey) {
146
- const paramsMetadata = this.metadataScanner.scanFromPrototype(null, component.prototype, method => Reflect.getMetadata(metadataKey, component, method));
147
- const paramsInjectables = this.flatten(paramsMetadata).map((param) => (0, common_1.flatten)(Object.keys(param).map(k => param[k].pipes)).filter(shared_utils_1.isFunction));
148
- (0, common_1.flatten)(paramsInjectables).forEach((injectable) => this.insertInjectable(injectable, token, component));
141
+ const paramsMetadata = this.metadataScanner.scanFromPrototype(null, component.prototype, methodKey => {
142
+ const metadata = Reflect.getMetadata(metadataKey, component, methodKey);
143
+ if (!metadata) {
144
+ return;
145
+ }
146
+ return { methodKey, metadata };
147
+ });
148
+ paramsMetadata.forEach(({ methodKey, metadata }) => {
149
+ const params = Object.values(metadata);
150
+ params
151
+ .map(item => item.pipes)
152
+ .flat(1)
153
+ .forEach(injectable => this.insertInjectable(injectable, token, component, 'pipe', methodKey));
154
+ });
149
155
  }
150
- reflectKeyMetadata(component, key, method) {
156
+ reflectKeyMetadata(component, key, methodKey) {
151
157
  let prototype = component.prototype;
152
158
  do {
153
- const descriptor = Reflect.getOwnPropertyDescriptor(prototype, method);
159
+ const descriptor = Reflect.getOwnPropertyDescriptor(prototype, methodKey);
154
160
  if (!descriptor) {
155
161
  continue;
156
162
  }
157
- return Reflect.getMetadata(key, descriptor.value);
163
+ const metadata = Reflect.getMetadata(key, descriptor.value);
164
+ if (!metadata) {
165
+ return;
166
+ }
167
+ return { methodKey, metadata };
158
168
  } while ((prototype = Reflect.getPrototypeOf(prototype)) &&
159
169
  prototype !== Object.prototype &&
160
170
  prototype);
161
171
  return undefined;
162
172
  }
163
- async calculateModulesDistance() {
173
+ calculateModulesDistance() {
164
174
  const modulesGenerator = this.container.getModules().values();
165
175
  // Skip "InternalCoreModule" from calculating distance
166
176
  modulesGenerator.next();
167
177
  const modulesStack = [];
168
178
  const calculateDistance = (moduleRef, distance = 1) => {
169
- if (modulesStack.includes(moduleRef)) {
179
+ if (!moduleRef || modulesStack.includes(moduleRef)) {
170
180
  return;
171
181
  }
172
182
  modulesStack.push(moduleRef);
@@ -204,7 +214,8 @@ class DependenciesScanner {
204
214
  if (!providersKeys.includes(type)) {
205
215
  return this.container.addProvider(provider, token);
206
216
  }
207
- const providerToken = `${type} (UUID: ${(0, random_string_generator_util_1.randomStringGenerator)()})`;
217
+ const uuid = deterministic_uuid_registry_1.DeterministicUuidRegistry.get(type.toString());
218
+ const providerToken = `${type} (UUID: ${uuid})`;
208
219
  let scope = provider.scope;
209
220
  if ((0, shared_utils_1.isNil)(scope) && provider.useClass) {
210
221
  scope = (0, get_class_scope_1.getClassScope)(provider.useClass);
@@ -216,14 +227,35 @@ class DependenciesScanner {
216
227
  scope,
217
228
  });
218
229
  const newProvider = Object.assign(Object.assign({}, provider), { provide: providerToken, scope });
230
+ const enhancerSubtype = constants_2.ENHANCER_TOKEN_TO_SUBTYPE_MAP[type];
219
231
  const factoryOrClassProvider = newProvider;
220
232
  if (this.isRequestOrTransient(factoryOrClassProvider.scope)) {
221
- return this.container.addInjectable(newProvider, token);
233
+ return this.container.addInjectable(newProvider, token, enhancerSubtype);
234
+ }
235
+ this.container.addProvider(newProvider, token, enhancerSubtype);
236
+ }
237
+ insertInjectable(injectable, token, host, subtype, methodKey) {
238
+ if ((0, shared_utils_1.isFunction)(injectable)) {
239
+ const instanceWrapper = this.container.addInjectable(injectable, token, subtype, host);
240
+ this.graphInspector.insertEnhancerMetadataCache({
241
+ moduleToken: token,
242
+ classRef: host,
243
+ enhancerInstanceWrapper: instanceWrapper,
244
+ targetNodeId: instanceWrapper.id,
245
+ subtype,
246
+ methodKey,
247
+ });
248
+ return instanceWrapper;
249
+ }
250
+ else {
251
+ this.graphInspector.insertEnhancerMetadataCache({
252
+ moduleToken: token,
253
+ classRef: host,
254
+ enhancerRef: injectable,
255
+ methodKey,
256
+ subtype,
257
+ });
222
258
  }
223
- this.container.addProvider(newProvider, token);
224
- }
225
- insertInjectable(injectable, token, host) {
226
- this.container.addInjectable(injectable, token, host);
227
259
  }
228
260
  insertExportedProvider(exportedProvider, token) {
229
261
  this.container.addExportedProvider(exportedProvider, token);
@@ -235,7 +267,7 @@ class DependenciesScanner {
235
267
  return Reflect.getMetadata(metadataKey, metatype) || [];
236
268
  }
237
269
  async registerCoreModule() {
238
- const moduleDefinition = internal_core_module_factory_1.InternalCoreModuleFactory.create(this.container, this, this.container.getModuleCompiler(), this.container.getHttpAdapterHostRef());
270
+ const moduleDefinition = internal_core_module_factory_1.InternalCoreModuleFactory.create(this.container, this, this.container.getModuleCompiler(), this.container.getHttpAdapterHostRef(), this.graphInspector);
239
271
  const [instance] = await this.scanForModules(moduleDefinition);
240
272
  this.container.registerCoreModuleRef(instance);
241
273
  }
@@ -269,9 +301,11 @@ class DependenciesScanner {
269
301
  let instanceWrapper;
270
302
  if (this.isRequestOrTransient(scope)) {
271
303
  instanceWrapper = getInstanceWrapper(moduleKey, providerKey, 'injectables');
304
+ this.graphInspector.insertAttachedEnhancer(instanceWrapper);
272
305
  return applyRequestProvidersMap[type](instanceWrapper);
273
306
  }
274
307
  instanceWrapper = getInstanceWrapper(moduleKey, providerKey, 'providers');
308
+ this.graphInspector.insertAttachedEnhancer(instanceWrapper);
275
309
  applyProvidersMap[type](instanceWrapper.instance);
276
310
  });
277
311
  }
@@ -318,9 +352,6 @@ class DependenciesScanner {
318
352
  isForwardReference(module) {
319
353
  return module && !!module.forwardRef;
320
354
  }
321
- flatten(arr) {
322
- return arr.flat(1);
323
- }
324
355
  isRequestOrTransient(scope) {
325
356
  return scope === interfaces_1.Scope.REQUEST || scope === interfaces_1.Scope.TRANSIENT;
326
357
  }