@nestjs/core 8.4.6 → 9.0.0-next.1

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.
@@ -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
  /**
@@ -51,4 +51,5 @@ export declare abstract class AbstractHttpAdapter<TServer = any, TRequest = any,
51
51
  abstract enableCors(options: CorsOptions | CorsOptionsDelegate<TRequest>, prefix?: string): any;
52
52
  abstract createMiddlewareFactory(requestMethod: RequestMethod): ((path: string, callback: Function) => any) | Promise<(path: string, callback: Function) => any>;
53
53
  abstract getType(): string;
54
+ abstract applyVersionFilter(handler: Function, version: VersionValue, versioningOptions: VersioningOptions): (req: TRequest, res: TResponse, next: () => void) => Function;
54
55
  }
@@ -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
  `;
@@ -1,6 +1,16 @@
1
- import { ContextId } from '../injector/instance-wrapper';
1
+ import { ChildContextIdInfo, ContextId } 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
+ */
10
+ attach(contextId: ContextId, request: T): ((info: ChildContextIdInfo) => ContextId) | undefined;
11
+ }
3
12
  export declare class ContextIdFactory {
13
+ private static strategy?;
4
14
  /**
5
15
  * Generates a context identifier based on the request object.
6
16
  */
@@ -10,4 +20,10 @@ export declare class ContextIdFactory {
10
20
  * @param request request object
11
21
  */
12
22
  static getByRequest<T extends Record<any, any> = any>(request: T, propsToInspect?: string[]): ContextId;
23
+ /**
24
+ * Registers a custom context id strategy that lets you attach
25
+ * a parent context id to the existing context id object.
26
+ * @param strategy strategy instance
27
+ */
28
+ static apply(strategy: ContextIdStrategy): void;
13
29
  }
@@ -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;
@@ -1,6 +1,6 @@
1
1
  export * from './container';
2
2
  export * from './inquirer';
3
- export { ContextId } from './instance-wrapper';
3
+ export { ChildContextIdInfo, ContextId } from './instance-wrapper';
4
4
  export * from './lazy-module-loader';
5
5
  export * from './module-ref';
6
6
  export * from './modules-container';
@@ -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,7 +29,7 @@ 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
34
  return instanceHost.donePromise;
35
35
  }
@@ -104,7 +104,7 @@ class Injector {
104
104
  inquirerId = this.getInquirerId(parentInquirer);
105
105
  }
106
106
  const paramWrapper = await this.resolveSingleParam(wrapper, param, { index, dependencies }, moduleRef, contextId, inquirer, index);
107
- const instanceHost = paramWrapper.getInstanceByContextId(contextId, inquirerId);
107
+ const instanceHost = paramWrapper.getInstanceByContextId(this.getContextId(contextId, paramWrapper), inquirerId);
108
108
  if (!instanceHost.isResolved && !paramWrapper.forwardRef) {
109
109
  isResolved = false;
110
110
  }
@@ -187,7 +187,7 @@ class Injector {
187
187
  async resolveComponentHost(moduleRef, instanceWrapper, contextId = constants_2.STATIC_CONTEXT, inquirer) {
188
188
  var _a;
189
189
  const inquirerId = this.getInquirerId(inquirer);
190
- const instanceHost = instanceWrapper.getInstanceByContextId(contextId, inquirerId);
190
+ const instanceHost = instanceWrapper.getInstanceByContextId(this.getContextId(contextId, instanceWrapper), inquirerId);
191
191
  if (!instanceHost.isResolved && !instanceWrapper.forwardRef) {
192
192
  await this.loadProvider(instanceWrapper, (_a = instanceWrapper.host) !== null && _a !== void 0 ? _a : moduleRef, contextId, inquirer);
193
193
  }
@@ -205,7 +205,7 @@ class Injector {
205
205
  instanceHost.donePromise.then(() => this.loadProvider(instanceWrapper, moduleRef, contextId, inquirer));
206
206
  }
207
207
  if (instanceWrapper.async) {
208
- const host = instanceWrapper.getInstanceByContextId(contextId, inquirerId);
208
+ const host = instanceWrapper.getInstanceByContextId(this.getContextId(contextId, instanceWrapper), inquirerId);
209
209
  host.instance = await host.instance;
210
210
  instanceWrapper.setInstanceByContextId(contextId, host, inquirerId);
211
211
  }
@@ -260,7 +260,7 @@ class Injector {
260
260
  instanceWrapperRef = providers.get(name);
261
261
  this.addDependencyMetadata(keyOrIndex, wrapper, instanceWrapperRef);
262
262
  const inquirerId = this.getInquirerId(inquirer);
263
- const instanceHost = instanceWrapperRef.getInstanceByContextId(contextId, inquirerId);
263
+ const instanceHost = instanceWrapperRef.getInstanceByContextId(this.getContextId(contextId, instanceWrapperRef), inquirerId);
264
264
  if (!instanceHost.isResolved && !instanceWrapperRef.forwardRef) {
265
265
  await this.loadProvider(instanceWrapperRef, relatedModule, contextId, wrapper);
266
266
  break;
@@ -291,7 +291,7 @@ class Injector {
291
291
  return undefined;
292
292
  }
293
293
  const inquirerId = this.getInquirerId(inquirer);
294
- const instanceHost = paramWrapper.getInstanceByContextId(contextId, inquirerId);
294
+ const instanceHost = paramWrapper.getInstanceByContextId(this.getContextId(contextId, paramWrapper), inquirerId);
295
295
  return instanceHost.instance;
296
296
  }
297
297
  catch (err) {
@@ -319,7 +319,7 @@ class Injector {
319
319
  async instantiateClass(instances, wrapper, targetMetatype, contextId = constants_2.STATIC_CONTEXT, inquirer) {
320
320
  const { metatype, inject } = wrapper;
321
321
  const inquirerId = this.getInquirerId(inquirer);
322
- const instanceHost = targetMetatype.getInstanceByContextId(contextId, inquirerId);
322
+ const instanceHost = targetMetatype.getInstanceByContextId(this.getContextId(contextId, targetMetatype), inquirerId);
323
323
  const isInContext = wrapper.isStatic(contextId, inquirer) ||
324
324
  wrapper.isInRequestScope(contextId, inquirer) ||
325
325
  wrapper.isLazyTransient(contextId, inquirer) ||
@@ -343,7 +343,7 @@ class Injector {
343
343
  }
344
344
  await this.loadInstance(wrapper, collection, moduleRef, ctx, wrapper);
345
345
  await this.loadEnhancersPerContext(wrapper, ctx, wrapper);
346
- const host = wrapper.getInstanceByContextId(ctx, wrapper.id);
346
+ const host = wrapper.getInstanceByContextId(this.getContextId(ctx, wrapper), wrapper.id);
347
347
  return host && host.instance;
348
348
  }
349
349
  async loadEnhancersPerContext(wrapper, ctx, inquirer) {
@@ -357,7 +357,7 @@ class Injector {
357
357
  async loadCtorMetadata(metadata, contextId, inquirer, parentInquirer) {
358
358
  const hosts = await Promise.all(metadata.map(async (item) => this.resolveScopedComponentHost(item, contextId, inquirer, parentInquirer)));
359
359
  const inquirerId = this.getInquirerId(inquirer);
360
- return hosts.map(item => item.getInstanceByContextId(contextId, inquirerId).instance);
360
+ return hosts.map(item => item.getInstanceByContextId(this.getContextId(contextId, item), inquirerId).instance);
361
361
  }
362
362
  async loadPropertiesMetadata(metadata, contextId, inquirer) {
363
363
  const dependenciesHosts = await Promise.all(metadata.map(async ({ wrapper: item, key }) => ({
@@ -368,7 +368,7 @@ class Injector {
368
368
  return dependenciesHosts.map(({ key, host }) => ({
369
369
  key,
370
370
  name: key,
371
- instance: host.getInstanceByContextId(contextId, inquirerId).instance,
371
+ instance: host.getInstanceByContextId(this.getContextId(contextId, host), inquirerId).instance,
372
372
  }));
373
373
  }
374
374
  getInquirerId(inquirer) {
@@ -428,5 +428,13 @@ class Injector {
428
428
  isDebugMode() {
429
429
  return !!process.env.NEST_DEBUG;
430
430
  }
431
+ getContextId(contextId, instanceWrapper) {
432
+ return contextId.getParent
433
+ ? contextId.getParent({
434
+ token: instanceWrapper.token,
435
+ isTreeDurable: instanceWrapper.isDependencyTreeDurable(),
436
+ })
437
+ : contextId;
438
+ }
431
439
  }
432
440
  exports.Injector = Injector;
@@ -3,8 +3,19 @@ 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 ChildContextIdInfo {
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: ChildContextIdInfo): ContextId;
8
19
  }
9
20
  export interface InstancePerContext<T> {
10
21
  instance: T;
@@ -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;
@@ -139,10 +139,6 @@ class NestApplication extends nest_application_context_1.NestApplicationContext
139
139
  await Promise.all(this.microservices.map(msvc => msvc.listen()));
140
140
  return this;
141
141
  }
142
- startAllMicroservicesAsync() {
143
- this.logger.warn('DEPRECATED! "startAllMicroservicesAsync" method is deprecated and will be removed in the next major release. Please, use "startAllMicroservices" instead.');
144
- return this.startAllMicroservices();
145
- }
146
142
  use(...args) {
147
143
  this.httpAdapter.use(...args);
148
144
  return this;
@@ -187,10 +183,6 @@ class NestApplication extends nest_application_context_1.NestApplicationContext
187
183
  });
188
184
  });
189
185
  }
190
- listenAsync(port, ...args) {
191
- this.logger.warn('DEPRECATED! "listenAsync" method is deprecated and will be removed in the next major release. Please, use "listen" instead.');
192
- return this.listen(port, ...args);
193
- }
194
186
  async getUrl() {
195
187
  return new Promise((resolve, reject) => {
196
188
  if (!this.isListening) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestjs/core",
3
- "version": "8.4.6",
3
+ "version": "9.0.0-next.1",
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.4.6"
39
+ "@nestjs/common": "^9.0.0-next.1"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@nestjs/common": "^8.0.0",
@@ -4,7 +4,6 @@ exports.RouterExplorer = void 0;
4
4
  const constants_1 = require("@nestjs/common/constants");
5
5
  const version_type_enum_1 = require("@nestjs/common/enums/version-type.enum");
6
6
  const exceptions_1 = require("@nestjs/common/exceptions");
7
- const version_options_interface_1 = require("@nestjs/common/interfaces/version-options.interface");
8
7
  const logger_service_1 = require("@nestjs/common/services/logger.service");
9
8
  const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
10
9
  const pathToRegexp = require("path-to-regexp");
@@ -160,107 +159,8 @@ class RouterExplorer {
160
159
  };
161
160
  }
162
161
  applyVersionFilter(router, routePathMetadata, handler) {
163
- const { versioningOptions } = routePathMetadata;
164
162
  const version = this.routePathFactory.getVersion(routePathMetadata);
165
- if (router === null || router === void 0 ? void 0 : router.applyVersionFilter) {
166
- return router.applyVersionFilter(handler, version, versioningOptions);
167
- }
168
- /**
169
- * TODO(v9): This was left for backward-compatibility and can be removed.
170
- */
171
- return (req, res, next) => {
172
- var _a, _b, _c, _d;
173
- if (version === version_options_interface_1.VERSION_NEUTRAL) {
174
- return handler(req, res, next);
175
- }
176
- // URL Versioning is done via the path, so the filter continues forward
177
- if (versioningOptions.type === version_type_enum_1.VersioningType.URI) {
178
- return handler(req, res, next);
179
- }
180
- // Custom Extractor Versioning Handler
181
- if (versioningOptions.type === version_type_enum_1.VersioningType.CUSTOM) {
182
- const extractedVersion = versioningOptions.extractor(req);
183
- if (Array.isArray(version)) {
184
- if (Array.isArray(extractedVersion) &&
185
- version.filter(extractedVersion.includes).length) {
186
- return handler(req, res, next);
187
- }
188
- else if ((0, shared_utils_1.isString)(extractedVersion) &&
189
- version.includes(extractedVersion)) {
190
- return handler(req, res, next);
191
- }
192
- }
193
- else {
194
- if (Array.isArray(extractedVersion) &&
195
- extractedVersion.includes(version)) {
196
- return handler(req, res, next);
197
- }
198
- else if ((0, shared_utils_1.isString)(extractedVersion) &&
199
- version === extractedVersion) {
200
- return handler(req, res, next);
201
- }
202
- }
203
- }
204
- // Media Type (Accept Header) Versioning Handler
205
- if (versioningOptions.type === version_type_enum_1.VersioningType.MEDIA_TYPE) {
206
- const MEDIA_TYPE_HEADER = 'Accept';
207
- const acceptHeaderValue = ((_a = req.headers) === null || _a === void 0 ? void 0 : _a[MEDIA_TYPE_HEADER]) ||
208
- ((_b = req.headers) === null || _b === void 0 ? void 0 : _b[MEDIA_TYPE_HEADER.toLowerCase()]);
209
- const acceptHeaderVersionParameter = acceptHeaderValue
210
- ? acceptHeaderValue.split(';')[1]
211
- : undefined;
212
- // No version was supplied
213
- if ((0, shared_utils_1.isUndefined)(acceptHeaderVersionParameter)) {
214
- if (Array.isArray(version)) {
215
- if (version.includes(version_options_interface_1.VERSION_NEUTRAL)) {
216
- return handler(req, res, next);
217
- }
218
- }
219
- }
220
- else {
221
- const headerVersion = acceptHeaderVersionParameter.split(versioningOptions.key)[1];
222
- if (Array.isArray(version)) {
223
- if (version.includes(headerVersion)) {
224
- return handler(req, res, next);
225
- }
226
- }
227
- else if ((0, shared_utils_1.isString)(version)) {
228
- if (version === headerVersion) {
229
- return handler(req, res, next);
230
- }
231
- }
232
- }
233
- }
234
- // Header Versioning Handler
235
- else if (versioningOptions.type === version_type_enum_1.VersioningType.HEADER) {
236
- const customHeaderVersionParameter = ((_c = req.headers) === null || _c === void 0 ? void 0 : _c[versioningOptions.header]) ||
237
- ((_d = req.headers) === null || _d === void 0 ? void 0 : _d[versioningOptions.header.toLowerCase()]);
238
- // No version was supplied
239
- if ((0, shared_utils_1.isUndefined)(customHeaderVersionParameter)) {
240
- if (Array.isArray(version)) {
241
- if (version.includes(version_options_interface_1.VERSION_NEUTRAL)) {
242
- return handler(req, res, next);
243
- }
244
- }
245
- }
246
- else {
247
- if (Array.isArray(version)) {
248
- if (version.includes(customHeaderVersionParameter)) {
249
- return handler(req, res, next);
250
- }
251
- }
252
- else if ((0, shared_utils_1.isString)(version)) {
253
- if (version === customHeaderVersionParameter) {
254
- return handler(req, res, next);
255
- }
256
- }
257
- }
258
- }
259
- if (!next) {
260
- throw new exceptions_1.InternalServerErrorException('HTTP adapter does not support filtering on version');
261
- }
262
- return next();
263
- };
163
+ return router.applyVersionFilter(handler, version, routePathMetadata.versioningOptions);
264
164
  }
265
165
  createCallbackProxy(instance, callback, methodName, moduleRef, requestMethod, contextId = constants_2.STATIC_CONTEXT, inquirerId) {
266
166
  const executionContext = this.executionContextCreator.create(instance, callback, methodName, moduleRef, requestMethod, contextId, inquirerId);
@@ -29,7 +29,7 @@ class RouterResponseController {
29
29
  return this.applicationRef.render(response, template, result);
30
30
  }
31
31
  async transformToResult(resultOrDeferred) {
32
- if (resultOrDeferred && (0, shared_utils_1.isFunction)(resultOrDeferred.subscribe)) {
32
+ if ((0, rxjs_1.isObservable)(resultOrDeferred)) {
33
33
  return (0, rxjs_1.lastValueFrom)(resultOrDeferred);
34
34
  }
35
35
  return resultOrDeferred;
@@ -80,8 +80,8 @@ class RouterResponseController {
80
80
  subscription.unsubscribe();
81
81
  });
82
82
  }
83
- assertObservable(result) {
84
- if (!(0, shared_utils_1.isFunction)(result.subscribe)) {
83
+ assertObservable(value) {
84
+ if (!(0, rxjs_1.isObservable)(value)) {
85
85
  throw new ReferenceError('You must return an Observable stream to use Server-Sent Events (SSE).');
86
86
  }
87
87
  }
package/scanner.d.ts CHANGED
@@ -11,7 +11,6 @@ export declare class DependenciesScanner {
11
11
  private readonly container;
12
12
  private readonly metadataScanner;
13
13
  private readonly applicationConfig;
14
- private readonly logger;
15
14
  private readonly applicationProvidersApplyMap;
16
15
  constructor(container: NestContainer, metadataScanner: MetadataScanner, applicationConfig?: ApplicationConfig);
17
16
  scan(module: Type<any>): Promise<void>;
@@ -33,7 +32,7 @@ export declare class DependenciesScanner {
33
32
  insertInjectable(injectable: Type<Injectable>, token: string, host: Type<Injectable>): void;
34
33
  insertExportedProvider(exportedProvider: Type<Injectable>, token: string): void;
35
34
  insertController(controller: Type<Controller>, token: string): void;
36
- reflectMetadata(metatype: Type<any>, metadataKey: string): any;
35
+ reflectMetadata(metadataKey: string, metatype: Type<any>): any;
37
36
  registerCoreModule(): Promise<void>;
38
37
  /**
39
38
  * Add either request or transient globally scoped enhancers
package/scanner.js CHANGED
@@ -20,7 +20,6 @@ class DependenciesScanner {
20
20
  this.container = container;
21
21
  this.metadataScanner = metadataScanner;
22
22
  this.applicationConfig = applicationConfig;
23
- this.logger = new common_1.Logger(DependenciesScanner.name);
24
23
  this.applicationProvidersApplyMap = [];
25
24
  }
26
25
  async scan(module) {
@@ -42,9 +41,9 @@ class DependenciesScanner {
42
41
  moduleDefinition = moduleDefinition.forwardRef();
43
42
  }
44
43
  const modules = !this.isDynamicModule(moduleDefinition)
45
- ? this.reflectMetadata(moduleDefinition, constants_1.MODULE_METADATA.IMPORTS)
44
+ ? this.reflectMetadata(constants_1.MODULE_METADATA.IMPORTS, moduleDefinition)
46
45
  : [
47
- ...this.reflectMetadata(moduleDefinition.module, constants_1.MODULE_METADATA.IMPORTS),
46
+ ...this.reflectMetadata(constants_1.MODULE_METADATA.IMPORTS, moduleDefinition.module),
48
47
  ...(moduleDefinition.imports || []),
49
48
  ];
50
49
  let registeredModuleRefs = [];
@@ -74,8 +73,7 @@ class DependenciesScanner {
74
73
  if (this.isInjectable(moduleToAdd) ||
75
74
  this.isController(moduleToAdd) ||
76
75
  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);
76
+ throw new invalid_class_module_exception_1.InvalidClassModuleException(moduleDefinition, scope);
79
77
  }
80
78
  return this.container.addModule(moduleToAdd, scope);
81
79
  }
@@ -89,7 +87,7 @@ class DependenciesScanner {
89
87
  }
90
88
  async reflectImports(module, token, context) {
91
89
  const modules = [
92
- ...this.reflectMetadata(module, constants_1.MODULE_METADATA.IMPORTS),
90
+ ...this.reflectMetadata(constants_1.MODULE_METADATA.IMPORTS, module),
93
91
  ...this.container.getDynamicMetadataByToken(token, constants_1.MODULE_METADATA.IMPORTS),
94
92
  ];
95
93
  for (const related of modules) {
@@ -98,7 +96,7 @@ class DependenciesScanner {
98
96
  }
99
97
  reflectProviders(module, token) {
100
98
  const providers = [
101
- ...this.reflectMetadata(module, constants_1.MODULE_METADATA.PROVIDERS),
99
+ ...this.reflectMetadata(constants_1.MODULE_METADATA.PROVIDERS, module),
102
100
  ...this.container.getDynamicMetadataByToken(token, constants_1.MODULE_METADATA.PROVIDERS),
103
101
  ];
104
102
  providers.forEach(provider => {
@@ -108,7 +106,7 @@ class DependenciesScanner {
108
106
  }
109
107
  reflectControllers(module, token) {
110
108
  const controllers = [
111
- ...this.reflectMetadata(module, constants_1.MODULE_METADATA.CONTROLLERS),
109
+ ...this.reflectMetadata(constants_1.MODULE_METADATA.CONTROLLERS, module),
112
110
  ...this.container.getDynamicMetadataByToken(token, constants_1.MODULE_METADATA.CONTROLLERS),
113
111
  ];
114
112
  controllers.forEach(item => {
@@ -128,13 +126,13 @@ class DependenciesScanner {
128
126
  }
129
127
  reflectExports(module, token) {
130
128
  const exports = [
131
- ...this.reflectMetadata(module, constants_1.MODULE_METADATA.EXPORTS),
129
+ ...this.reflectMetadata(constants_1.MODULE_METADATA.EXPORTS, module),
132
130
  ...this.container.getDynamicMetadataByToken(token, constants_1.MODULE_METADATA.EXPORTS),
133
131
  ];
134
132
  exports.forEach(exportedProvider => this.insertExportedProvider(exportedProvider, token));
135
133
  }
136
134
  reflectInjectables(component, token, metadataKey) {
137
- const controllerInjectables = this.reflectMetadata(component, metadataKey);
135
+ const controllerInjectables = this.reflectMetadata(metadataKey, component);
138
136
  const methodsInjectables = this.metadataScanner.scanFromPrototype(null, component.prototype, this.reflectKeyMetadata.bind(this, component, metadataKey));
139
137
  const flattenMethodsInjectables = this.flatten(methodsInjectables);
140
138
  const combinedInjectables = [
@@ -233,7 +231,7 @@ class DependenciesScanner {
233
231
  insertController(controller, token) {
234
232
  this.container.addController(controller, token);
235
233
  }
236
- reflectMetadata(metatype, metadataKey) {
234
+ reflectMetadata(metadataKey, metatype) {
237
235
  return Reflect.getMetadata(metadataKey, metatype) || [];
238
236
  }
239
237
  async registerCoreModule() {