feature(@nestjs/core) expose container to ModuleRef, add close() to NestContext

This commit is contained in:
Kamil Myśliwiec
2018-07-24 22:07:14 +02:00
parent e39c9d920d
commit 1527e12013
22 changed files with 247 additions and 320 deletions

View File

@@ -137,6 +137,7 @@
"packages/microservices/exceptions/",
"packages/microservices/microservices-module.ts",
"packages/core/middleware/middleware-module.ts",
"packages/core/injector/module-ref.ts",
"packages/common/services/logger.service.ts"
],
"extension": [

View File

@@ -1,5 +1,4 @@
import { Type } from './type.interface';
import { LoggerService } from '../services/logger.service';
export interface INestApplicationContext {
/**
@@ -10,10 +9,17 @@ export interface INestApplicationContext {
/**
* Retrieves an instance of either injectable or controller available anywhere, otherwise, throws exception.
* @returns {T}
* @returns {TResult}
*/
get<T>(
typeOrToken: Type<T> | string | symbol,
get<TInput = any, TResult = TInput>(
typeOrToken: Type<TInput> | string | symbol,
options?: { strict: boolean },
): T;
): TResult;
/**
* Terminates the application
*
* @returns {Promise<void>}
*/
close(): Promise<void>;
}

View File

@@ -1,11 +1,11 @@
import { FILTER_CATCH_EXCEPTIONS } from '@nestjs/common/constants';
import { Type } from '@nestjs/common/interfaces';
import { ExceptionFilter } from '@nestjs/common/interfaces/exceptions/exception-filter.interface';
import { Type } from '@nestjs/common/interfaces/index';
import { isEmpty, isFunction, isUndefined } from '@nestjs/common/utils/shared.utils';
import iterate from 'iterare';
import 'reflect-metadata';
import { ContextCreator } from '../helpers/context-creator';
import { NestContainer } from '../injector/container';
import { ContextCreator } from './../helpers/context-creator';
export class BaseExceptionFilterContext extends ContextCreator {
protected moduleContext: string;

View File

@@ -1,17 +1,12 @@
import 'reflect-metadata';
import iterate from 'iterare';
import { Controller } from '@nestjs/common/interfaces';
import { GUARDS_METADATA } from '@nestjs/common/constants';
import {
isUndefined,
isFunction,
isNil,
isEmpty,
} from '@nestjs/common/utils/shared.utils';
import { ContextCreator } from './../helpers/context-creator';
import { NestContainer } from '../injector/container';
import { CanActivate } from '@nestjs/common';
import { GUARDS_METADATA } from '@nestjs/common/constants';
import { Controller } from '@nestjs/common/interfaces';
import { ConfigurationProvider } from '@nestjs/common/interfaces/configuration-provider.interface';
import { isEmpty, isFunction, isUndefined } from '@nestjs/common/utils/shared.utils';
import iterate from 'iterare';
import 'reflect-metadata';
import { ContextCreator } from '../helpers/context-creator';
import { NestContainer } from '../injector/container';
export class GuardsContextCreator extends ContextCreator {
private moduleContext: string;

View File

@@ -1,8 +1,5 @@
import 'reflect-metadata';
import iterate from 'iterare';
import { Controller } from '@nestjs/common/interfaces';
import { isUndefined, isFunction } from '@nestjs/common/utils/shared.utils';
import { ApplicationConfig } from './../application-config';
import 'reflect-metadata';
export abstract class ContextCreator {
public abstract createConcreteContext<T extends any[], R extends any[]>(

View File

@@ -1,13 +1,13 @@
import 'reflect-metadata';
import { GuardsContextCreator } from './../guards/guards-context-creator';
import { GuardsConsumer } from './../guards/guards-consumer';
import { InterceptorsContextCreator } from './../interceptors/interceptors-context-creator';
import { InterceptorsConsumer } from './../interceptors/interceptors-consumer';
import { Controller } from '@nestjs/common/interfaces';
import { FORBIDDEN_MESSAGE } from '../guards/constants';
import { ForbiddenException } from '@nestjs/common';
import { Module } from './../injector/module';
import { ModulesContainer } from './../injector/modules-container';
import { Controller } from '@nestjs/common/interfaces';
import 'reflect-metadata';
import { FORBIDDEN_MESSAGE } from '../guards/constants';
import { GuardsConsumer } from '../guards/guards-consumer';
import { GuardsContextCreator } from '../guards/guards-context-creator';
import { Module } from '../injector/module';
import { ModulesContainer } from '../injector/modules-container';
import { InterceptorsConsumer } from '../interceptors/interceptors-consumer';
import { InterceptorsContextCreator } from '../interceptors/interceptors-context-creator';
export class ExternalContextCreator {
constructor(

View File

@@ -2,9 +2,9 @@ import { DynamicModule } from '@nestjs/common';
import { GLOBAL_MODULE_METADATA } from '@nestjs/common/constants';
import { Type } from '@nestjs/common/interfaces/type.interface';
import 'reflect-metadata';
import { ApplicationConfig } from '../application-config';
import { InvalidModuleException } from '../errors/exceptions/invalid-module.exception';
import { UnknownModuleException } from '../errors/exceptions/unknown-module.exception';
import { ApplicationConfig } from './../application-config';
import { InvalidModuleException } from './../errors/exceptions/invalid-module.exception';
import { ModuleCompiler } from './compiler';
import { Module } from './module';
import { ModulesContainer } from './modules-container';

View File

@@ -5,9 +5,9 @@ import { Type } from '@nestjs/common/interfaces/type.interface';
import { isFunction, isNil, isUndefined } from '@nestjs/common/utils/shared.utils';
import 'reflect-metadata';
import { RuntimeException } from '../errors/exceptions/runtime.exception';
import { UndefinedDependencyException } from '../errors/exceptions/undefined-dependency.exception';
import { UnknownDependenciesException } from '../errors/exceptions/unknown-dependencies.exception';
import { MiddlewareWrapper } from '../middleware/container';
import { UndefinedDependencyException } from './../errors/exceptions/undefined-dependency.exception';
import { InstanceWrapper } from './container';
import { Module } from './module';

View File

@@ -1,5 +1,65 @@
import { OpaqueToken } from './module';
import { Type } from '@nestjs/common';
import { isFunction } from '@nestjs/common/utils/shared.utils';
import { UnknownElementException } from '../errors/exceptions/unknown-element.exception';
import { InstanceWrapper, NestContainer } from './container';
import { Module } from './module';
export abstract class ModuleRef {
public abstract get<T>(type: OpaqueToken): T;
private flattenModuleFixture: Partial<Module>;
constructor(protected readonly container: NestContainer) {}
public abstract get<TInput = any, TResult = TInput>(
typeOrToken: Type<TInput> | string | symbol,
options?: { strict: boolean },
): TResult;
protected find<TInput = any, TResult = TInput>(
typeOrToken: Type<TInput> | string | symbol,
): TResult {
this.initFlattenModule();
return this.findInstanceByPrototypeOrToken<TInput, TResult>(
typeOrToken,
this.flattenModuleFixture,
);
}
protected findInstanceByPrototypeOrToken<TInput = any, TResult = TInput>(
metatypeOrToken: Type<TInput> | string | symbol,
contextModule: Partial<Module>,
): TResult {
const dependencies = new Map([
...contextModule.components,
...contextModule.routes,
...contextModule.injectables,
]);
const name = isFunction(metatypeOrToken)
? (metatypeOrToken as any).name
: metatypeOrToken;
const instanceWrapper = dependencies.get(name);
if (!instanceWrapper) {
throw new UnknownElementException();
}
return (instanceWrapper as InstanceWrapper<any>).instance;
}
private initFlattenModule() {
if (this.flattenModuleFixture) {
return void 0;
}
const modules = this.container.getModules();
const initialValue = {
components: [],
routes: [],
injectables: [],
};
this.flattenModuleFixture = [...modules.values()].reduce(
(flatten, curr) => ({
components: [...flatten.components, ...curr.components],
routes: [...flatten.routes, ...curr.routes],
injectables: [...flatten.injectables, ...curr.injectables],
}),
initialValue,
) as any;
}
}

View File

@@ -3,12 +3,12 @@ import { Type } from '@nestjs/common/interfaces/type.interface';
import { isFunction, isNil, isString, isSymbol, isUndefined } from '@nestjs/common/utils/shared.utils';
import { RuntimeException } from '../errors/exceptions/runtime.exception';
import { UnknownExportException } from '../errors/exceptions/unknown-export.exception';
import { GuardsConsumer } from '../guards/guards-consumer';
import { GuardsContextCreator } from '../guards/guards-context-creator';
import { ExternalContextCreator } from '../helpers/external-context-creator';
import { InterceptorsConsumer } from '../interceptors/interceptors-consumer';
import { InterceptorsContextCreator } from '../interceptors/interceptors-context-creator';
import { Reflector } from '../services/reflector.service';
import { GuardsConsumer } from './../guards/guards-consumer';
import { GuardsContextCreator } from './../guards/guards-context-creator';
import { ExternalContextCreator } from './../helpers/external-context-creator';
import { InterceptorsConsumer } from './../interceptors/interceptors-consumer';
import { InterceptorsContextCreator } from './../interceptors/interceptors-context-creator';
import { InstanceWrapper, NestContainer } from './container';
import { ModuleRef } from './module-ref';
import { ModulesContainer } from './modules-container';
@@ -41,7 +41,7 @@ export class Module {
constructor(
private readonly _metatype: Type<any>,
private readonly _scope: Type<any>[],
container: NestContainer,
private readonly container: NestContainer,
) {
this.addCoreInjectables(container);
}
@@ -92,7 +92,7 @@ export class Module {
}
public addModuleRef() {
const moduleRef = this.createModuleRefMetatype(this._components);
const moduleRef = this.createModuleRefMetatype();
this._components.set(ModuleRef.name, {
name: ModuleRef.name,
metatype: ModuleRef as any,
@@ -324,15 +324,24 @@ export class Module {
});
}
public createModuleRefMetatype(components) {
return class {
public readonly components = components;
public createModuleRefMetatype(): any {
const self = this;
return class extends ModuleRef {
constructor() {
super(self.container);
}
public get<T>(type: OpaqueToken): T {
const name = isFunction(type) ? (type as Type<any>).name : type;
const exists = this.components.has(name);
return exists ? (this.components.get(name).instance as T) : null;
public get<TInput = any, TResult = TInput>(
typeOrToken: Type<TInput> | string | symbol,
options: { strict: boolean } = { strict: true },
): TResult {
if (!(options && options.strict)) {
return this.find<TInput, TResult>(typeOrToken);
}
return this.findInstanceByPrototypeOrToken<TInput, TResult>(
typeOrToken,
self,
);
}
};
}

View File

@@ -1,16 +1,11 @@
import 'reflect-metadata';
import iterate from 'iterare';
import { Controller, NestInterceptor } from '@nestjs/common/interfaces';
import { INTERCEPTORS_METADATA } from '@nestjs/common/constants';
import {
isUndefined,
isFunction,
isNil,
isEmpty,
} from '@nestjs/common/utils/shared.utils';
import { ContextCreator } from './../helpers/context-creator';
import { NestContainer } from '../injector/container';
import { Controller, NestInterceptor } from '@nestjs/common/interfaces';
import { ConfigurationProvider } from '@nestjs/common/interfaces/configuration-provider.interface';
import { isEmpty, isFunction, isUndefined } from '@nestjs/common/utils/shared.utils';
import iterate from 'iterare';
import 'reflect-metadata';
import { ContextCreator } from '../helpers/context-creator';
import { NestContainer } from '../injector/container';
export class InterceptorsContextCreator extends ContextCreator {
private moduleContext: string;

View File

@@ -1,26 +1,28 @@
import { INestApplicationContext, OnModuleInit } from '@nestjs/common';
import { Type } from '@nestjs/common/interfaces/type.interface';
import {
isFunction,
isNil,
isUndefined,
} from '@nestjs/common/utils/shared.utils';
INestApplicationContext,
OnModuleDestroy,
OnModuleInit,
} from '@nestjs/common';
import { Type } from '@nestjs/common/interfaces/type.interface';
import { isNil, isUndefined } from '@nestjs/common/utils/shared.utils';
import iterate from 'iterare';
import { UnknownElementException } from './errors/exceptions/unknown-element.exception';
import { UnknownModuleException } from './errors/exceptions/unknown-module.exception';
import { InstanceWrapper, NestContainer } from './injector/container';
import { NestContainer } from './injector/container';
import { Module } from './injector/module';
import { ModuleRef } from './injector/module-ref';
import { ModuleTokenFactory } from './injector/module-token-factory';
export class NestApplicationContext implements INestApplicationContext {
export class NestApplicationContext extends ModuleRef
implements INestApplicationContext {
private readonly moduleTokenFactory = new ModuleTokenFactory();
private contextModuleFixture: Partial<Module>;
constructor(
protected readonly container: NestContainer,
container: NestContainer,
private readonly scope: Type<any>[],
protected contextModule: Module,
) {}
) {
super(container);
}
public selectContextModule() {
const modules = this.container.getModules().values();
@@ -53,21 +55,15 @@ export class NestApplicationContext implements INestApplicationContext {
);
}
public find<TInput = any, TResult = TInput>(
typeOrToken: Type<TInput> | string | symbol,
): TResult {
this.initFlattenModule();
return this.findInstanceByPrototypeOrToken<TInput, TResult>(
typeOrToken,
this.contextModuleFixture,
);
}
public async init(): Promise<this> {
await this.callInitHook();
return this;
}
public async close(): Promise<void> {
await this.callDestroyHook();
}
protected async callInitHook(): Promise<any> {
const modules = this.container.getModules();
await Promise.all(
@@ -92,42 +88,30 @@ export class NestApplicationContext implements INestApplicationContext {
return !isUndefined((instance as OnModuleInit).onModuleInit);
}
private findInstanceByPrototypeOrToken<TInput = any, TResult = TInput>(
metatypeOrToken: Type<TInput> | string | symbol,
contextModule,
): TResult {
const dependencies = new Map([
...contextModule.components,
...contextModule.routes,
...contextModule.injectables,
]);
const name = isFunction(metatypeOrToken)
? (metatypeOrToken as any).name
: metatypeOrToken;
const instanceWrapper = dependencies.get(name);
if (!instanceWrapper) {
throw new UnknownElementException();
}
return (instanceWrapper as InstanceWrapper<any>).instance;
protected async callDestroyHook(): Promise<any> {
const modules = this.container.getModules();
await Promise.all(
iterate(modules.values()).map(
async module => await this.callModuleDestroyHook(module),
),
);
}
private initFlattenModule() {
if (this.contextModuleFixture) {
return undefined;
}
const modules = this.container.getModules();
const initialValue = {
components: [],
routes: [],
injectables: [],
};
this.contextModuleFixture = [...modules.values()].reduce(
(flatten, curr) => ({
components: [...flatten.components, ...curr.components],
routes: [...flatten.routes, ...curr.routes],
injectables: [...flatten.injectables, ...curr.injectables],
}),
initialValue,
) as any;
protected async callModuleDestroyHook(module: Module): Promise<any> {
const components = [...module.routes, ...module.components];
await Promise.all(
iterate(components)
.map(([key, { instance }]) => instance)
.filter(instance => !isNil(instance))
.filter(this.hasOnModuleDestroyHook)
.map(
async instance =>
await (instance as OnModuleDestroy).onModuleDestroy(),
),
);
}
protected hasOnModuleDestroyHook(instance): instance is OnModuleDestroy {
return !isUndefined((instance as OnModuleDestroy).onModuleDestroy);
}
}

View File

@@ -4,7 +4,6 @@ import {
INestApplication,
INestMicroservice,
NestInterceptor,
OnModuleDestroy,
PipeTransform,
WebSocketAdapter,
} from '@nestjs/common';
@@ -19,9 +18,7 @@ import { Logger } from '@nestjs/common/services/logger.service';
import { loadPackage } from '@nestjs/common/utils/load-package.util';
import {
isFunction,
isNil,
isObject,
isUndefined,
validatePath,
} from '@nestjs/common/utils/shared.utils';
import * as bodyParser from 'body-parser';
@@ -35,7 +32,6 @@ import { FastifyAdapter } from './adapters/fastify-adapter';
import { ApplicationConfig } from './application-config';
import { messages } from './constants';
import { NestContainer } from './injector/container';
import { Module } from './injector/module';
import { MiddlewareContainer } from './middleware/container';
import { MiddlewareModule } from './middleware/middleware-module';
import { NestApplicationContext } from './nest-application-context';
@@ -308,7 +304,7 @@ export class NestApplication extends NestApplicationContext
await microservice.close();
}),
);
await this.callDestroyHook();
await super.close();
}
public setGlobalPrefix(prefix: string): this {
@@ -387,31 +383,4 @@ export class NestApplication extends NestApplicationContext
await microservice.listen(resolve);
});
}
private async callDestroyHook(): Promise<any> {
const modules = this.container.getModules();
await Promise.all(
iterate(modules.values()).map(
async module => await this.callModuleDestroyHook(module),
),
);
}
private async callModuleDestroyHook(module: Module): Promise<any> {
const components = [...module.routes, ...module.components];
await Promise.all(
iterate(components)
.map(([key, { instance }]) => instance)
.filter(instance => !isNil(instance))
.filter(this.hasOnModuleDestroyHook)
.map(
async instance =>
await (instance as OnModuleDestroy).onModuleDestroy(),
),
);
}
private hasOnModuleDestroyHook(instance): instance is OnModuleDestroy {
return !isUndefined((instance as OnModuleDestroy).onModuleDestroy);
}
}

View File

@@ -1,6 +1,5 @@
import { Transform, Paramtype } from '@nestjs/common/interfaces';
import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum';
import { ParamsTokenFactory } from './../pipes/params-token-factory';
import { Transform } from '@nestjs/common/interfaces';
import { ParamsTokenFactory } from './params-token-factory';
export class PipesConsumer {
private readonly paramsTokenFactory = new ParamsTokenFactory();

View File

@@ -1,18 +1,10 @@
import 'reflect-metadata';
import iterate from 'iterare';
import {
Controller,
PipeTransform,
Transform,
} from '@nestjs/common/interfaces';
import { PIPES_METADATA } from '@nestjs/common/constants';
import {
isUndefined,
isFunction,
isEmpty,
} from '@nestjs/common/utils/shared.utils';
import { ApplicationConfig } from './../application-config';
import { ContextCreator } from './../helpers/context-creator';
import { Controller, PipeTransform, Transform } from '@nestjs/common/interfaces';
import { isEmpty, isFunction, isUndefined } from '@nestjs/common/utils/shared.utils';
import iterate from 'iterare';
import 'reflect-metadata';
import { ApplicationConfig } from '../application-config';
import { ContextCreator } from '../helpers/context-creator';
import { NestContainer } from '../injector/container';
export class PipesContextCreator extends ContextCreator {

View File

@@ -3,11 +3,11 @@ import { EXCEPTION_FILTERS_METADATA } from '@nestjs/common/constants';
import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
import { isEmpty } from '@nestjs/common/utils/shared.utils';
import 'reflect-metadata';
import { ApplicationConfig } from '../application-config';
import { BaseExceptionFilterContext } from '../exceptions/base-exception-filter-context';
import { ExceptionsHandler } from '../exceptions/exceptions-handler';
import { NestContainer } from '../injector/container';
import { ApplicationConfig } from './../application-config';
import { RouterProxyCallback } from './../router/router-proxy';
import { RouterProxyCallback } from './router-proxy';
export class RouterExceptionFilters extends BaseExceptionFilterContext {
constructor(

View File

@@ -1,39 +1,19 @@
import 'reflect-metadata';
import {
ROUTE_ARGS_METADATA,
PARAMTYPES_METADATA,
HTTP_CODE_METADATA,
CUSTOM_ROUTE_AGRS_METADATA,
RENDER_METADATA,
HEADERS_METADATA,
} from '@nestjs/common/constants';
import {
isUndefined,
isFunction,
isString,
} from '@nestjs/common/utils/shared.utils';
import { ForbiddenException, HttpServer, ParamData, PipeTransform, RequestMethod } from '@nestjs/common';
import { CUSTOM_ROUTE_AGRS_METADATA, HEADERS_METADATA, HTTP_CODE_METADATA, PARAMTYPES_METADATA, RENDER_METADATA, ROUTE_ARGS_METADATA } from '@nestjs/common/constants';
import { RouteParamsMetadata } from '@nestjs/common/decorators';
import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum';
import { Controller, Transform } from '@nestjs/common/interfaces';
import { RouteParamsMetadata } from '@nestjs/common/decorators';
import { IRouteParamsFactory } from './interfaces/route-params-factory.interface';
import { PipesContextCreator } from './../pipes/pipes-context-creator';
import { PipesConsumer } from './../pipes/pipes-consumer';
import {
ParamData,
PipeTransform,
RequestMethod,
ForbiddenException,
HttpServer,
} from '@nestjs/common';
import { GuardsContextCreator } from '../guards/guards-context-creator';
import { GuardsConsumer } from '../guards/guards-consumer';
import {
RouterResponseController,
CustomHeader,
} from './router-response-controller';
import { InterceptorsContextCreator } from '../interceptors/interceptors-context-creator';
import { InterceptorsConsumer } from '../interceptors/interceptors-consumer';
import { isFunction, isString, isUndefined } from '@nestjs/common/utils/shared.utils';
import 'reflect-metadata';
import { FORBIDDEN_MESSAGE } from '../guards/constants';
import { GuardsConsumer } from '../guards/guards-consumer';
import { GuardsContextCreator } from '../guards/guards-context-creator';
import { InterceptorsConsumer } from '../interceptors/interceptors-consumer';
import { InterceptorsContextCreator } from '../interceptors/interceptors-context-creator';
import { PipesConsumer } from '../pipes/pipes-consumer';
import { PipesContextCreator } from '../pipes/pipes-context-creator';
import { IRouteParamsFactory } from './interfaces/route-params-factory.interface';
import { CustomHeader, RouterResponseController } from './router-response-controller';
export interface ParamProperties {
index: number;

View File

@@ -1,26 +1,26 @@
import 'reflect-metadata';
import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
import { METHOD_METADATA, PATH_METADATA } from '@nestjs/common/constants';
import { RequestMethod } from '@nestjs/common/enums/request-method.enum';
import { RouterProxy, RouterProxyCallback } from './router-proxy';
import { UnknownRequestMappingException } from '../errors/exceptions/unknown-request-mapping.exception';
import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
import { Type } from '@nestjs/common/interfaces/type.interface';
import { isUndefined, validatePath } from '@nestjs/common/utils/shared.utils';
import { RouterMethodFactory } from '../helpers/router-method-factory';
import { PATH_METADATA, METHOD_METADATA } from '@nestjs/common/constants';
import { Logger } from '@nestjs/common/services/logger.service';
import { isUndefined, validatePath } from '@nestjs/common/utils/shared.utils';
import 'reflect-metadata';
import { ApplicationConfig } from '../application-config';
import { UnknownRequestMappingException } from '../errors/exceptions/unknown-request-mapping.exception';
import { GuardsConsumer } from '../guards/guards-consumer';
import { GuardsContextCreator } from '../guards/guards-context-creator';
import { routeMappedMessage } from '../helpers/messages';
import { RouterExecutionContext } from './router-execution-context';
import { RouterMethodFactory } from '../helpers/router-method-factory';
import { NestContainer } from '../injector/container';
import { InterceptorsConsumer } from '../interceptors/interceptors-consumer';
import { InterceptorsContextCreator } from '../interceptors/interceptors-context-creator';
import { MetadataScanner } from '../metadata-scanner';
import { PipesConsumer } from '../pipes/pipes-consumer';
import { PipesContextCreator } from '../pipes/pipes-context-creator';
import { ExceptionsFilter } from './interfaces/exceptions-filter.interface';
import { RouteParamsFactory } from './route-params-factory';
import { MetadataScanner } from '../metadata-scanner';
import { ApplicationConfig } from './../application-config';
import { PipesContextCreator } from './../pipes/pipes-context-creator';
import { PipesConsumer } from './../pipes/pipes-consumer';
import { NestContainer } from '../injector/container';
import { GuardsContextCreator } from '../guards/guards-context-creator';
import { GuardsConsumer } from '../guards/guards-consumer';
import { InterceptorsContextCreator } from '../interceptors/interceptors-context-creator';
import { InterceptorsConsumer } from '../interceptors/interceptors-consumer';
import { RouterExecutionContext } from './router-execution-context';
import { RouterProxy, RouterProxyCallback } from './router-proxy';
export class RouterExplorer {
private readonly executionContextCreator: RouterExecutionContext;

View File

@@ -1,16 +1,16 @@
import { NestContainer, InstanceWrapper } from '../injector/container';
import { RouterProxy } from './router-proxy';
import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
import { Logger } from '@nestjs/common/services/logger.service';
import { controllerMappingMessage } from '../helpers/messages';
import { Resolver } from './interfaces/resolver.interface';
import { RouterExceptionFilters } from './router-exception-filters';
import { MetadataScanner } from '../metadata-scanner';
import { RouterExplorer } from './router-explorer';
import { ApplicationConfig } from './../application-config';
import { NotFoundException, BadRequestException } from '@nestjs/common';
import { BadRequestException, NotFoundException } from '@nestjs/common';
import { MODULE_PATH } from '@nestjs/common/constants';
import { HttpServer } from '@nestjs/common/interfaces';
import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
import { Logger } from '@nestjs/common/services/logger.service';
import { ApplicationConfig } from '../application-config';
import { controllerMappingMessage } from '../helpers/messages';
import { InstanceWrapper, NestContainer } from '../injector/container';
import { MetadataScanner } from '../metadata-scanner';
import { Resolver } from './interfaces/resolver.interface';
import { RouterExceptionFilters } from './router-exception-filters';
import { RouterExplorer } from './router-explorer';
import { RouterProxy } from './router-proxy';
export class RoutesResolver implements Resolver {
private readonly logger = new Logger(RoutesResolver.name, true);

View File

@@ -17,11 +17,11 @@ import {
isUndefined,
} from '@nestjs/common/utils/shared.utils';
import 'reflect-metadata';
import { MetadataScanner } from '../core/metadata-scanner';
import { ApplicationConfig } from './application-config';
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from './constants';
import { CircularDependencyException } from './errors/exceptions/circular-dependency.exception';
import { NestContainer } from './injector/container';
import { MetadataScanner } from './metadata-scanner';
interface ApplicationProviderWrapper {
moduleKey: string;

View File

@@ -1,14 +1,16 @@
import { expect } from 'chai';
import * as sinon from 'sinon';
import { Module as ModuleDecorator } from '../../../common/decorators/modules/module.decorator';
import { UnknownExportException } from '../../errors/exceptions/unknown-export.exception';
import { Module } from '../../injector/module';
import { Component } from '../../../common/decorators/core/component.decorator';
import { Module as ModuleDecorator } from '../../../common/decorators/modules/module.decorator';
import { RuntimeException } from '../../errors/exceptions/runtime.exception';
import { UnknownElementException } from '../../errors/exceptions/unknown-element.exception';
import { UnknownExportException } from '../../errors/exceptions/unknown-export.exception';
import { NestContainer } from '../../injector/container';
import { Module } from '../../injector/module';
describe('Module', () => {
let module: Module;
let container: NestContainer;
@ModuleDecorator({})
class TestModule {}
@@ -16,7 +18,8 @@ describe('Module', () => {
class TestComponent {}
beforeEach(() => {
module = new Module(TestModule as any, [], new NestContainer());
container = new NestContainer();
module = new Module(TestModule as any, [], container);
});
it('should add route', () => {
@@ -287,13 +290,12 @@ describe('Module', () => {
});
describe('createModuleRefMetatype', () => {
let components: Map<string, any>;
let moduleRef;
beforeEach(() => {
components = new Map();
class SimpleClass {}
const Class = module.createModuleRefMetatype(components);
beforeEach(() => {
const Class = module.createModuleRefMetatype();
moduleRef = new Class();
});
@@ -301,13 +303,8 @@ describe('Module', () => {
expect(!!moduleRef.get).to.be.true;
});
describe('get', () => {
it('should return component if exists', () => {
const comp = { instance: [] };
components.set('comp', comp);
expect(moduleRef.get('comp')).to.be.eql(comp.instance);
});
it('should return null if not exists', () => {
expect(moduleRef.get('fail')).to.be.null;
it('should throw exception if not exists', () => {
expect(() => moduleRef.get('fail')).to.throws(UnknownElementException);
});
});
});

View File

@@ -1,28 +1,23 @@
import * as optional from 'optional';
import iterate from 'iterare';
import { NestContainer } from '@nestjs/core/injector/container';
import { MicroservicesModule } from './microservices-module';
import { messages } from '@nestjs/core/constants';
import { Logger } from '@nestjs/common/services/logger.service';
import { Server } from './server/server';
import { MicroserviceOptions } from './interfaces/microservice-configuration.interface';
import { ServerFactory } from './server/server-factory';
import { Transport } from './enums/transport.enum';
import {
INestMicroservice,
WebSocketAdapter,
CanActivate,
PipeTransform,
NestInterceptor,
ExceptionFilter,
OnModuleInit,
INestMicroservice,
NestInterceptor,
PipeTransform,
WebSocketAdapter,
} from '@nestjs/common';
import { Logger } from '@nestjs/common/services/logger.service';
import { ApplicationConfig } from '@nestjs/core/application-config';
import { CustomTransportStrategy } from '@nestjs/microservices';
import { Module } from '@nestjs/core/injector/module';
import { isNil, isUndefined } from '@nestjs/common/utils/shared.utils';
import { OnModuleDestroy } from '@nestjs/common/interfaces';
import { messages } from '@nestjs/core/constants';
import { NestContainer } from '@nestjs/core/injector/container';
import { NestApplicationContext } from '@nestjs/core/nest-application-context';
import { CustomTransportStrategy } from '@nestjs/microservices';
import * as optional from 'optional';
import { Transport } from './enums/transport.enum';
import { MicroserviceOptions } from './interfaces/microservice-configuration.interface';
import { MicroservicesModule } from './microservices-module';
import { Server } from './server/server';
import { ServerFactory } from './server/server-factory';
const { SocketModule } =
optional('@nestjs/websockets/socket-module') || ({} as any);
@@ -144,59 +139,7 @@ export class NestMicroservice extends NestApplicationContext
protected async closeApplication(): Promise<any> {
this.socketModule && (await this.socketModule.close());
await this.callDestroyHook();
await super.close();
this.setIsTerminated(true);
}
protected async callInitHook(): Promise<any> {
const modules = this.container.getModules();
await Promise.all(
iterate(modules.values()).map(
async module => await this.callModuleInitHook(module),
),
);
this.setIsInitHookCalled(true);
}
protected async callModuleInitHook(module: Module): Promise<any> {
const components = [...module.routes, ...module.components];
await Promise.all(
iterate(components)
.map(([key, { instance }]) => instance)
.filter(instance => !isNil(instance))
.filter(this.hasOnModuleInitHook)
.map(async instance => await (instance as OnModuleInit).onModuleInit()),
);
}
protected hasOnModuleInitHook(instance: any): instance is OnModuleInit {
return !isUndefined((instance as OnModuleInit).onModuleInit);
}
private async callDestroyHook(): Promise<any> {
const modules = this.container.getModules();
await Promise.all(
iterate(modules.values()).map(
async module => await this.callModuleDestroyHook(module),
),
);
}
private async callModuleDestroyHook(module: Module): Promise<any> {
const components = [...module.routes, ...module.components];
await Promise.all(
iterate(components)
.map(([key, { instance }]) => instance)
.filter(instance => !isNil(instance))
.filter(this.hasOnModuleDestroyHook)
.map(
async instance =>
await (instance as OnModuleDestroy).onModuleDestroy(),
),
);
}
private hasOnModuleDestroyHook(instance): instance is OnModuleDestroy {
return !isUndefined((instance as OnModuleDestroy).onModuleDestroy);
}
}