@nestjs/core 5.3.14 → 5.4.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.
package/Readme.md CHANGED
@@ -14,7 +14,7 @@
14
14
  <a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/dm/@nestjs/core.svg" alt="NPM Downloads" /></a>
15
15
  <a href="https://travis-ci.org/nestjs/nest"><img src="https://api.travis-ci.org/nestjs/nest.svg?branch=master" alt="Travis" /></a>
16
16
  <a href="https://travis-ci.org/nestjs/nest"><img src="https://img.shields.io/travis/nestjs/nest/master.svg?label=linux" alt="Linux" /></a>
17
- <a href="https://coveralls.io/github/nestjs/nest?branch=master"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#7" alt="Coverage" /></a>
17
+ <a href="https://coveralls.io/github/nestjs/nest?branch=master"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#8" alt="Coverage" /></a>
18
18
  <a href="https://gitter.im/nestjs/nestjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge"><img src="https://badges.gitter.im/nestjs/nestjs.svg" alt="Gitter" /></a>
19
19
  <a href="https://opencollective.com/nest#backer"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
20
20
  <a href="https://opencollective.com/nest#sponsor"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
@@ -53,12 +53,12 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
53
53
  <a href="http://xtremis.com/"><img src="https://nestjs.com/img/logo-xtremis.svg" width="220" /></a>
54
54
 
55
55
  #### Silver Sponsors
56
-
57
- <a href="https://neoteric.eu/"><img src="https://nestjs.com/img/neoteric-cut.png" width="120" /></a> &nbsp; <a href="https://www.swingdev.io"><img src="https://nestjs.com/img/swingdev-logo.svg#1" width="150" /></a>
56
+ <a href="https://neoteric.eu/"><img src="https://nestjs.com/img/neoteric-cut.png" width="120" /></a> &nbsp;
57
+ <a href="http://gojob.com"><img src="http://nestjs.com/img/gojob-logo.png" valign="bottom" height="95" /></a> &nbsp; <a href="https://www.swingdev.io"><img src="https://nestjs.com/img/swingdev-logo.svg#1" width="150" /> </a>
58
58
 
59
59
  #### Sponsors
60
60
 
61
- <a href="https://scal.io"><img src="https://nestjs.com/img/scalio-logo.svg" width="110" /></a> &nbsp; <a href="http://angularity.io"><img src="http://angularity.io/media/logo.svg" height="30" /></a> &nbsp; <a href="http://gojob.com"><img src="https://gojob.com/w/wp-content/uploads/2017/02/cropped-Logo-web-home.png" height="40" /> &nbsp; <!--<a href="https://keycdn.com"><img src="https://nestjs.com/img/keycdn.svg" height="30" /></a> &nbsp;--> <a href="https://hostpresto.com"><img src="https://nestjs.com/img/hostpresto.png" height="30" /></a> &nbsp; <a href="https://genuinebee.com/"><img src="https://nestjs.com/img/genuinebee.svg" height="38" /></a> &nbsp; <a href="http://architectnow.net/"><img src="https://nestjs.com/img/architectnow.png" height="24" /></a> &nbsp; <a href="https://quander.io/"><img src="https://nestjs.com/img/quander.png" height="28" /></a>
61
+ <a href="https://scal.io"><img src="https://nestjs.com/img/scalio-logo.svg" width="110" /></a> &nbsp; <a href="http://angularity.io"><img src="http://angularity.io/media/logo.svg" height="30" /></a> &nbsp; <!--<a href="https://keycdn.com"><img src="https://nestjs.com/img/keycdn.svg" height="30" /></a> &nbsp;--> <a href="https://hostpresto.com"><img src="https://nestjs.com/img/hostpresto.png" height="30" /></a> &nbsp; <a href="https://genuinebee.com/"><img src="https://nestjs.com/img/genuinebee.svg" height="38" /></a> &nbsp; <a href="http://architectnow.net/"><img src="https://nestjs.com/img/architectnow.png" height="24" /></a> &nbsp; <a href="https://quander.io/"><img src="https://nestjs.com/img/quander.png" height="28" /></a>
62
62
 
63
63
 
64
64
  ## Backers
@@ -0,0 +1,4 @@
1
+ import { RuntimeException } from './runtime.exception';
2
+ export declare class InvalidClassException extends RuntimeException {
3
+ constructor(value: any);
4
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const messages_1 = require("../messages");
4
+ const runtime_exception_1 = require("./runtime.exception");
5
+ class InvalidClassException extends runtime_exception_1.RuntimeException {
6
+ constructor(value) {
7
+ super(messages_1.INVALID_CLASS_MESSAGE `${value}`);
8
+ }
9
+ }
10
+ exports.InvalidClassException = InvalidClassException;
@@ -1,5 +1,6 @@
1
1
  import { InjectorDependencyContext } from '../../injector/injector';
2
2
  import { RuntimeException } from './runtime.exception';
3
+ import { Module } from '../../injector/module';
3
4
  export declare class UndefinedDependencyException extends RuntimeException {
4
- constructor(type: string, undefinedDependencyContext: InjectorDependencyContext);
5
+ constructor(type: string, undefinedDependencyContext: InjectorDependencyContext, module?: Module);
5
6
  }
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const messages_1 = require("../messages");
4
4
  const runtime_exception_1 = require("./runtime.exception");
5
5
  class UndefinedDependencyException extends runtime_exception_1.RuntimeException {
6
- constructor(type, undefinedDependencyContext) {
7
- super(messages_1.UNKNOWN_DEPENDENCIES_MESSAGE(type, undefinedDependencyContext));
6
+ constructor(type, undefinedDependencyContext, module) {
7
+ super(messages_1.UNKNOWN_DEPENDENCIES_MESSAGE(type, undefinedDependencyContext, module));
8
8
  }
9
9
  }
10
10
  exports.UndefinedDependencyException = UndefinedDependencyException;
@@ -1,5 +1,6 @@
1
1
  import { InjectorDependencyContext } from '../../injector/injector';
2
2
  import { RuntimeException } from './runtime.exception';
3
+ import { Module } from '../../injector/module';
3
4
  export declare class UnknownDependenciesException extends RuntimeException {
4
- constructor(type: string, unknownDependencyContext: InjectorDependencyContext);
5
+ constructor(type: string, unknownDependencyContext: InjectorDependencyContext, module?: Module);
5
6
  }
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const messages_1 = require("../messages");
4
4
  const runtime_exception_1 = require("./runtime.exception");
5
5
  class UnknownDependenciesException extends runtime_exception_1.RuntimeException {
6
- constructor(type, unknownDependencyContext) {
7
- super(messages_1.UNKNOWN_DEPENDENCIES_MESSAGE(type, unknownDependencyContext));
6
+ constructor(type, unknownDependencyContext, module) {
7
+ super(messages_1.UNKNOWN_DEPENDENCIES_MESSAGE(type, unknownDependencyContext, module));
8
8
  }
9
9
  }
10
10
  exports.UnknownDependenciesException = UnknownDependenciesException;
@@ -1,8 +1,10 @@
1
1
  import { InjectorDependencyContext } from '../injector/injector';
2
- export declare const UNKNOWN_DEPENDENCIES_MESSAGE: (type: string, unknownDependencyContext: InjectorDependencyContext) => string;
2
+ import { Module } from '../injector/module';
3
+ export declare const UNKNOWN_DEPENDENCIES_MESSAGE: (type: string, unknownDependencyContext: InjectorDependencyContext, module: Module) => string;
3
4
  export declare const INVALID_MIDDLEWARE_MESSAGE: (text: any, name: string) => string;
4
5
  export declare const INVALID_MODULE_MESSAGE: (text: any, scope: string) => string;
5
6
  export declare const UNKNOWN_EXPORT_MESSAGE: (text: any, module: string) => string;
7
+ export declare const INVALID_CLASS_MESSAGE: (text: any, value: any) => string;
6
8
  export declare const INVALID_MIDDLEWARE_CONFIGURATION = "Invalid middleware configuration passed inside the module 'configure()' method.";
7
9
  export declare const UNKNOWN_REQUEST_MAPPING = "Request mapping properties not defined in the @RequestMapping() annotation!";
8
10
  export declare const UNHANDLED_RUNTIME_EXCEPTION = "Unhandled Runtime Exception.";
@@ -1,25 +1,43 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
4
+ // TODO: Replace `any` with `unknown` type when TS 3.0.0 is supported
5
+ /**
6
+ * Returns the name of an instance
7
+ * @param instance The instance which should get the name from
8
+ */
9
+ const getInstanceName = (instance) => (instance && instance.name);
3
10
  /**
4
11
  * Returns the name of the dependency
5
12
  * Tries to get the class name, otherwise the string value
6
13
  * (= injection token). As fallback it returns '+'
7
- * @param dependency The dependency whichs name shoul get displayed
14
+ * @param dependency The dependency whichs name should get displayed
15
+ */
16
+ const getDependencyName = (dependency) => getInstanceName(dependency) || dependency || '+';
17
+ /**
18
+ * Returns the name of the module
19
+ * Tries to get the class name. As fallback it returns 'current'.
20
+ * @param module The module which should get displayed
8
21
  */
9
- const getDependencyName = (dependency) => (dependency && dependency.name) || dependency || '+';
10
- exports.UNKNOWN_DEPENDENCIES_MESSAGE = (type, unknownDependencyContext) => {
11
- const { index, dependencies } = unknownDependencyContext;
22
+ const getModuleName = (module) => (module && getInstanceName(module.metatype)) || 'current';
23
+ exports.UNKNOWN_DEPENDENCIES_MESSAGE = (type, unknownDependencyContext, module) => {
24
+ const { index, dependencies, key } = unknownDependencyContext;
12
25
  let message = `Nest can't resolve dependencies of the ${type}`;
13
- message += ` (`;
14
- const dependenciesName = dependencies.map(getDependencyName);
26
+ if (shared_utils_1.isNil(index)) {
27
+ message += `. Please make sure that the "${key}" property is available in the current context.`;
28
+ return message;
29
+ }
30
+ const dependenciesName = (dependencies || []).map(getDependencyName);
15
31
  dependenciesName[index] = '?';
32
+ message += ` (`;
16
33
  message += dependenciesName.join(', ');
17
- message += `). Please make sure that the argument at index [${index}] is available in the current context.`;
34
+ message += `). Please make sure that the argument at index [${index}] is available in the ${getModuleName(module)} context.`;
18
35
  return message;
19
36
  };
20
37
  exports.INVALID_MIDDLEWARE_MESSAGE = (text, name) => `The middleware doesn't provide the 'resolve' method (${name})`;
21
38
  exports.INVALID_MODULE_MESSAGE = (text, scope) => `Nest cannot create the module instance. Often, this is because of a circular dependency between modules. Use forwardRef() to avoid it. (Read more https://docs.nestjs.com/advanced/circular-dependency.) Scope [${scope}]`;
22
39
  exports.UNKNOWN_EXPORT_MESSAGE = (text, module) => `Nest cannot export a component/module that is not a part of the currently processed module (${module}). Please verify whether each exported unit is available in this particular context.`;
40
+ exports.INVALID_CLASS_MESSAGE = (text, value) => `ModuleRef cannot instantiate class (${value} is not constructable).`;
23
41
  exports.INVALID_MIDDLEWARE_CONFIGURATION = `Invalid middleware configuration passed inside the module 'configure()' method.`;
24
42
  exports.UNKNOWN_REQUEST_MAPPING = `Request mapping properties not defined in the @RequestMapping() annotation!`;
25
43
  exports.UNHANDLED_RUNTIME_EXCEPTION = `Unhandled Runtime Exception.`;
@@ -1,8 +1,10 @@
1
1
  import { ArgumentsHost, ExceptionFilter, HttpServer } from '@nestjs/common';
2
+ import { ApplicationReferenceHost } from './../helpers/application-ref-host';
2
3
  export declare class BaseExceptionFilter<T = any> implements ExceptionFilter<T> {
3
4
  protected readonly applicationRef: HttpServer;
4
5
  private static readonly logger;
5
- constructor(applicationRef: HttpServer);
6
+ protected readonly applicationRefHost?: ApplicationReferenceHost;
7
+ constructor(applicationRef?: HttpServer);
6
8
  catch(exception: T, host: ArgumentsHost): void;
7
9
  isExceptionObject(err: any): err is Error;
8
10
  }
@@ -1,19 +1,31 @@
1
1
  "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  const common_1 = require("@nestjs/common");
4
13
  const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
5
14
  const constants_1 = require("../constants");
15
+ const application_ref_host_1 = require("./../helpers/application-ref-host");
6
16
  class BaseExceptionFilter {
7
17
  constructor(applicationRef) {
8
18
  this.applicationRef = applicationRef;
9
19
  }
10
20
  catch(exception, host) {
21
+ const applicationRef = this.applicationRef ||
22
+ (this.applicationRefHost && this.applicationRefHost.applicationRef);
11
23
  if (!(exception instanceof common_1.HttpException)) {
12
24
  const body = {
13
25
  statusCode: common_1.HttpStatus.INTERNAL_SERVER_ERROR,
14
26
  message: constants_1.MESSAGES.UNKNOWN_EXCEPTION_MESSAGE,
15
27
  };
16
- this.applicationRef.reply(host.getArgByIndex(1), body, body.statusCode);
28
+ applicationRef.reply(host.getArgByIndex(1), body, body.statusCode);
17
29
  if (this.isExceptionObject(exception)) {
18
30
  return BaseExceptionFilter.logger.error(exception.message, exception.stack);
19
31
  }
@@ -26,11 +38,16 @@ class BaseExceptionFilter {
26
38
  statusCode: exception.getStatus(),
27
39
  message: res,
28
40
  };
29
- this.applicationRef.reply(host.getArgByIndex(1), message, exception.getStatus());
41
+ applicationRef.reply(host.getArgByIndex(1), message, exception.getStatus());
30
42
  }
31
43
  isExceptionObject(err) {
32
44
  return shared_utils_1.isObject(err) && !!err.message;
33
45
  }
34
46
  }
35
47
  BaseExceptionFilter.logger = new common_1.Logger('ExceptionsHandler');
48
+ __decorate([
49
+ common_1.Optional(),
50
+ common_1.Inject(),
51
+ __metadata("design:type", application_ref_host_1.ApplicationReferenceHost)
52
+ ], BaseExceptionFilter.prototype, "applicationRefHost", void 0);
36
53
  exports.BaseExceptionFilter = BaseExceptionFilter;
@@ -1,10 +1,9 @@
1
- import { HttpException, HttpServer } from '@nestjs/common';
1
+ import { HttpException } from '@nestjs/common';
2
2
  import { ExceptionFilterMetadata } from '@nestjs/common/interfaces/exceptions/exception-filter-metadata.interface';
3
3
  import { ArgumentsHost } from '@nestjs/common/interfaces/features/arguments-host.interface';
4
4
  import { BaseExceptionFilter } from './base-exception-filter';
5
5
  export declare class ExceptionsHandler extends BaseExceptionFilter {
6
6
  private filters;
7
- constructor(applicationRef: HttpServer);
8
7
  next(exception: Error | HttpException | any, ctx: ArgumentsHost): void;
9
8
  setCustomFilters(filters: ExceptionFilterMetadata[]): void;
10
9
  invokeCustomFilters(exception: any, response: any): boolean;
@@ -4,8 +4,8 @@ const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
4
4
  const invalid_exception_filter_exception_1 = require("../errors/exceptions/invalid-exception-filter.exception");
5
5
  const base_exception_filter_1 = require("./base-exception-filter");
6
6
  class ExceptionsHandler extends base_exception_filter_1.BaseExceptionFilter {
7
- constructor(applicationRef) {
8
- super(applicationRef);
7
+ constructor() {
8
+ super(...arguments);
9
9
  this.filters = [];
10
10
  }
11
11
  next(exception, ctx) {
@@ -0,0 +1,11 @@
1
+ import { Type } from '@nestjs/common';
2
+ import { NestContainer } from './container';
3
+ import { Module } from './module';
4
+ export declare class ContainerScanner {
5
+ private readonly container;
6
+ private flatContainer;
7
+ constructor(container: NestContainer);
8
+ find<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | string | symbol): TResult;
9
+ findInstanceByPrototypeOrToken<TInput = any, TResult = TInput>(metatypeOrToken: Type<TInput> | string | symbol, contextModule: Partial<Module>): TResult;
10
+ private initFlatContainer();
11
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
4
+ const unknown_element_exception_1 = require("../errors/exceptions/unknown-element.exception");
5
+ class ContainerScanner {
6
+ constructor(container) {
7
+ this.container = container;
8
+ }
9
+ find(typeOrToken) {
10
+ this.initFlatContainer();
11
+ return this.findInstanceByPrototypeOrToken(typeOrToken, this.flatContainer);
12
+ }
13
+ findInstanceByPrototypeOrToken(metatypeOrToken, contextModule) {
14
+ const dependencies = new Map([
15
+ ...contextModule.components,
16
+ ...contextModule.routes,
17
+ ...contextModule.injectables,
18
+ ]);
19
+ const name = shared_utils_1.isFunction(metatypeOrToken)
20
+ ? metatypeOrToken.name
21
+ : metatypeOrToken;
22
+ const instanceWrapper = dependencies.get(name);
23
+ if (!instanceWrapper) {
24
+ throw new unknown_element_exception_1.UnknownElementException();
25
+ }
26
+ return instanceWrapper.instance;
27
+ }
28
+ initFlatContainer() {
29
+ if (this.flatContainer) {
30
+ return undefined;
31
+ }
32
+ const modules = this.container.getModules();
33
+ const initialValue = {
34
+ components: [],
35
+ routes: [],
36
+ injectables: [],
37
+ };
38
+ const merge = (initial, arr) => [...initial, ...arr];
39
+ this.flatContainer = [...modules.values()].reduce((current, next) => ({
40
+ components: merge(current.components, next.components),
41
+ routes: merge(current.routes, next.routes),
42
+ injectables: merge(current.injectables, next.injectables),
43
+ }), initialValue);
44
+ }
45
+ }
46
+ exports.ContainerScanner = ContainerScanner;
@@ -8,11 +8,24 @@ import { Module } from './module';
8
8
  * The type of an injectable dependency
9
9
  */
10
10
  export declare type InjectorDependency = Type<any> | Function | string;
11
+ /**
12
+ * The property-based dependency
13
+ */
14
+ export interface PropertyDependency {
15
+ key: string;
16
+ name: InjectorDependency;
17
+ isOptional?: boolean;
18
+ instance?: any;
19
+ }
11
20
  /**
12
21
  * Context of a dependency which gets injected by
13
22
  * the injector
14
23
  */
15
24
  export interface InjectorDependencyContext {
25
+ /**
26
+ * The name of the property key (property-based injection)
27
+ */
28
+ key?: string;
16
29
  /**
17
30
  * The name of the function or injection token
18
31
  */
@@ -21,11 +34,11 @@ export interface InjectorDependencyContext {
21
34
  * The index of the dependency which gets injected
22
35
  * from the dependencies array
23
36
  */
24
- index: number;
37
+ index?: number;
25
38
  /**
26
39
  * The dependency array which gets injected
27
40
  */
28
- dependencies: InjectorDependency[];
41
+ dependencies?: InjectorDependency[];
29
42
  }
30
43
  export declare class Injector {
31
44
  loadInstanceOfMiddleware(wrapper: MiddlewareWrapper, collection: Map<string, MiddlewareWrapper>, module: Module): Promise<void>;
@@ -34,7 +47,7 @@ export declare class Injector {
34
47
  loadPrototypeOfInstance<T>({metatype, name}: InstanceWrapper<T>, collection: Map<string, InstanceWrapper<T>>): any;
35
48
  loadInstanceOfComponent(wrapper: InstanceWrapper<Injectable>, module: Module): Promise<void>;
36
49
  applyDoneHook<T>(wrapper: InstanceWrapper<T>): () => void;
37
- loadInstance<T>(wrapper: InstanceWrapper<T>, collection: any, module: Module): Promise<void>;
50
+ loadInstance<T>(wrapper: InstanceWrapper<T>, collection: Map<string, InstanceWrapper<any>>, module: Module): Promise<void>;
38
51
  resolveConstructorParams<T>(wrapper: InstanceWrapper<T>, module: Module, inject: InjectorDependency[], callback: (args) => void): Promise<void>;
39
52
  reflectConstructorParams<T>(type: Type<T>): any[];
40
53
  reflectOptionalParams<T>(type: Type<T>): any[];
@@ -45,5 +58,8 @@ export declare class Injector {
45
58
  lookupComponent<T = any>(components: Map<string, any>, module: Module, dependencyContext: InjectorDependencyContext, wrapper: InstanceWrapper<T>): Promise<any>;
46
59
  lookupComponentInExports<T = any>(dependencyContext: InjectorDependencyContext, module: Module, wrapper: InstanceWrapper<T>): Promise<any>;
47
60
  lookupComponentInRelatedModules(module: Module, name: any, moduleRegistry?: any[]): any;
48
- instantiateClass(instances: any[], wrapper: InstanceWrapper<any>, targetMetatype: InstanceWrapper<any>, done: Function): Promise<void>;
61
+ resolveProperties<T>(wrapper: InstanceWrapper<T>, module: Module, inject?: InjectorDependency[]): Promise<PropertyDependency[]>;
62
+ reflectProperties<T>(type: Type<T>): PropertyDependency[];
63
+ applyProperties<T = any>(instance: T, properties: PropertyDependency[]): any;
64
+ instantiateClass<T = any>(instances: any[], wrapper: InstanceWrapper<any>, targetMetatype: InstanceWrapper<any>): Promise<T>;
49
65
  }
@@ -55,23 +55,29 @@ class Injector {
55
55
  }
56
56
  const done = this.applyDoneHook(wrapper);
57
57
  const { name, inject } = wrapper;
58
- const targetMetatype = collection.get(name);
59
- if (shared_utils_1.isUndefined(targetMetatype)) {
58
+ const targetWrapper = collection.get(name);
59
+ if (shared_utils_1.isUndefined(targetWrapper)) {
60
60
  throw new runtime_exception_1.RuntimeException();
61
61
  }
62
- if (targetMetatype.isResolved) {
62
+ if (targetWrapper.isResolved) {
63
63
  return;
64
64
  }
65
- await this.resolveConstructorParams(wrapper, module, inject, async (instances) => this.instantiateClass(instances, wrapper, targetMetatype, done));
65
+ const callback = async (instances) => {
66
+ const properties = await this.resolveProperties(wrapper, module, inject);
67
+ const instance = await this.instantiateClass(instances, wrapper, targetWrapper);
68
+ this.applyProperties(instance, properties);
69
+ done();
70
+ };
71
+ await this.resolveConstructorParams(wrapper, module, inject, callback);
66
72
  }
67
73
  async resolveConstructorParams(wrapper, module, inject, callback) {
68
- let isResolved = true;
69
74
  const dependencies = shared_utils_1.isNil(inject)
70
75
  ? this.reflectConstructorParams(wrapper.metatype)
71
76
  : inject;
72
77
  const optionalDependenciesIds = shared_utils_1.isNil(inject)
73
78
  ? this.reflectOptionalParams(wrapper.metatype)
74
79
  : [];
80
+ let isResolved = true;
75
81
  const instances = await Promise.all(dependencies.map(async (param, index) => {
76
82
  try {
77
83
  const paramWrapper = await this.resolveSingleParam(wrapper, param, { index, dependencies }, module);
@@ -104,7 +110,7 @@ class Injector {
104
110
  }
105
111
  async resolveSingleParam(wrapper, param, dependencyContext, module) {
106
112
  if (shared_utils_1.isUndefined(param)) {
107
- throw new undefined_dependency_exception_1.UndefinedDependencyException(wrapper.name, dependencyContext);
113
+ throw new undefined_dependency_exception_1.UndefinedDependencyException(wrapper.name, dependencyContext, module);
108
114
  }
109
115
  const token = this.resolveParamToken(wrapper, param);
110
116
  return this.resolveComponentInstance(module, shared_utils_1.isFunction(token) ? token.name : token, dependencyContext, wrapper);
@@ -118,7 +124,7 @@ class Injector {
118
124
  }
119
125
  async resolveComponentInstance(module, name, dependencyContext, wrapper) {
120
126
  const components = module.components;
121
- const instanceWrapper = await this.lookupComponent(components, module, Object.assign({ name }, dependencyContext), wrapper);
127
+ const instanceWrapper = await this.lookupComponent(components, module, Object.assign({}, dependencyContext, { name }), wrapper);
122
128
  if (!instanceWrapper.isResolved && !instanceWrapper.forwardRef) {
123
129
  await this.loadInstanceOfComponent(instanceWrapper, module);
124
130
  }
@@ -135,7 +141,7 @@ class Injector {
135
141
  async lookupComponentInExports(dependencyContext, module, wrapper) {
136
142
  const instanceWrapper = await this.lookupComponentInRelatedModules(module, dependencyContext.name);
137
143
  if (shared_utils_1.isNil(instanceWrapper)) {
138
- throw new unknown_dependencies_exception_1.UnknownDependenciesException(wrapper.name, dependencyContext);
144
+ throw new unknown_dependencies_exception_1.UnknownDependenciesException(wrapper.name, dependencyContext, module);
139
145
  }
140
146
  return instanceWrapper;
141
147
  }
@@ -164,17 +170,55 @@ class Injector {
164
170
  }
165
171
  return componentRef;
166
172
  }
167
- async instantiateClass(instances, wrapper, targetMetatype, done) {
173
+ async resolveProperties(wrapper, module, inject) {
174
+ if (!shared_utils_1.isNil(inject)) {
175
+ return [];
176
+ }
177
+ const properties = this.reflectProperties(wrapper.metatype);
178
+ const instances = await Promise.all(properties.map(async (item) => {
179
+ try {
180
+ const dependencyContext = {
181
+ key: item.key,
182
+ name: item.name,
183
+ };
184
+ const paramWrapper = await this.resolveSingleParam(wrapper, item.name, dependencyContext, module);
185
+ return (paramWrapper && paramWrapper.instance) || undefined;
186
+ }
187
+ catch (err) {
188
+ if (!item.isOptional) {
189
+ throw err;
190
+ }
191
+ return undefined;
192
+ }
193
+ }));
194
+ return properties.map((item, index) => (Object.assign({}, item, { instance: instances[index] })));
195
+ }
196
+ reflectProperties(type) {
197
+ const properties = Reflect.getMetadata(constants_1.PROPERTY_DEPS_METADATA, type) || [];
198
+ const optionalKeys = Reflect.getMetadata(constants_1.OPTIONAL_PROPERTY_DEPS_METADATA, type) || [];
199
+ return properties.map(item => (Object.assign({}, item, { name: item.type, isOptional: optionalKeys.includes(item.key) })));
200
+ }
201
+ applyProperties(instance, properties) {
202
+ if (!shared_utils_1.isObject(instance)) {
203
+ return undefined;
204
+ }
205
+ properties
206
+ .filter(item => !shared_utils_1.isNil(item.instance))
207
+ .forEach(item => (instance[item.key] = item.instance));
208
+ }
209
+ async instantiateClass(instances, wrapper, targetMetatype) {
168
210
  const { metatype, inject } = wrapper;
169
211
  if (shared_utils_1.isNil(inject)) {
170
- targetMetatype.instance = Object.assign(targetMetatype.instance, new metatype(...instances));
212
+ targetMetatype.instance = wrapper.forwardRef
213
+ ? Object.assign(targetMetatype.instance, new metatype(...instances))
214
+ : new metatype(...instances);
171
215
  }
172
216
  else {
173
217
  const factoryResult = targetMetatype.metatype(...instances);
174
218
  targetMetatype.instance = await factoryResult;
175
219
  }
176
220
  targetMetatype.isResolved = true;
177
- done();
221
+ return targetMetatype.instance;
178
222
  }
179
223
  }
180
224
  exports.Injector = Injector;
@@ -3,12 +3,14 @@ import { NestContainer } from './container';
3
3
  import { Module } from './module';
4
4
  export declare abstract class ModuleRef {
5
5
  protected readonly container: NestContainer;
6
- private flattenModuleFixture;
6
+ private readonly injector;
7
+ private readonly containerScanner;
7
8
  constructor(container: NestContainer);
8
9
  abstract get<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | string | symbol, options?: {
9
10
  strict: boolean;
10
11
  }): TResult;
12
+ abstract create<T = any>(type: Type<T>): Promise<T>;
11
13
  protected find<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | string | symbol): TResult;
14
+ protected instantiateClass<T = any>(type: Type<T>, module: Module): Promise<T>;
12
15
  protected findInstanceByPrototypeOrToken<TInput = any, TResult = TInput>(metatypeOrToken: Type<TInput> | string | symbol, contextModule: Partial<Module>): TResult;
13
- private initFlattenModule();
14
16
  }
@@ -1,45 +1,40 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
4
- const unknown_element_exception_1 = require("../errors/exceptions/unknown-element.exception");
3
+ const container_scanner_1 = require("./container-scanner");
4
+ const injector_1 = require("./injector");
5
5
  class ModuleRef {
6
6
  constructor(container) {
7
7
  this.container = container;
8
+ this.injector = new injector_1.Injector();
9
+ this.containerScanner = new container_scanner_1.ContainerScanner(container);
8
10
  }
9
11
  find(typeOrToken) {
10
- this.initFlattenModule();
11
- return this.findInstanceByPrototypeOrToken(typeOrToken, this.flattenModuleFixture);
12
+ return this.containerScanner.find(typeOrToken);
12
13
  }
13
- findInstanceByPrototypeOrToken(metatypeOrToken, contextModule) {
14
- const dependencies = new Map([
15
- ...contextModule.components,
16
- ...contextModule.routes,
17
- ...contextModule.injectables,
18
- ]);
19
- const name = shared_utils_1.isFunction(metatypeOrToken)
20
- ? metatypeOrToken.name
21
- : metatypeOrToken;
22
- const instanceWrapper = dependencies.get(name);
23
- if (!instanceWrapper) {
24
- throw new unknown_element_exception_1.UnknownElementException();
25
- }
26
- return instanceWrapper.instance;
27
- }
28
- initFlattenModule() {
29
- if (this.flattenModuleFixture) {
30
- return;
31
- }
32
- const modules = this.container.getModules();
33
- const initialValue = {
34
- components: [],
35
- routes: [],
36
- injectables: [],
14
+ async instantiateClass(type, module) {
15
+ const wrapper = {
16
+ name: type.name,
17
+ metatype: type,
18
+ instance: undefined,
19
+ isResolved: false,
37
20
  };
38
- this.flattenModuleFixture = [...modules.values()].reduce((flatten, curr) => ({
39
- components: [...flatten.components, ...curr.components],
40
- routes: [...flatten.routes, ...curr.routes],
41
- injectables: [...flatten.injectables, ...curr.injectables],
42
- }), initialValue);
21
+ return new Promise(async (resolve, reject) => {
22
+ try {
23
+ const callback = async (instances) => {
24
+ const properties = await this.injector.resolveProperties(wrapper, module);
25
+ const instance = new type(...instances);
26
+ this.injector.applyProperties(instance, properties);
27
+ resolve(instance);
28
+ };
29
+ await this.injector.resolveConstructorParams(wrapper, module, undefined, callback);
30
+ }
31
+ catch (err) {
32
+ reject(err);
33
+ }
34
+ });
35
+ }
36
+ findInstanceByPrototypeOrToken(metatypeOrToken, contextModule) {
37
+ return this.containerScanner.findInstanceByPrototypeOrToken(metatypeOrToken, contextModule);
43
38
  }
44
39
  }
45
40
  exports.ModuleRef = ModuleRef;
@@ -38,7 +38,7 @@ export declare class Module {
38
38
  readonly components: Map<string, InstanceWrapper<Injectable>>;
39
39
  readonly injectables: Map<string, InstanceWrapper<Injectable>>;
40
40
  readonly routes: Map<string, InstanceWrapper<Controller>>;
41
- readonly exports: Set<string>;
41
+ readonly exports: Set<string | symbol>;
42
42
  readonly instance: NestModule;
43
43
  readonly metatype: Type<any>;
44
44
  addCoreInjectables(container: NestContainer): void;
@@ -60,9 +60,9 @@ export declare class Module {
60
60
  addCustomClass(component: CustomClass, collection: Map<string, any>): void;
61
61
  addCustomValue(component: CustomValue, collection: Map<string, any>): void;
62
62
  addCustomFactory(component: CustomFactory, collection: Map<string, any>): void;
63
- addExportedComponent(exportedComponent: ComponentMetatype | string | DynamicModule): Set<string>;
64
- addCustomExportedComponent(exportedComponent: CustomFactory | CustomValue | CustomClass): Set<string>;
65
- validateExportedProvider(token: string): string;
63
+ addExportedComponent(exportedComponent: ComponentMetatype | string | symbol | DynamicModule): Set<string | symbol>;
64
+ addCustomExportedComponent(exportedComponent: CustomFactory | CustomValue | CustomClass): Set<string | symbol>;
65
+ validateExportedProvider(token: string | symbol): string | symbol;
66
66
  addRoute(route: Type<Controller>): void;
67
67
  addRelatedModule(relatedModule: any): void;
68
68
  replace(toReplace: any, options: any): string;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const random_string_generator_util_1 = require("@nestjs/common/utils/random-string-generator.util");
4
4
  const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
5
+ const invalid_class_exception_1 = require("../errors/exceptions/invalid-class.exception");
5
6
  const runtime_exception_1 = require("../errors/exceptions/runtime.exception");
6
7
  const unknown_export_exception_1 = require("../errors/exceptions/unknown-export.exception");
7
8
  const application_ref_host_1 = require("../helpers/application-ref-host");
@@ -206,7 +207,7 @@ class Module {
206
207
  if (this.isCustomProvider(exportedComponent)) {
207
208
  return this.addCustomExportedComponent(exportedComponent);
208
209
  }
209
- else if (shared_utils_1.isString(exportedComponent)) {
210
+ else if (shared_utils_1.isString(exportedComponent) || shared_utils_1.isSymbol(exportedComponent)) {
210
211
  return addExportedUnit(exportedComponent);
211
212
  }
212
213
  else if (this.isDynamicModule(exportedComponent)) {
@@ -267,6 +268,12 @@ class Module {
267
268
  }
268
269
  return this.findInstanceByPrototypeOrToken(typeOrToken, self);
269
270
  }
271
+ async create(type) {
272
+ if (!(type && shared_utils_1.isFunction(type) && type.prototype)) {
273
+ throw new invalid_class_exception_1.InvalidClassException(type);
274
+ }
275
+ return this.instantiateClass(type, self);
276
+ }
270
277
  };
271
278
  }
272
279
  }
@@ -2,11 +2,12 @@ import { INestApplicationContext, LoggerService, OnApplicationBootstrap, OnModul
2
2
  import { Type } from '@nestjs/common/interfaces/type.interface';
3
3
  import { NestContainer } from './injector/container';
4
4
  import { Module } from './injector/module';
5
- import { ModuleRef } from './injector/module-ref';
6
- export declare class NestApplicationContext extends ModuleRef implements INestApplicationContext {
5
+ export declare class NestApplicationContext implements INestApplicationContext {
6
+ protected readonly container: NestContainer;
7
7
  private readonly scope;
8
- protected contextModule: Module;
8
+ private contextModule;
9
9
  private readonly moduleTokenFactory;
10
+ private readonly containerScanner;
10
11
  constructor(container: NestContainer, scope: Type<any>[], contextModule: Module);
11
12
  selectContextModule(): void;
12
13
  select<T>(module: Type<T>): INestApplicationContext;
@@ -25,4 +26,6 @@ export declare class NestApplicationContext extends ModuleRef implements INestAp
25
26
  protected callBootstrapHook(): Promise<any>;
26
27
  protected callModuleBootstrapHook(module: Module): Promise<any>;
27
28
  protected hasOnAppBotstrapHook(instance: any): instance is OnApplicationBootstrap;
29
+ protected find<TInput = any, TResult = TInput>(typeOrToken: Type<TInput> | string | symbol): TResult;
30
+ protected findInstanceByPrototypeOrToken<TInput = any, TResult = TInput>(metatypeOrToken: Type<TInput> | string | symbol, contextModule: Partial<Module>): TResult;
28
31
  }
@@ -4,14 +4,15 @@ const common_1 = require("@nestjs/common");
4
4
  const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
5
5
  const iterare_1 = require("iterare");
6
6
  const unknown_module_exception_1 = require("./errors/exceptions/unknown-module.exception");
7
- const module_ref_1 = require("./injector/module-ref");
7
+ const container_scanner_1 = require("./injector/container-scanner");
8
8
  const module_token_factory_1 = require("./injector/module-token-factory");
9
- class NestApplicationContext extends module_ref_1.ModuleRef {
9
+ class NestApplicationContext {
10
10
  constructor(container, scope, contextModule) {
11
- super(container);
11
+ this.container = container;
12
12
  this.scope = scope;
13
13
  this.contextModule = contextModule;
14
14
  this.moduleTokenFactory = new module_token_factory_1.ModuleTokenFactory();
15
+ this.containerScanner = new container_scanner_1.ContainerScanner(container);
15
16
  }
16
17
  selectContextModule() {
17
18
  const modules = this.container.getModules().values();
@@ -116,5 +117,11 @@ class NestApplicationContext extends module_ref_1.ModuleRef {
116
117
  hasOnAppBotstrapHook(instance) {
117
118
  return !shared_utils_1.isUndefined(instance.onApplicationBootstrap);
118
119
  }
120
+ find(typeOrToken) {
121
+ return this.containerScanner.find(typeOrToken);
122
+ }
123
+ findInstanceByPrototypeOrToken(metatypeOrToken, contextModule) {
124
+ return this.containerScanner.findInstanceByPrototypeOrToken(metatypeOrToken, contextModule);
125
+ }
119
126
  }
120
127
  exports.NestApplicationContext = NestApplicationContext;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestjs/core",
3
- "version": "5.3.14",
3
+ "version": "5.4.1",
4
4
  "description": "Nest - modern, fast, powerful node.js web framework (@core)",
5
5
  "author": "Kamil Mysliwiec",
6
6
  "license": "MIT",