@nestjs/core 8.2.0 → 8.2.4

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.
package/Readme.md CHANGED
@@ -57,10 +57,13 @@ With official support, you can get expert help straight from Nest core team. We
57
57
  Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
58
58
 
59
59
  #### Principal Sponsors
60
- <table style="text-align:center;"><tr><td>
60
+ <table style="text-align:center;"><tr>
61
+ <td><a href="https://trilon.io" target="_blank"><img src="https://nestjs.com/img/trilon.svg" width="200" valign="middle" /></a></td>
62
+ <td><a href="https://www.redhat.com" target="_blank"><img src="https://nestjs.com/img/red-hat-logo.svg" width="200" valign="middle" /></a></td>
63
+ <td>
61
64
  <a href="https://github.com/Sanofi-IADC" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/sanofi.png" width="180" valign="middle" /></a></td>
62
65
  <td>
63
- <a href="https://trilon.io" target="_blank"><img src="https://nestjs.com/img/trilon.svg" width="200" valign="middle" /></a></td>
66
+ <a href="https://nx.dev" target="_blank"><img src="https://nestjs.com/img/nx-logo.png" height="45" valign="middle" /></a></td>
64
67
  </tr></table>
65
68
 
66
69
  #### Gold Sponsors
@@ -78,7 +81,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
78
81
  <table style="text-align:center;"><tr><td>
79
82
  <a href="https://neoteric.eu/" target="_blank"><img src="https://nestjs.com/img/neoteric-cut.png" width="120" valign="middle" /></a> </td><td>
80
83
  <a href="http://gojob.com" target="_blank"><img src="http://nestjs.com/img/gojob-logo.png" valign="middle" width="100" /></a> </td><td>
81
- <a href="http://www.leogistics.com" target="_blank"><img src="https://nestjs.com/img/leogistics-logo.jpeg" width="150" valign="middle" /></td><td>
84
+ <a href="https://www.myleodsc.com/" target="_blank"><img src="https://nestjs.com/img/myleo-logo.png" width="180" valign="middle" /></td><td>
82
85
  <a href="https://careers.meetdandy.com/?gh_src=063ba61e3us" target="_blank"><img src="https://nestjs.com/img/dandy-roles-logo.svg" width="150" valign="middle" /></td><td>
83
86
  <a href="https://www.castlecraft.in" target="_blank"><img src="https://nestjs.com/img/castlecraft-logo.png" width="150" valign="middle" /></td>
84
87
  <td><a href="https://www.tinystacks.com" target="_blank"><img src="https://nestjs.com/img/tinystacks-logo.png#1" width="140" valign="middle" /></td></tr></table>
@@ -113,6 +116,8 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
113
116
  <td align="center" valign="middle"><a href="https://studyclerk.com/pay-for-research-paper" target="_blank"><img src="https://nestjs.com/img/studyclerk-logo.png" width="125" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://xyndata.com" target="_blank"><img src="https://nestjs.com/img/xyndata-logo.png" width="125" valign="middle" /></a></td></tr><tr>
114
117
  <td align="center" valign="middle"><a href="https://www.anonymistic.com/" target="_blank"><img src="https://nestjs.com/img/anonymistic-logo.png" width="125" valign="middle" /></a></td>
115
118
  <td align="center" valign="middle"><a href="https://www.naologic.com/" target="_blank"><img src="https://nestjs.com/img/naologic-logo.svg" width="125" valign="middle" /></a></td>
119
+ <td align="center" valign="middle"><a href="https://messaged.com/" target="_blank"><img src="https://nestjs.com/img/messaged-logo.png" width="50" valign="middle" /></a></td>
120
+ <td align="center" valign="middle"><a href="https://triplecore.io" target="_blank"><img src="https://nestjs.com/img/triplecore-logo.svg" width="50" valign="middle" /></a></td>
116
121
  </tr></table>
117
122
 
118
123
  ## Backers
@@ -94,6 +94,10 @@ class ApplicationConfig {
94
94
  return this.globalRequestGuards;
95
95
  }
96
96
  enableVersioning(options) {
97
+ if (Array.isArray(options.defaultVersion)) {
98
+ // Drop duplicated versions
99
+ options.defaultVersion = Array.from(new Set(options.defaultVersion));
100
+ }
97
101
  this.versioningOptions = options;
98
102
  }
99
103
  getVersioning() {
@@ -0,0 +1,4 @@
1
+ import { RuntimeException } from './runtime.exception';
2
+ export declare class InvalidClassModuleException extends RuntimeException {
3
+ constructor(metatypeUsedAsAModule: any, scope: any[]);
4
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InvalidClassModuleException = void 0;
4
+ const messages_1 = require("../messages");
5
+ const runtime_exception_1 = require("./runtime.exception");
6
+ class InvalidClassModuleException extends runtime_exception_1.RuntimeException {
7
+ constructor(metatypeUsedAsAModule, scope) {
8
+ super(messages_1.USING_INVALID_CLASS_AS_A_MODULE_MESSAGE(metatypeUsedAsAModule, scope));
9
+ }
10
+ }
11
+ exports.InvalidClassModuleException = InvalidClassModuleException;
@@ -1,10 +1,11 @@
1
- import { Type } from '@nestjs/common';
1
+ import type { ForwardReference, Type } from '@nestjs/common';
2
2
  import { InjectorDependencyContext } from '../injector/injector';
3
3
  import { Module } from '../injector/module';
4
4
  export declare const UNKNOWN_DEPENDENCIES_MESSAGE: (type: string | symbol, unknownDependencyContext: InjectorDependencyContext, module: Module) => string;
5
5
  export declare const INVALID_MIDDLEWARE_MESSAGE: (text: TemplateStringsArray, name: string) => string;
6
6
  export declare const UNDEFINED_FORWARDREF_MESSAGE: (scope: Type<any>[]) => string;
7
7
  export declare const INVALID_MODULE_MESSAGE: (parentModule: any, index: number, scope: any[]) => string;
8
+ export declare const USING_INVALID_CLASS_AS_A_MODULE_MESSAGE: (metatypeUsedAsAModule: Type | ForwardReference, scope: any[]) => string;
8
9
  export declare const UNDEFINED_MODULE_MESSAGE: (parentModule: any, index: number, scope: any[]) => string;
9
10
  export declare const UNKNOWN_EXPORT_MESSAGE: (token: string | symbol, module: string) => string;
10
11
  export declare const INVALID_CLASS_MESSAGE: (text: TemplateStringsArray, value: any) => string;
@@ -1,17 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MICROSERVICES_PACKAGE_NOT_FOUND_EXCEPTION = exports.INVALID_EXCEPTION_FILTER = exports.UNHANDLED_RUNTIME_EXCEPTION = exports.UNKNOWN_REQUEST_MAPPING = exports.INVALID_MIDDLEWARE_CONFIGURATION = exports.INVALID_CLASS_SCOPE_MESSAGE = exports.INVALID_CLASS_MESSAGE = exports.UNKNOWN_EXPORT_MESSAGE = exports.UNDEFINED_MODULE_MESSAGE = exports.INVALID_MODULE_MESSAGE = exports.UNDEFINED_FORWARDREF_MESSAGE = exports.INVALID_MIDDLEWARE_MESSAGE = exports.UNKNOWN_DEPENDENCIES_MESSAGE = void 0;
3
+ exports.MICROSERVICES_PACKAGE_NOT_FOUND_EXCEPTION = exports.INVALID_EXCEPTION_FILTER = exports.UNHANDLED_RUNTIME_EXCEPTION = exports.UNKNOWN_REQUEST_MAPPING = exports.INVALID_MIDDLEWARE_CONFIGURATION = exports.INVALID_CLASS_SCOPE_MESSAGE = exports.INVALID_CLASS_MESSAGE = exports.UNKNOWN_EXPORT_MESSAGE = exports.UNDEFINED_MODULE_MESSAGE = exports.USING_INVALID_CLASS_AS_A_MODULE_MESSAGE = exports.INVALID_MODULE_MESSAGE = exports.UNDEFINED_FORWARDREF_MESSAGE = exports.INVALID_MIDDLEWARE_MESSAGE = exports.UNKNOWN_DEPENDENCIES_MESSAGE = void 0;
4
4
  const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
5
5
  /**
6
- * Returns the name of an instance
6
+ * Returns the name of an instance or `undefined`
7
7
  * @param instance The instance which should get the name from
8
8
  */
9
9
  const getInstanceName = (instance) => {
10
- var _a, _b, _c;
10
+ var _a, _b, _c, _d, _e;
11
11
  if ((_a = instance) === null || _a === void 0 ? void 0 : _a.forwardRef) {
12
12
  return (_b = instance.forwardRef()) === null || _b === void 0 ? void 0 : _b.name;
13
13
  }
14
- return (_c = instance) === null || _c === void 0 ? void 0 : _c.name;
14
+ if ((_c = instance) === null || _c === void 0 ? void 0 : _c.module) {
15
+ return (_d = instance.module) === null || _d === void 0 ? void 0 : _d.name;
16
+ }
17
+ return (_e = instance) === null || _e === void 0 ? void 0 : _e.name;
15
18
  };
16
19
  /**
17
20
  * Returns the name of the dependency
@@ -67,16 +70,26 @@ const UNDEFINED_FORWARDREF_MESSAGE = (scope) => `Nest cannot create the module i
67
70
 
68
71
  (Read more: https://docs.nestjs.com/fundamentals/circular-dependency)
69
72
  Scope [${stringifyScope(scope)}]
70
- `;
73
+ `;
71
74
  exports.UNDEFINED_FORWARDREF_MESSAGE = UNDEFINED_FORWARDREF_MESSAGE;
72
75
  const INVALID_MODULE_MESSAGE = (parentModule, index, scope) => {
73
76
  const parentModuleName = (parentModule === null || parentModule === void 0 ? void 0 : parentModule.name) || 'module';
74
77
  return `Nest cannot create the ${parentModuleName} instance.
75
- Received an unexpected value at index [${index}] of the ${parentModuleName} "imports" array.
78
+ Received an unexpected value at index [${index}] of the ${parentModuleName} "imports" array.
76
79
 
77
80
  Scope [${stringifyScope(scope)}]`;
78
81
  };
79
82
  exports.INVALID_MODULE_MESSAGE = INVALID_MODULE_MESSAGE;
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.
88
+
89
+ Scope [${stringifyScope(scope)}]
90
+ `;
91
+ };
92
+ exports.USING_INVALID_CLASS_AS_A_MODULE_MESSAGE = USING_INVALID_CLASS_AS_A_MODULE_MESSAGE;
80
93
  const UNDEFINED_MODULE_MESSAGE = (parentModule, index, scope) => {
81
94
  const parentModuleName = (parentModule === null || parentModule === void 0 ? void 0 : parentModule.name) || 'module';
82
95
  return `Nest cannot create the ${parentModuleName} instance.
@@ -8,19 +8,21 @@ exports.MODULE_INIT_MESSAGE = MODULE_INIT_MESSAGE;
8
8
  const ROUTE_MAPPED_MESSAGE = (path, method) => `Mapped {${path}, ${request_method_enum_1.RequestMethod[method]}} route`;
9
9
  exports.ROUTE_MAPPED_MESSAGE = ROUTE_MAPPED_MESSAGE;
10
10
  const VERSIONED_ROUTE_MAPPED_MESSAGE = (path, method, version) => {
11
- if (version === version_options_interface_1.VERSION_NEUTRAL) {
12
- version = 'Neutral';
13
- }
14
- return `Mapped {${path}, ${request_method_enum_1.RequestMethod[method]}} (version: ${version}) route`;
11
+ const controllerVersions = Array.isArray(version) ? version : [version];
12
+ const versions = controllerVersions
13
+ .map(version => (version === version_options_interface_1.VERSION_NEUTRAL ? 'Neutral' : version))
14
+ .join(',');
15
+ return `Mapped {${path}, ${request_method_enum_1.RequestMethod[method]}} (version: ${versions}) route`;
15
16
  };
16
17
  exports.VERSIONED_ROUTE_MAPPED_MESSAGE = VERSIONED_ROUTE_MAPPED_MESSAGE;
17
18
  const CONTROLLER_MAPPING_MESSAGE = (name, path) => `${name} {${path}}:`;
18
19
  exports.CONTROLLER_MAPPING_MESSAGE = CONTROLLER_MAPPING_MESSAGE;
19
20
  const VERSIONED_CONTROLLER_MAPPING_MESSAGE = (name, path, version) => {
20
- if (version === version_options_interface_1.VERSION_NEUTRAL) {
21
- version = 'Neutral';
22
- }
23
- return `${name} {${path}} (version: ${version}):`;
21
+ const controllerVersions = Array.isArray(version) ? version : [version];
22
+ const versions = controllerVersions
23
+ .map(version => (version === version_options_interface_1.VERSION_NEUTRAL ? 'Neutral' : version))
24
+ .join(',');
25
+ return `${name} {${path}} (version: ${versions}):`;
24
26
  };
25
27
  exports.VERSIONED_CONTROLLER_MAPPING_MESSAGE = VERSIONED_CONTROLLER_MAPPING_MESSAGE;
26
28
  const INVALID_EXECUTION_CONTEXT = (methodName, currentContext) => `Calling ${methodName} is not allowed in this context. Your current execution context is "${currentContext}".`;
@@ -10,7 +10,7 @@ const transient_instances_1 = require("../injector/helpers/transient-instances")
10
10
  * @param instance The instance which should be checked
11
11
  */
12
12
  function hasBeforeApplicationShutdownHook(instance) {
13
- return !shared_utils_1.isNil(instance.beforeApplicationShutdown);
13
+ return shared_utils_1.isFunction(instance.beforeApplicationShutdown);
14
14
  }
15
15
  /**
16
16
  * Calls the given instances
@@ -10,7 +10,7 @@ const transient_instances_1 = require("../injector/helpers/transient-instances")
10
10
  * @param instance The instance which should be checked
11
11
  */
12
12
  function hasOnAppBootstrapHook(instance) {
13
- return !shared_utils_1.isNil(instance.onApplicationBootstrap);
13
+ return shared_utils_1.isFunction(instance.onApplicationBootstrap);
14
14
  }
15
15
  /**
16
16
  * Calls the given instances
@@ -10,7 +10,7 @@ const transient_instances_1 = require("../injector/helpers/transient-instances")
10
10
  * @param instance The instance which should be checked
11
11
  */
12
12
  function hasOnAppShutdownHook(instance) {
13
- return !shared_utils_1.isNil(instance.onApplicationShutdown);
13
+ return shared_utils_1.isFunction(instance.onApplicationShutdown);
14
14
  }
15
15
  /**
16
16
  * Calls the given instances
@@ -10,7 +10,7 @@ const transient_instances_1 = require("../injector/helpers/transient-instances")
10
10
  * @param instance The instance which should be checked
11
11
  */
12
12
  function hasOnModuleDestroyHook(instance) {
13
- return !shared_utils_1.isNil(instance.onModuleDestroy);
13
+ return shared_utils_1.isFunction(instance.onModuleDestroy);
14
14
  }
15
15
  /**
16
16
  * Calls the given instances onModuleDestroy hook
@@ -10,7 +10,7 @@ const transient_instances_1 = require("../injector/helpers/transient-instances")
10
10
  * @param instance The instance which should be checked
11
11
  */
12
12
  function hasOnModuleInitHook(instance) {
13
- return !shared_utils_1.isNil(instance.onModuleInit);
13
+ return shared_utils_1.isFunction(instance.onModuleInit);
14
14
  }
15
15
  /**
16
16
  * Calls the given instances
@@ -71,7 +71,7 @@ export declare class Injector {
71
71
  private resolveScopedComponentHost;
72
72
  private isInquirerRequest;
73
73
  private isInquirer;
74
- private addDependencyMetadata;
74
+ protected addDependencyMetadata(keyOrIndex: number | string, hostWrapper: InstanceWrapper, instanceWrapper: InstanceWrapper): void;
75
75
  private getTokenName;
76
76
  private printResolvingDependenciesLog;
77
77
  private printLookingForProviderLog;
@@ -137,6 +137,7 @@ class Injector {
137
137
  }
138
138
  async resolveSingleParam(wrapper, param, dependencyContext, moduleRef, contextId = constants_2.STATIC_CONTEXT, inquirer, keyOrIndex) {
139
139
  if (shared_utils_1.isUndefined(param)) {
140
+ this.logger.log('Nest encountered an undefined dependency. This may be due to a circular import or a missing dependency declaration.');
140
141
  throw new undefined_dependency_exception_1.UndefinedDependencyException(wrapper.name, dependencyContext, moduleRef);
141
142
  }
142
143
  const token = this.resolveParamToken(wrapper, param);
@@ -364,12 +365,12 @@ class Injector {
364
365
  return shared_utils_1.isFunction(token) ? token.name : token.toString();
365
366
  }
366
367
  printResolvingDependenciesLog(token, inquirer) {
367
- var _a;
368
+ var _a, _b, _c;
368
369
  if (!this.isDebugMode()) {
369
370
  return;
370
371
  }
371
372
  const tokenName = this.getTokenName(token);
372
- const dependentName = (_a = inquirer === null || inquirer === void 0 ? void 0 : inquirer.name) !== null && _a !== void 0 ? _a : 'unknown';
373
+ const dependentName = (_c = ((inquirer === null || inquirer === void 0 ? void 0 : inquirer.name) && ((_b = (_a = inquirer.name).toString) === null || _b === void 0 ? void 0 : _b.call(_a)))) !== null && _c !== void 0 ? _c : 'unknown';
373
374
  const isAlias = dependentName === tokenName;
374
375
  const messageToPrint = `Resolving dependency ${cli_colors_util_1.clc.cyanBright(tokenName)}${cli_colors_util_1.clc.green(' in the ')}${cli_colors_util_1.clc.yellow(dependentName)}${cli_colors_util_1.clc.green(` provider ${isAlias ? '(alias)' : ''}`)}`;
375
376
  this.logger.log(messageToPrint);
@@ -1,10 +1,11 @@
1
1
  import { Logger } from '@nestjs/common';
2
2
  import { NestContainer } from './container';
3
+ import { Injector } from './injector';
3
4
  import { Module } from './module';
4
5
  export declare class InstanceLoader {
5
- private readonly container;
6
+ protected readonly container: NestContainer;
6
7
  private readonly logger;
7
- private readonly injector;
8
+ protected readonly injector: Injector;
8
9
  constructor(container: NestContainer, logger?: Logger);
9
10
  createInstancesOfDependencies(modules?: Map<string, Module>): Promise<void>;
10
11
  private createPrototypes;
@@ -8,10 +8,10 @@ export declare abstract class ModuleRef {
8
8
  private _instanceLinksHost;
9
9
  private get instanceLinksHost();
10
10
  constructor(container: NestContainer);
11
- abstract get<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | string | symbol, options?: {
11
+ abstract get<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | Function | string | symbol, options?: {
12
12
  strict: boolean;
13
13
  }): TResult;
14
- abstract resolve<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | string | symbol, contextId?: ContextId, options?: {
14
+ abstract resolve<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | Function | string | symbol, contextId?: ContextId, options?: {
15
15
  strict: boolean;
16
16
  }): Promise<TResult>;
17
17
  abstract create<T = any>(type: Type<T>): Promise<T>;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ModuleTokenFactory = void 0;
4
4
  const random_string_generator_util_1 = require("@nestjs/common/utils/random-string-generator.util");
5
+ const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
5
6
  const fast_safe_stringify_1 = require("fast-safe-stringify");
6
7
  const hash = require("object-hash");
7
8
  class ModuleTokenFactory {
@@ -38,7 +39,7 @@ class ModuleTokenFactory {
38
39
  return metatype.name;
39
40
  }
40
41
  replacer(key, value) {
41
- if (typeof value === 'function') {
42
+ if (shared_utils_1.isFunction(value)) {
42
43
  const funcAsString = value.toString();
43
44
  const isClass = /^class\s/.test(funcAsString);
44
45
  if (isClass) {
@@ -46,7 +47,7 @@ class ModuleTokenFactory {
46
47
  }
47
48
  return hash(funcAsString, { ignoreUnknown: true });
48
49
  }
49
- if (typeof value === 'symbol') {
50
+ if (shared_utils_1.isSymbol(value)) {
50
51
  return value.toString();
51
52
  }
52
53
  return value;
@@ -63,7 +63,7 @@ function isMiddlewareClass(middleware) {
63
63
  const middlewareArr = middlewareStr.split(' ');
64
64
  return (middlewareArr[0] === 'function' &&
65
65
  /[A-Z]/.test((_a = middlewareArr[1]) === null || _a === void 0 ? void 0 : _a[0]) &&
66
- typeof ((_b = middleware.prototype) === null || _b === void 0 ? void 0 : _b.use) === 'function');
66
+ shared_utils_1.isFunction((_b = middleware.prototype) === null || _b === void 0 ? void 0 : _b.use));
67
67
  }
68
68
  exports.isMiddlewareClass = isMiddlewareClass;
69
69
  function assignToken(metatype, token = uuid_1.v4()) {
@@ -14,6 +14,7 @@ export declare class NestApplicationContext implements INestApplicationContext {
14
14
  private contextModule;
15
15
  protected isInitialized: boolean;
16
16
  protected readonly injector: Injector;
17
+ private shouldFlushLogsOnOverride;
17
18
  private readonly activeShutdownSignals;
18
19
  private readonly moduleCompiler;
19
20
  private shutdownCleanupRef?;
@@ -40,6 +41,10 @@ export declare class NestApplicationContext implements INestApplicationContext {
40
41
  close(): Promise<void>;
41
42
  useLogger(logger: LoggerService | LogLevel[] | false): void;
42
43
  flushLogs(): void;
44
+ /**
45
+ * Define that it must flush logs right after defining a custom logger.
46
+ */
47
+ flushLogsOnOverride(): void;
43
48
  /**
44
49
  * Enables the usage of shutdown hooks. Will call the
45
50
  * `onApplicationShutdown` function of a provider if the
@@ -24,6 +24,7 @@ class NestApplicationContext {
24
24
  this.contextModule = contextModule;
25
25
  this.isInitialized = false;
26
26
  this.injector = new injector_1.Injector();
27
+ this.shouldFlushLogsOnOverride = false;
27
28
  this.activeShutdownSignals = new Array();
28
29
  this.moduleCompiler = new compiler_1.ModuleCompiler();
29
30
  }
@@ -85,10 +86,19 @@ class NestApplicationContext {
85
86
  }
86
87
  useLogger(logger) {
87
88
  common_1.Logger.overrideLogger(logger);
89
+ if (this.shouldFlushLogsOnOverride) {
90
+ this.flushLogs();
91
+ }
88
92
  }
89
93
  flushLogs() {
90
94
  common_1.Logger.flush();
91
95
  }
96
+ /**
97
+ * Define that it must flush logs right after defining a custom logger.
98
+ */
99
+ flushLogsOnOverride() {
100
+ this.shouldFlushLogsOnOverride = true;
101
+ }
92
102
  /**
93
103
  * Enables the usage of shutdown hooks. Will call the
94
104
  * `onApplicationShutdown` function of a provider if the
@@ -61,8 +61,7 @@ class NestApplication extends nest_application_context_1.NestApplicationContext
61
61
  if (!this.appOptions || !this.appOptions.cors) {
62
62
  return undefined;
63
63
  }
64
- const passCustomOptions = shared_utils_1.isObject(this.appOptions.cors) ||
65
- typeof this.appOptions.cors === 'function';
64
+ const passCustomOptions = shared_utils_1.isObject(this.appOptions.cors) || shared_utils_1.isFunction(this.appOptions.cors);
66
65
  if (!passCustomOptions) {
67
66
  return this.enableCors();
68
67
  }
@@ -200,7 +199,7 @@ class NestApplication extends nest_application_context_1.NestApplicationContext
200
199
  });
201
200
  }
202
201
  formatAddress(address) {
203
- if (typeof address === 'string') {
202
+ if (shared_utils_1.isString(address)) {
204
203
  if (os_1.platform() === 'win32') {
205
204
  return address;
206
205
  }
@@ -276,7 +275,7 @@ class NestApplication extends nest_application_context_1.NestApplicationContext
276
275
  }
277
276
  host() {
278
277
  const address = this.httpServer.address();
279
- if (typeof address === 'string') {
278
+ if (shared_utils_1.isString(address)) {
280
279
  return undefined;
281
280
  }
282
281
  return address && address.address;
package/nest-factory.js CHANGED
@@ -74,6 +74,9 @@ class NestFactoryStatic {
74
74
  const modules = container.getModules().values();
75
75
  const root = modules.next().value;
76
76
  const context = this.createNestInstance(new nest_application_context_1.NestApplicationContext(container, [], root));
77
+ if (this.autoFlushLogs) {
78
+ context.flushLogsOnOverride();
79
+ }
77
80
  return context.init();
78
81
  }
79
82
  createNestInstance(instance) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestjs/core",
3
- "version": "8.2.0",
3
+ "version": "8.2.4",
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": "8.3.2"
37
37
  },
38
38
  "devDependencies": {
39
- "@nestjs/common": "8.2.0"
39
+ "@nestjs/common": "8.2.4"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@nestjs/common": "^8.0.0",
@@ -11,16 +11,21 @@ class RoutePathFactory {
11
11
  create(metadata, requestMethod) {
12
12
  var _a;
13
13
  let paths = [''];
14
- const version = this.getVersion(metadata);
15
- if (version && ((_a = metadata.versioningOptions) === null || _a === void 0 ? void 0 : _a.type) === common_1.VersioningType.URI) {
14
+ const versionOrVersions = this.getVersion(metadata);
15
+ if (versionOrVersions &&
16
+ ((_a = metadata.versioningOptions) === null || _a === void 0 ? void 0 : _a.type) === common_1.VersioningType.URI) {
16
17
  const versionPrefix = this.getVersionPrefix(metadata.versioningOptions);
17
- // Version Neutral - Do not include version in URL
18
- if (version !== common_1.VERSION_NEUTRAL) {
19
- if (Array.isArray(version)) {
20
- paths = common_1.flatten(paths.map(path => version.map(v => path + `/${versionPrefix}${v}`)));
21
- }
22
- else {
23
- paths = paths.map(path => path + `/${versionPrefix}${version}`);
18
+ if (Array.isArray(versionOrVersions)) {
19
+ paths = common_1.flatten(paths.map(path => versionOrVersions.map(version =>
20
+ // Version Neutral - Do not include version in URL
21
+ version === common_1.VERSION_NEUTRAL
22
+ ? path
23
+ : `${path}/${versionPrefix}${version}`)));
24
+ }
25
+ else {
26
+ // Version Neutral - Do not include version in URL
27
+ if (versionOrVersions !== common_1.VERSION_NEUTRAL) {
28
+ paths = paths.map(path => `${path}/${versionPrefix}${versionOrVersions}`);
24
29
  }
25
30
  }
26
31
  }
@@ -158,15 +158,16 @@ class RouterExecutionContext {
158
158
  return await this.responseController.render(result, res, renderTemplate);
159
159
  };
160
160
  }
161
- if (redirectResponse && typeof redirectResponse.url === 'string') {
161
+ if (redirectResponse && shared_utils_1.isString(redirectResponse.url)) {
162
162
  return async (result, res) => {
163
163
  await this.responseController.redirect(result, res, redirectResponse);
164
164
  };
165
165
  }
166
166
  const isSseHandler = !!this.reflectSse(callback);
167
167
  if (isSseHandler) {
168
- return async (result, res, req) => {
169
- await this.responseController.sse(result, res.raw || res, req.raw || req);
168
+ return (result, res, req) => {
169
+ var _a;
170
+ this.responseController.sse(result, res.raw || res, req.raw || req, { additionalHeaders: (_a = res.getHeaders) === null || _a === void 0 ? void 0 : _a.call(res) });
170
171
  };
171
172
  }
172
173
  return async (result, res) => {
@@ -2,7 +2,7 @@
2
2
  import { HttpServer, RequestMethod } from '@nestjs/common';
3
3
  import { IncomingMessage } from 'http';
4
4
  import { Observable } from 'rxjs';
5
- import { HeaderStream } from './sse-stream';
5
+ import { AdditionalHeaders, WritableHeaderStream } from './sse-stream';
6
6
  export interface CustomHeader {
7
7
  name: string;
8
8
  value: string;
@@ -13,6 +13,7 @@ export interface RedirectResponse {
13
13
  }
14
14
  export declare class RouterResponseController {
15
15
  private readonly applicationRef;
16
+ private readonly logger;
16
17
  constructor(applicationRef: HttpServer);
17
18
  apply<TInput = any, TResponse = any>(result: TInput, response: TResponse, httpStatusCode?: number): Promise<any>;
18
19
  redirect<TInput = any, TResponse = any>(resultOrDeferred: TInput, response: TResponse, redirectResponse: RedirectResponse): Promise<void>;
@@ -21,6 +22,8 @@ export declare class RouterResponseController {
21
22
  getStatusByMethod(requestMethod: RequestMethod): number;
22
23
  setHeaders<TResponse = unknown>(response: TResponse, headers: CustomHeader[]): void;
23
24
  setStatus<TResponse = unknown>(response: TResponse, statusCode: number): void;
24
- sse<TInput extends Observable<unknown> = any, TResponse extends HeaderStream = any, TRequest extends IncomingMessage = any>(result: TInput, response: TResponse, request: TRequest): Promise<void>;
25
+ sse<TInput extends Observable<unknown> = any, TResponse extends WritableHeaderStream = any, TRequest extends IncomingMessage = any>(result: TInput, response: TResponse, request: TRequest, options?: {
26
+ additionalHeaders: AdditionalHeaders;
27
+ }): void;
25
28
  private assertObservable;
26
29
  }
@@ -9,6 +9,7 @@ const sse_stream_1 = require("./sse-stream");
9
9
  class RouterResponseController {
10
10
  constructor(applicationRef) {
11
11
  this.applicationRef = applicationRef;
12
+ this.logger = new common_1.Logger(RouterResponseController.name);
12
13
  }
13
14
  async apply(result, response, httpStatusCode) {
14
15
  return this.applicationRef.reply(response, result, httpStatusCode);
@@ -47,21 +48,29 @@ class RouterResponseController {
47
48
  setStatus(response, statusCode) {
48
49
  this.applicationRef.status(response, statusCode);
49
50
  }
50
- async sse(result, response, request) {
51
+ sse(result, response, request, options) {
51
52
  // It's possible that we sent headers already so don't use a stream
52
53
  if (response.writableEnded) {
53
54
  return;
54
55
  }
55
56
  this.assertObservable(result);
56
57
  const stream = new sse_stream_1.SseStream(request);
57
- stream.pipe(response);
58
+ stream.pipe(response, options);
58
59
  const subscription = result
59
- .pipe(operators_1.debounce((message) => new Promise(resolve => {
60
- if (!shared_utils_1.isObject(message)) {
61
- message = { data: message };
60
+ .pipe(operators_1.map((message) => {
61
+ if (shared_utils_1.isObject(message)) {
62
+ return message;
62
63
  }
63
- stream.writeMessage(message, resolve);
64
- })))
64
+ return { data: message };
65
+ }), operators_1.debounce(message => new Promise(resolve => stream.writeMessage(message, () => resolve()))), operators_1.catchError(err => {
66
+ const data = err instanceof Error ? err.message : err;
67
+ stream.writeMessage({ type: 'error', data }, writeError => {
68
+ if (writeError) {
69
+ this.logger.error(writeError);
70
+ }
71
+ });
72
+ return rxjs_1.EMPTY;
73
+ }))
65
74
  .subscribe({
66
75
  complete: () => {
67
76
  response.end();
@@ -2,13 +2,18 @@
2
2
  import { MessageEvent } from '@nestjs/common/interfaces';
3
3
  import { IncomingMessage, OutgoingHttpHeaders } from 'http';
4
4
  import { Transform } from 'stream';
5
+ export declare type AdditionalHeaders = Record<string, string[] | string | number | undefined>;
6
+ interface ReadHeaders {
7
+ getHeaders?(): AdditionalHeaders;
8
+ }
5
9
  interface WriteHeaders {
6
10
  writableEnded?: boolean;
7
11
  writeHead?(statusCode: number, reasonPhrase?: string, headers?: OutgoingHttpHeaders): void;
8
12
  writeHead?(statusCode: number, headers?: OutgoingHttpHeaders): void;
9
13
  flushHeaders?(): void;
10
14
  }
11
- export declare type HeaderStream = NodeJS.WritableStream & WriteHeaders;
15
+ export declare type WritableHeaderStream = NodeJS.WritableStream & WriteHeaders;
16
+ export declare type HeaderStream = WritableHeaderStream & ReadHeaders;
12
17
  /**
13
18
  * Adapted from https://raw.githubusercontent.com/EventSource/node-ssestream
14
19
  * Transforms "messages" to W3C event stream content.
@@ -25,7 +30,8 @@ export declare type HeaderStream = NodeJS.WritableStream & WriteHeaders;
25
30
  export declare class SseStream extends Transform {
26
31
  private lastEventId;
27
32
  constructor(req?: IncomingMessage);
28
- pipe<T extends HeaderStream>(destination: T, options?: {
33
+ pipe<T extends WritableHeaderStream>(destination: T, options?: {
34
+ additionalHeaders?: AdditionalHeaders;
29
35
  end?: boolean;
30
36
  }): T;
31
37
  _transform(message: MessageEvent, encoding: string, callback: (error?: Error | null, data?: any) => void): void;
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SseStream = void 0;
4
+ const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
4
5
  const stream_1 = require("stream");
5
6
  function toDataString(data) {
6
- if (typeof data === 'object') {
7
+ if (shared_utils_1.isObject(data)) {
7
8
  return toDataString(JSON.stringify(data));
8
9
  }
9
10
  return data
@@ -36,17 +37,13 @@ class SseStream extends stream_1.Transform {
36
37
  }
37
38
  pipe(destination, options) {
38
39
  if (destination.writeHead) {
39
- destination.writeHead(200, {
40
+ destination.writeHead(200, Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.additionalHeaders), {
40
41
  // See https://github.com/dunglas/mercure/blob/master/hub/subscribe.go#L124-L130
41
- 'Content-Type': 'text/event-stream',
42
- Connection: 'keep-alive',
42
+ 'Content-Type': 'text/event-stream', Connection: 'keep-alive',
43
43
  // Disable cache, even for old browsers and proxies
44
- 'Cache-Control': 'private, no-cache, no-store, must-revalidate, max-age=0, no-transform',
45
- Pragma: 'no-cache',
46
- Expire: '0',
44
+ 'Cache-Control': 'private, no-cache, no-store, must-revalidate, max-age=0, no-transform', Pragma: 'no-cache', Expire: '0',
47
45
  // NGINX support https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/#x-accel-buffering
48
- 'X-Accel-Buffering': 'no',
49
- });
46
+ 'X-Accel-Buffering': 'no' }));
50
47
  destination.flushHeaders();
51
48
  }
52
49
  destination.write(':\n');
@@ -11,7 +11,7 @@ function flattenRoutePaths(routes) {
11
11
  if (item.children) {
12
12
  const childrenRef = item.children;
13
13
  childrenRef.forEach(child => {
14
- if (typeof child !== 'string' && child.path) {
14
+ if (!shared_utils_1.isString(child) && child.path) {
15
15
  child.path = shared_utils_1.normalizePath(shared_utils_1.normalizePath(item.path) + shared_utils_1.normalizePath(child.path));
16
16
  }
17
17
  else {
package/scanner.d.ts CHANGED
@@ -11,11 +11,12 @@ export declare class DependenciesScanner {
11
11
  private readonly container;
12
12
  private readonly metadataScanner;
13
13
  private readonly applicationConfig;
14
+ private readonly logger;
14
15
  private readonly applicationProvidersApplyMap;
15
16
  constructor(container: NestContainer, metadataScanner: MetadataScanner, applicationConfig?: ApplicationConfig);
16
17
  scan(module: Type<any>): Promise<void>;
17
18
  scanForModules(moduleDefinition: ForwardReference | Type<unknown> | DynamicModule | Promise<DynamicModule>, scope?: Type<unknown>[], ctxRegistry?: (ForwardReference | DynamicModule | Type<unknown>)[]): Promise<Module[]>;
18
- insertModule(module: any, scope: Type<unknown>[]): Promise<Module | undefined>;
19
+ insertModule(moduleDefinition: any, scope: Type<unknown>[]): Promise<Module | undefined>;
19
20
  scanModulesForDependencies(modules?: Map<string, Module>): Promise<void>;
20
21
  reflectImports(module: Type<unknown>, token: string, context: string): Promise<void>;
21
22
  reflectProviders(module: Type<any>, token: string): void;
@@ -47,7 +48,22 @@ export declare class DependenciesScanner {
47
48
  [type: string]: Function;
48
49
  };
49
50
  isDynamicModule(module: Type<any> | DynamicModule): module is DynamicModule;
50
- isForwardReference(module: Type<any> | DynamicModule | ForwardReference): module is ForwardReference;
51
+ /**
52
+ * @param metatype
53
+ * @returns `true` if `metatype` is annotated with the `@Injectable()` decorator.
54
+ */
55
+ private isInjectable;
56
+ /**
57
+ * @param metatype
58
+ * @returns `true` if `metatype` is annotated with the `@Controller()` decorator.
59
+ */
60
+ private isController;
61
+ /**
62
+ * @param metatype
63
+ * @returns `true` if `metatype` is annotated with the `@Catch()` decorator.
64
+ */
65
+ private isExceptionFilter;
66
+ private isForwardReference;
51
67
  private flatten;
52
68
  private isRequestOrTransient;
53
69
  }
package/scanner.js CHANGED
@@ -11,6 +11,7 @@ const application_config_1 = require("./application-config");
11
11
  const constants_2 = require("./constants");
12
12
  const circular_dependency_exception_1 = require("./errors/exceptions/circular-dependency.exception");
13
13
  const invalid_module_exception_1 = require("./errors/exceptions/invalid-module.exception");
14
+ const invalid_class_module_exception_1 = require("./errors/exceptions/invalid-class-module.exception");
14
15
  const undefined_module_exception_1 = require("./errors/exceptions/undefined-module.exception");
15
16
  const get_class_scope_1 = require("./helpers/get-class-scope");
16
17
  const internal_core_module_factory_1 = require("./injector/internal-core-module-factory");
@@ -19,6 +20,7 @@ class DependenciesScanner {
19
20
  this.container = container;
20
21
  this.metadataScanner = metadataScanner;
21
22
  this.applicationConfig = applicationConfig;
23
+ this.logger = new common_1.Logger(DependenciesScanner.name);
22
24
  this.applicationProvidersApplyMap = [];
23
25
  }
24
26
  async scan(module) {
@@ -65,11 +67,17 @@ class DependenciesScanner {
65
67
  }
66
68
  return [moduleInstance].concat(registeredModuleRefs);
67
69
  }
68
- async insertModule(module, scope) {
69
- if (module && module.forwardRef) {
70
- return this.container.addModule(module.forwardRef(), scope);
70
+ async insertModule(moduleDefinition, scope) {
71
+ const moduleToAdd = this.isForwardReference(moduleDefinition)
72
+ ? moduleDefinition.forwardRef()
73
+ : moduleDefinition;
74
+ if (this.isInjectable(moduleToAdd) ||
75
+ this.isController(moduleToAdd) ||
76
+ this.isExceptionFilter(moduleToAdd)) {
77
+ // TODO(v9): Throw the exception instead of printing a warning
78
+ this.logger.warn(new invalid_class_module_exception_1.InvalidClassModuleException(moduleDefinition, scope).message);
71
79
  }
72
- return this.container.addModule(module, scope);
80
+ return this.container.addModule(moduleToAdd, scope);
73
81
  }
74
82
  async scanModulesForDependencies(modules = this.container.getModules()) {
75
83
  for (const [token, { metatype }] of modules) {
@@ -179,7 +187,7 @@ class DependenciesScanner {
179
187
  if (shared_utils_1.isUndefined(related)) {
180
188
  throw new circular_dependency_exception_1.CircularDependencyException(context);
181
189
  }
182
- if (related && related.forwardRef) {
190
+ if (this.isForwardReference(related)) {
183
191
  return this.container.addImport(related.forwardRef(), token);
184
192
  }
185
193
  await this.container.addImport(related, token);
@@ -288,6 +296,27 @@ class DependenciesScanner {
288
296
  isDynamicModule(module) {
289
297
  return module && !!module.module;
290
298
  }
299
+ /**
300
+ * @param metatype
301
+ * @returns `true` if `metatype` is annotated with the `@Injectable()` decorator.
302
+ */
303
+ isInjectable(metatype) {
304
+ return !!Reflect.getMetadata(constants_1.INJECTABLE_WATERMARK, metatype);
305
+ }
306
+ /**
307
+ * @param metatype
308
+ * @returns `true` if `metatype` is annotated with the `@Controller()` decorator.
309
+ */
310
+ isController(metatype) {
311
+ return !!Reflect.getMetadata(constants_1.CONTROLLER_WATERMARK, metatype);
312
+ }
313
+ /**
314
+ * @param metatype
315
+ * @returns `true` if `metatype` is annotated with the `@Catch()` decorator.
316
+ */
317
+ isExceptionFilter(metatype) {
318
+ return !!Reflect.getMetadata(constants_1.CATCH_WATERMARK, metatype);
319
+ }
291
320
  isForwardReference(module) {
292
321
  return module && !!module.forwardRef;
293
322
  }