From 5af2ffa89e6f79726bc66b345c0162bc24a073a6 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 10 Nov 2017 23:23:58 -0500 Subject: [PATCH 01/34] Created PipesModelParser --- package.json | 2 + src/core/pipes/pipes-model-parser.ts | 30 ++++++++++++++ .../test/pipes/pipes-model-parser.spec.ts | 39 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 src/core/pipes/pipes-model-parser.ts create mode 100644 src/core/test/pipes/pipes-model-parser.spec.ts diff --git a/package.json b/package.json index f881e0c1b2c..cb3dbbc9db0 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "@nestjs/microservices": "^4.0.0", "@nestjs/testing": "^4.0.0", "@nestjs/websockets": "^4.0.0", + "class-transformer": "^0.1.8", + "class-validator": "^0.7.3", "cli-color": "^1.1.0", "engine.io-client": "^3.1.1", "express": "^4.16.2", diff --git a/src/core/pipes/pipes-model-parser.ts b/src/core/pipes/pipes-model-parser.ts new file mode 100644 index 00000000000..7bb0f700e6d --- /dev/null +++ b/src/core/pipes/pipes-model-parser.ts @@ -0,0 +1,30 @@ +import { HttpException } from "@nestjs/core"; +import { + PipeTransform, + Pipe, + ArgumentMetadata, + HttpStatus +} from "@nestjs/common"; +import { validate } from "class-validator"; +import { plainToClass } from "class-transformer"; + +@Pipe() +export class PipesModelParser implements PipeTransform { + async transform(value, metadata: ArgumentMetadata) { + const { metatype } = metadata; + if (!metatype || !this.toValidate(metatype)) { + return value; + } + const entity = plainToClass(metatype, value); + const errors = await validate(entity); + if (errors.length > 0) { + throw new HttpException("Validation failed", HttpStatus.BAD_REQUEST); + } + return entity; + } + + private toValidate(metatype): boolean { + const types = [String, Boolean, Number, Array, Object]; + return !types.find(type => metatype === type); + } +} diff --git a/src/core/test/pipes/pipes-model-parser.spec.ts b/src/core/test/pipes/pipes-model-parser.spec.ts new file mode 100644 index 00000000000..b55779c1fcf --- /dev/null +++ b/src/core/test/pipes/pipes-model-parser.spec.ts @@ -0,0 +1,39 @@ +import * as sinon from "sinon"; +import { expect } from "chai"; +import { PipesModelParser } from "./../../pipes/pipes-model-parser"; +import { ArgumentMetadata } from "@nestjs/common"; + +class TestModel { + constructor(public prop1: string, public prop2: number) {} +} + +describe("PipesModelParser", () => { + let target: PipesModelParser; + let testModel; + beforeEach(() => { + target = new PipesModelParser(); + }); + describe("transform", () => { + describe("when metadata is empty or undefined", () => { + it("should return the value unchanged", async () => { + const testObj = { prop1: "value1", prop2: "value2" }; + expect(await target.transform(testObj, {} as any)).to.equal(testObj); + expect(await target.transform(testObj, {} as any)).to.not.be.instanceOf( + TestModel + ); + }); + }); + describe("when metadata contains a class", () => { + const metadata: ArgumentMetadata = { + type: "body", + metatype: TestModel, + data: "" + }; + it("should return an instance of the class", async () => { + const testObj = { prop1: "value1", prop2: "value2" }; + const result = await target.transform(testObj, metadata); + expect(result).to.be.instanceOf(TestModel); + }); + }); + }); +}); From 339a33582c89ee21e2ac3c080063897fc1066e22 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 11 Nov 2017 07:25:59 -0500 Subject: [PATCH 02/34] Improved test coverage --- .../test/pipes/pipes-model-parser.spec.ts | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/core/test/pipes/pipes-model-parser.spec.ts b/src/core/test/pipes/pipes-model-parser.spec.ts index b55779c1fcf..de5c216d0ff 100644 --- a/src/core/test/pipes/pipes-model-parser.spec.ts +++ b/src/core/test/pipes/pipes-model-parser.spec.ts @@ -2,14 +2,25 @@ import * as sinon from "sinon"; import { expect } from "chai"; import { PipesModelParser } from "./../../pipes/pipes-model-parser"; import { ArgumentMetadata } from "@nestjs/common"; +import { IsString } from "class-validator"; class TestModel { - constructor(public prop1: string, public prop2: number) {} + constructor() {} + @IsString() + public prop1: string; + + @IsString() + public prop2: string; } describe("PipesModelParser", () => { let target: PipesModelParser; let testModel; + const metadata: ArgumentMetadata = { + type: "body", + metatype: TestModel, + data: "" + }; beforeEach(() => { target = new PipesModelParser(); }); @@ -24,16 +35,17 @@ describe("PipesModelParser", () => { }); }); describe("when metadata contains a class", () => { - const metadata: ArgumentMetadata = { - type: "body", - metatype: TestModel, - data: "" - }; it("should return an instance of the class", async () => { const testObj = { prop1: "value1", prop2: "value2" }; const result = await target.transform(testObj, metadata); expect(result).to.be.instanceOf(TestModel); }); }); + describe("when validation vails", () => { + it("should throw an error", async () => { + const testObj = { prop1: "value1" }; + return expect(target.transform(testObj, metadata)).to.be.rejected; + }); + }); }); }); From a286a77f4762a5980524f457b24dcd081643a612 Mon Sep 17 00:00:00 2001 From: Michael Yali Date: Sat, 11 Nov 2017 19:33:21 +0200 Subject: [PATCH 03/34] feature(@nest): custom route params decorators --- src/common/constants.ts | 1 + .../custom-route-param-reflector.interface.ts | 6 +++ src/common/interfaces/index.ts | 3 +- .../interfaces/nest-application.interface.ts | 10 ++++ .../reflect-route-param-metadata.decorator.ts | 47 +++++++++++++++++++ src/common/utils/index.ts | 3 +- src/core/application-config.ts | 10 ++++ src/core/nest-application.ts | 5 ++ .../route-custom-params-factory.interface.ts | 3 ++ .../router/route-custom-params-factory.ts | 24 ++++++++++ src/core/router/router-execution-context.ts | 20 ++++++-- src/core/router/router-explorer.ts | 2 + .../route-custom-params.factory.spec.ts | 2 + .../router/router-execution-context.spec.ts | 3 +- 14 files changed, 133 insertions(+), 6 deletions(-) create mode 100644 src/common/interfaces/custom-route-param-reflector.interface.ts create mode 100644 src/common/utils/decorators/reflect-route-param-metadata.decorator.ts create mode 100644 src/core/router/interfaces/route-custom-params-factory.interface.ts create mode 100644 src/core/router/route-custom-params-factory.ts create mode 100644 src/core/test/router/route-custom-params.factory.spec.ts diff --git a/src/common/constants.ts b/src/common/constants.ts index 4ab5c2e9db0..e43a0ffefb6 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -11,6 +11,7 @@ export const PARAMTYPES_METADATA = 'design:paramtypes'; export const SELF_DECLARED_DEPS_METADATA = 'self:paramtypes'; export const METHOD_METADATA = 'method'; export const ROUTE_ARGS_METADATA = '__routeArguments__'; +export const CUSTOM_ROUTE_AGRS_METADATA = '_CUSTOM_ROUTE_ARGS'; export const EXCEPTION_FILTERS_METADATA = '__exceptionFilters__'; export const FILTER_CATCH_EXCEPTIONS = '__filterCatchExceptions__'; export const PIPES_METADATA = '__pipes__'; diff --git a/src/common/interfaces/custom-route-param-reflector.interface.ts b/src/common/interfaces/custom-route-param-reflector.interface.ts new file mode 100644 index 00000000000..07a223def36 --- /dev/null +++ b/src/common/interfaces/custom-route-param-reflector.interface.ts @@ -0,0 +1,6 @@ +export type CustomParamReflector = (data, req, res, next) => any; + +export interface ICustomParamReflector { + paramtype: number|string, + reflector: CustomParamReflector; +} \ No newline at end of file diff --git a/src/common/interfaces/index.ts b/src/common/interfaces/index.ts index a0129eba36b..a134c700801 100644 --- a/src/common/interfaces/index.ts +++ b/src/common/interfaces/index.ts @@ -19,4 +19,5 @@ export * from './can-activate.interface'; export * from './exceptions/rpc-exception-filter.interface'; export * from './exceptions/ws-exception-filter.interface'; export * from './execution-context.interface'; -export * from './nest-interceptor.interface'; \ No newline at end of file +export * from './nest-interceptor.interface'; +export * from './custom-route-param-reflector.interface'; \ No newline at end of file diff --git a/src/common/interfaces/nest-application.interface.ts b/src/common/interfaces/nest-application.interface.ts index 0aa254de441..cce19ad442e 100644 --- a/src/common/interfaces/nest-application.interface.ts +++ b/src/common/interfaces/nest-application.interface.ts @@ -3,6 +3,7 @@ import { INestMicroservice, ExceptionFilter, PipeTransform } from './index'; import { WebSocketAdapter } from './web-socket-adapter.interface'; import { CanActivate } from './can-activate.interface'; import { NestInterceptor } from './nest-interceptor.interface'; +import { ICustomParamReflector } from './custom-route-param-reflector.interface'; export interface INestApplication { /** @@ -116,6 +117,15 @@ export interface INestApplication { */ useGlobalGuards(...guards: CanActivate[]); + /** + * Setups creating custom param decorators for controllers + * + * @param {...ICustomParamReflector[]} decorators + * @returns {*} + * @memberof INestApplication + */ + useCustomParamDecorators(...decorators: ICustomParamReflector[]): any; + /** * Terminates the application (both NestApplication, Web Socket Gateways and every connected microservice) * diff --git a/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts b/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts new file mode 100644 index 00000000000..d2fc73cf7bd --- /dev/null +++ b/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts @@ -0,0 +1,47 @@ +import { ROUTE_ARGS_METADATA, CUSTOM_ROUTE_AGRS_METADATA } from '../../constants'; +import { ICustomParamReflector, CustomParamReflector } from '../../interfaces/custom-route-param-reflector.interface'; +import { RouteParamsMetadata, ParamData } from './route-params.decorator'; + +const assignCustomMetadata = ( + args: RouteParamsMetadata, + paramtype: number|string, + index: number, + data?: ParamData, +) => ({ + ...args, + [`${paramtype}${CUSTOM_ROUTE_AGRS_METADATA}:${index}`]: { + index, + data, + }, +}); + +/** + * Create route params custom decorator + * @param paramtype + * @param handler + */ +export const ReflectRouteParamDecorator = ( + paramtype: number|string, + reflector: CustomParamReflector, +): [ + (data?: ParamData) => ParameterDecorator, + ICustomParamReflector +] => { + const decorator = (data?: ParamData): ParameterDecorator => (target, key, index) => { + const args = Reflect.getMetadata(ROUTE_ARGS_METADATA, target, key) || {}; + Reflect.defineMetadata( + ROUTE_ARGS_METADATA, + assignCustomMetadata(args, paramtype, index, data), + target, + key, + ); + }; + + return [ + decorator, + { + paramtype: `${paramtype}${CUSTOM_ROUTE_AGRS_METADATA}`, + reflector, + }, + ] +}; diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts index 6e71813dee0..87b58ccfb76 100644 --- a/src/common/utils/index.ts +++ b/src/common/utils/index.ts @@ -15,4 +15,5 @@ export * from './decorators/reflect-metadata.decorator'; export * from './decorators/use-interceptors.decorator'; export * from './decorators/http-code.decorator'; export * from './decorators/bind.decorator'; -export * from './forward-ref.util'; \ No newline at end of file +export * from './forward-ref.util'; +export * from './decorators/reflect-route-param-metadata.decorator'; \ No newline at end of file diff --git a/src/core/application-config.ts b/src/core/application-config.ts index ba5e2710905..49a7acdf3ba 100644 --- a/src/core/application-config.ts +++ b/src/core/application-config.ts @@ -1,12 +1,14 @@ import * as optional from 'optional'; import { PipeTransform, WebSocketAdapter, ExceptionFilter, NestInterceptor, CanActivate } from '@nestjs/common'; import { ConfigurationProvider } from '@nestjs/common/interfaces/configuration-provider.interface'; +import { ICustomParamReflector } from '@nestjs/common/interfaces/custom-route-param-reflector.interface'; export class ApplicationConfig implements ConfigurationProvider { private globalPipes: PipeTransform[] = []; private globalFilters: ExceptionFilter[] = []; private globalInterceptors: NestInterceptor[] = []; private globalGuards: CanActivate[] = []; + private customParamDecorators: ICustomParamReflector[] = []; private globalPrefix = ''; constructor(private ioAdapter: WebSocketAdapter | null = null) {} @@ -58,4 +60,12 @@ export class ApplicationConfig implements ConfigurationProvider { public useGlobalGuards(...guards: CanActivate[]) { this.globalGuards = guards; } + + public getCustomParamDecorators() { + return this.customParamDecorators; + } + + public useCustomParamDecorators(...decorators: ICustomParamReflector[]) { + this.customParamDecorators = decorators; + } } \ No newline at end of file diff --git a/src/core/nest-application.ts b/src/core/nest-application.ts index e30baf13f31..419a502e28a 100644 --- a/src/core/nest-application.ts +++ b/src/core/nest-application.ts @@ -13,6 +13,7 @@ import { INestApplication, INestMicroservice, OnModuleInit } from '@nestjs/commo import { Logger } from '@nestjs/common/services/logger.service'; import { isNil, isUndefined, validatePath } from '@nestjs/common/utils/shared.utils'; import { MicroserviceConfiguration } from '@nestjs/common/interfaces/microservices/microservice-configuration.interface'; +import { ICustomParamReflector } from '@nestjs/common/interfaces/custom-route-param-reflector.interface'; import { ExpressAdapter } from './adapters/express-adapter'; import { ApplicationConfig } from './application-config'; import { messages } from './constants'; @@ -157,6 +158,10 @@ export class NestApplication implements INestApplication { this.config.useGlobalGuards(...guards); } + public useCustomParamDecorators(...decorators: ICustomParamReflector[]) { + this.config.useCustomParamDecorators(...decorators); + } + private async setupMiddlewares(instance) { await MiddlewaresModule.setupMiddlewares(instance); } diff --git a/src/core/router/interfaces/route-custom-params-factory.interface.ts b/src/core/router/interfaces/route-custom-params-factory.interface.ts new file mode 100644 index 00000000000..1a2a5f5095c --- /dev/null +++ b/src/core/router/interfaces/route-custom-params-factory.interface.ts @@ -0,0 +1,3 @@ +export interface IRouteCustomParamsFactory { + exchangeKeyForValue(paramtype: number|string, data, { req, res, next }); +} \ No newline at end of file diff --git a/src/core/router/route-custom-params-factory.ts b/src/core/router/route-custom-params-factory.ts new file mode 100644 index 00000000000..8b54381f07b --- /dev/null +++ b/src/core/router/route-custom-params-factory.ts @@ -0,0 +1,24 @@ +import { ApplicationConfig } from './../application-config'; +import { IRouteCustomParamsFactory } from './interfaces/route-custom-params-factory.interface'; + +export class RouteCustomParamsFactory implements IRouteCustomParamsFactory { + constructor(private readonly config?: ApplicationConfig) {} + + public exchangeKeyForValue(paramtype, data, { req, res, next }) { + const customParamDecorators = this.config && this.config.getCustomParamDecorators(); + if (customParamDecorators) { + const decorator = customParamDecorators.find((one) => one.paramtype === paramtype); + if (decorator && decorator.reflector) { + try { + return decorator.reflector(data, req, res, next); + } catch (error) { + return null; + } + } + + return null; + } + + return null; + } +} \ No newline at end of file diff --git a/src/core/router/router-execution-context.ts b/src/core/router/router-execution-context.ts index 575044d68f9..582ea9459c5 100644 --- a/src/core/router/router-execution-context.ts +++ b/src/core/router/router-execution-context.ts @@ -1,10 +1,11 @@ import 'reflect-metadata'; -import { ROUTE_ARGS_METADATA, PARAMTYPES_METADATA, HTTP_CODE_METADATA } from '@nestjs/common/constants'; +import { ROUTE_ARGS_METADATA, PARAMTYPES_METADATA, HTTP_CODE_METADATA, CUSTOM_ROUTE_AGRS_METADATA } from '@nestjs/common/constants'; import { isUndefined } from '@nestjs/common/utils/shared.utils'; import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum'; import { Controller, Transform } from '@nestjs/common/interfaces'; import { RouteParamsMetadata } from '@nestjs/common/utils'; import { IRouteParamsFactory } from './interfaces/route-params-factory.interface'; +import { IRouteCustomParamsFactory } from './interfaces/route-custom-params-factory.interface'; import { PipesContextCreator } from './../pipes/pipes-context-creator'; import { PipesConsumer } from './../pipes/pipes-consumer'; import { ParamData, PipeTransform, HttpStatus, RequestMethod } from '@nestjs/common'; @@ -28,6 +29,7 @@ export class RouterExecutionContext { private readonly responseController = new RouterResponseController(); constructor( private readonly paramsFactory: IRouteParamsFactory, + private readonly customParamsFactory: IRouteCustomParamsFactory, private readonly pipesContextCreator: PipesContextCreator, private readonly pipesConsumer: PipesConsumer, private readonly guardsContextCreator: GuardsContextCreator, @@ -79,6 +81,11 @@ export class RouterExecutionContext { return Number(keyPair[0]); } + public mapCustomParamType(key: string) { + const keyPair = key.split(':'); + return keyPair[0]; + } + public reflectCallbackMetadata(instance: Controller, methodName: string): RouteParamsMetadata { return Reflect.getMetadata(ROUTE_ARGS_METADATA, instance, methodName); } @@ -101,10 +108,17 @@ export class RouterExecutionContext { public exchangeKeysForValues(keys: string[], metadata: RouteParamsMetadata): ParamProperties[] { return keys.map(key => { - const type = this.mapParamType(key); const { index, data, pipes } = metadata[key]; + let type, extractValue; + + if (key.includes(CUSTOM_ROUTE_AGRS_METADATA)) { + type = this.mapCustomParamType(key); + extractValue = (req, res, next) => this.customParamsFactory.exchangeKeyForValue(type, data, { req, res, next }); + } else { + type = this.mapParamType(key); + extractValue = (req, res, next) => this.paramsFactory.exchangeKeyForValue(type, data, { req, res, next }); + } - const extractValue = (req, res, next) => this.paramsFactory.exchangeKeyForValue(type, data, { req, res, next }); return { index, extractValue, type, data, pipes }; }); } diff --git a/src/core/router/router-explorer.ts b/src/core/router/router-explorer.ts index 4cba4ec87fc..635933e0676 100644 --- a/src/core/router/router-explorer.ts +++ b/src/core/router/router-explorer.ts @@ -13,6 +13,7 @@ import { RouteMappedMessage } from '../helpers/messages'; import { RouterExecutionContext } from './router-execution-context'; import { ExceptionsFilter } from './interfaces/exceptions-filter.interface'; import { RouteParamsFactory } from './route-params-factory'; +import { RouteCustomParamsFactory } from './route-custom-params-factory'; import { RouterExplorer } from './interfaces/explorer.inteface'; import { MetadataScanner } from '../metadata-scanner'; import { ApplicationConfig } from './../application-config'; @@ -39,6 +40,7 @@ export class ExpressRouterExplorer implements RouterExplorer { this.executionContextCreator = new RouterExecutionContext( new RouteParamsFactory(), + new RouteCustomParamsFactory(config), new PipesContextCreator(config), new PipesConsumer(), new GuardsContextCreator(container, config), diff --git a/src/core/test/router/route-custom-params.factory.spec.ts b/src/core/test/router/route-custom-params.factory.spec.ts new file mode 100644 index 00000000000..3dc605ede77 --- /dev/null +++ b/src/core/test/router/route-custom-params.factory.spec.ts @@ -0,0 +1,2 @@ +import { expect } from 'chai'; +import { RouteCustomParamsFactory } from '../../router/route-custom-params-factory'; \ No newline at end of file diff --git a/src/core/test/router/router-execution-context.spec.ts b/src/core/test/router/router-execution-context.spec.ts index 96b621fd04c..75a31d376ac 100644 --- a/src/core/test/router/router-execution-context.spec.ts +++ b/src/core/test/router/router-execution-context.spec.ts @@ -4,6 +4,7 @@ import { RouteParamtypes } from '../../../common/enums/route-paramtypes.enum'; import { RouterExecutionContext } from '../../router/router-execution-context'; import { RouteParamsMetadata, Request, Body } from '../../../index'; import { RouteParamsFactory } from '../../router/route-params-factory'; +import { RouteCustomParamsFactory } from '../../router/route-custom-params-factory'; import { PipesContextCreator } from '../../pipes/pipes-context-creator'; import { PipesConsumer } from '../../pipes/pipes-consumer'; import { ApplicationConfig } from '../../application-config'; @@ -33,7 +34,7 @@ describe('RouterExecutionContext', () => { consumer = new PipesConsumer(); contextCreator = new RouterExecutionContext( - factory, new PipesContextCreator(new ApplicationConfig()), consumer, + factory, new RouteCustomParamsFactory(new ApplicationConfig()), new PipesContextCreator(new ApplicationConfig()), consumer, new GuardsContextCreator(new NestContainer()), new GuardsConsumer(), new InterceptorsContextCreator(new NestContainer()), new InterceptorsConsumer(), ); From 939859aacf6bb9da2631b0ae778e2c8d998965ca Mon Sep 17 00:00:00 2001 From: Michael Yali Date: Sat, 11 Nov 2017 21:03:42 +0200 Subject: [PATCH 04/34] feature(@nest): tests coverage for route custom params decorators --- .../reflect-route-param-metadata.spec.ts | 33 +++++++++++ src/core/test/application-config.spec.ts | 8 +++ .../route-custom-params.factory.spec.ts | 56 ++++++++++++++++++- .../router/router-execution-context.spec.ts | 17 ++++-- 4 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 src/common/test/utils/reflect-route-param-metadata.spec.ts diff --git a/src/common/test/utils/reflect-route-param-metadata.spec.ts b/src/common/test/utils/reflect-route-param-metadata.spec.ts new file mode 100644 index 00000000000..278d1e7dce9 --- /dev/null +++ b/src/common/test/utils/reflect-route-param-metadata.spec.ts @@ -0,0 +1,33 @@ +import { expect } from 'chai'; +import { ReflectRouteParamDecorator } from '../../utils/decorators/reflect-route-param-metadata.decorator'; +import { CUSTOM_ROUTE_AGRS_METADATA } from '../../constants'; + +const ley = 'key' +const reflector = (data, req, res, next) => true; +const [roles, rolesReflector] = ReflectRouteParamDecorator('roles', reflector); + +describe('ReflectRouteParamDecorator', () => { + let key; + let reflector; + let result; + + beforeEach(() => { + key = 'key'; + reflector = (data, req, res, next) => true; + result = ReflectRouteParamDecorator(key, reflector); + }); + it('should return an array', () => { + expect(result).to.be.an('array'); + }); + it('should return a function as a first element', () => { + expect(result[0]).to.be.a('function'); + }); + it('should return reflector object as a second element', () => { + expect(result[1]).to.be.an('object'); + expect(result[1]).to.have.property('paramtype'); + expect(result[1]).to.have.property('reflector'); + expect(result[1].paramtype).to.be.eql(`${key}${CUSTOM_ROUTE_AGRS_METADATA}`); + expect(result[1].reflector).to.be.eql(reflector); + }); +}); + diff --git a/src/core/test/application-config.spec.ts b/src/core/test/application-config.spec.ts index 908ae3145eb..13207ca2728 100644 --- a/src/core/test/application-config.spec.ts +++ b/src/core/test/application-config.spec.ts @@ -58,4 +58,12 @@ describe('ApplicationConfig', () => { expect(appConfig.getGlobalInterceptors()).to.be.eql(interceptors); }); }); + describe('Custom Param Decorators', () => { + it('should set and get custom param decorators', () => { + const decorators = ['test', 'test2']; + appConfig.useCustomParamDecorators(...decorators as any); + + expect(appConfig.getCustomParamDecorators()).to.be.eql(decorators); + }); + }); }); \ No newline at end of file diff --git a/src/core/test/router/route-custom-params.factory.spec.ts b/src/core/test/router/route-custom-params.factory.spec.ts index 3dc605ede77..410f49c2cbd 100644 --- a/src/core/test/router/route-custom-params.factory.spec.ts +++ b/src/core/test/router/route-custom-params.factory.spec.ts @@ -1,2 +1,56 @@ import { expect } from 'chai'; -import { RouteCustomParamsFactory } from '../../router/route-custom-params-factory'; \ No newline at end of file +import { RouteCustomParamsFactory } from '../../router/route-custom-params-factory'; +import { ICustomParamReflector } from '../../../common/interfaces/custom-route-param-reflector.interface'; +import { ApplicationConfig } from '../../application-config'; + +describe('RouteCustomParamsFactory', () => { + let factory: RouteCustomParamsFactory; + let config: ApplicationConfig; + beforeEach(() => { + config = new ApplicationConfig(); + factory = new RouteCustomParamsFactory(config); + }); + describe('exchangeKeyForValue', () => { + const res = {}; + const next = () => ({}); + const req = { + session: null, + body: { + foo: 'bar', + }, + headers: { + foo: 'bar', + }, + params: { + foo: 'bar', + }, + query: { + foo: 'bar', + }, + }; + const args = ['key', null, { req, res, next }]; + it('should return null if config is nil', () => { + let factory2 = new RouteCustomParamsFactory(); + expect((factory2 as any).exchangeKeyForValue(...args)).to.be.eql(null); + }); + it('should return null if no custom decorators found', () => { + expect((factory as any).exchangeKeyForValue(...args)).to.be.eql(null); + }); + it('should return null is reflector throws an error', () => { + const reflector = { + paramtype: 'key', + reflector: (data, req, res, next) => { throw new Error }, + } as ICustomParamReflector; + config.useCustomParamDecorators(reflector); + expect((factory as any).exchangeKeyForValue(...args)).to.be.eql(null); + }); + it('should return reflector result', () => { + const reflector = { + paramtype: 'key', + reflector: (data, req, res, next) => true, + } as ICustomParamReflector; + config.useCustomParamDecorators(reflector); + expect((factory as any).exchangeKeyForValue(...args)).to.be.eql(true); + }); + }); +}); \ No newline at end of file diff --git a/src/core/test/router/router-execution-context.spec.ts b/src/core/test/router/router-execution-context.spec.ts index 75a31d376ac..5e85e31cbd7 100644 --- a/src/core/test/router/router-execution-context.spec.ts +++ b/src/core/test/router/router-execution-context.spec.ts @@ -1,6 +1,8 @@ import * as sinon from 'sinon'; import { expect } from 'chai'; import { RouteParamtypes } from '../../../common/enums/route-paramtypes.enum'; +import { CUSTOM_ROUTE_AGRS_METADATA } from '../../../common/constants'; +import { ReflectRouteParamDecorator } from '../../../common/utils/decorators/reflect-route-param-metadata.decorator'; import { RouterExecutionContext } from '../../router/router-execution-context'; import { RouteParamsMetadata, Request, Body } from '../../../index'; import { RouteParamsFactory } from '../../router/route-params-factory'; @@ -105,8 +107,9 @@ describe('RouterExecutionContext', () => { }); }); describe('reflectCallbackMetadata', () => { + const [ CustomDecorator ] = ReflectRouteParamDecorator('custom', () => {}); class TestController { - public callback(@Request() req, @Body() body) {} + public callback(@Request() req, @Body() body, @CustomDecorator() custom) {} } it('should returns ROUTE_ARGS_METADATA callback metadata', () => { const instance = new TestController(); @@ -122,6 +125,10 @@ describe('RouterExecutionContext', () => { data: undefined, pipes: [], }, + [`custom${CUSTOM_ROUTE_AGRS_METADATA}:2`]: { + index: 2, + data: undefined, + }, }; expect(metadata).to.deep.equal(expectedMetadata); }); @@ -154,17 +161,15 @@ describe('RouterExecutionContext', () => { it('should exchange arguments keys for appropriate values', () => { const metadata = { [RouteParamtypes.REQUEST]: { index: 0, data: 'test', pipes: [] }, - [RouteParamtypes.BODY]: { - index: 2, - data: 'test', - pipes: [], - }, + [RouteParamtypes.BODY]: { index: 2, data: 'test', pipes: [] }, + [`key${CUSTOM_ROUTE_AGRS_METADATA}`]: { index: 3, data: 'custom', pipes: [] }, }; const keys = Object.keys(metadata); const values = contextCreator.exchangeKeysForValues(keys, metadata); const expectedValues = [ { index: 0, type: RouteParamtypes.REQUEST, data: 'test' }, { index: 2, type: RouteParamtypes.BODY, data: 'test' }, + { index: 3, type: `key${CUSTOM_ROUTE_AGRS_METADATA}`, data: 'custom' }, ]; expect(values[0]).to.deep.include(expectedValues[0]); expect(values[1]).to.deep.include(expectedValues[1]); From 997d57de1c1289a2cc19184036299df65274161f Mon Sep 17 00:00:00 2001 From: Michael Yali Date: Sun, 12 Nov 2017 11:43:04 +0200 Subject: [PATCH 05/34] feature(@nest): custorm params decorators - optional paramtype --- .../utils/reflect-route-param-metadata.spec.ts | 14 ++++++++------ .../reflect-route-param-metadata.decorator.ts | 9 ++++++--- .../test/router/router-execution-context.spec.ts | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/common/test/utils/reflect-route-param-metadata.spec.ts b/src/common/test/utils/reflect-route-param-metadata.spec.ts index 278d1e7dce9..bb1bb8837d7 100644 --- a/src/common/test/utils/reflect-route-param-metadata.spec.ts +++ b/src/common/test/utils/reflect-route-param-metadata.spec.ts @@ -2,10 +2,6 @@ import { expect } from 'chai'; import { ReflectRouteParamDecorator } from '../../utils/decorators/reflect-route-param-metadata.decorator'; import { CUSTOM_ROUTE_AGRS_METADATA } from '../../constants'; -const ley = 'key' -const reflector = (data, req, res, next) => true; -const [roles, rolesReflector] = ReflectRouteParamDecorator('roles', reflector); - describe('ReflectRouteParamDecorator', () => { let key; let reflector; @@ -14,7 +10,7 @@ describe('ReflectRouteParamDecorator', () => { beforeEach(() => { key = 'key'; reflector = (data, req, res, next) => true; - result = ReflectRouteParamDecorator(key, reflector); + result = ReflectRouteParamDecorator(reflector, key); }); it('should return an array', () => { expect(result).to.be.an('array'); @@ -26,8 +22,14 @@ describe('ReflectRouteParamDecorator', () => { expect(result[1]).to.be.an('object'); expect(result[1]).to.have.property('paramtype'); expect(result[1]).to.have.property('reflector'); - expect(result[1].paramtype).to.be.eql(`${key}${CUSTOM_ROUTE_AGRS_METADATA}`); expect(result[1].reflector).to.be.eql(reflector); }); + it('should return paramtype with a key string', () => { + expect(result[1].paramtype).to.be.eql(`${key}${CUSTOM_ROUTE_AGRS_METADATA}`); + }); + it('should return paramtype as a rundom string', () => { + result = ReflectRouteParamDecorator(reflector); + expect(result[1].paramtype).to.not.be.eql(`${key}${CUSTOM_ROUTE_AGRS_METADATA}`); + }); }); diff --git a/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts b/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts index d2fc73cf7bd..67036961a8b 100644 --- a/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts +++ b/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts @@ -15,18 +15,21 @@ const assignCustomMetadata = ( }, }); +const randomString = () => Math.random().toString(36).substring(2, 15); + /** * Create route params custom decorator - * @param paramtype - * @param handler + * @param reflector + * @param key */ export const ReflectRouteParamDecorator = ( - paramtype: number|string, reflector: CustomParamReflector, + key: number|string = null, ): [ (data?: ParamData) => ParameterDecorator, ICustomParamReflector ] => { + const paramtype = key === null ? randomString() + randomString() : key; const decorator = (data?: ParamData): ParameterDecorator => (target, key, index) => { const args = Reflect.getMetadata(ROUTE_ARGS_METADATA, target, key) || {}; Reflect.defineMetadata( diff --git a/src/core/test/router/router-execution-context.spec.ts b/src/core/test/router/router-execution-context.spec.ts index 5e85e31cbd7..fa37c482fbf 100644 --- a/src/core/test/router/router-execution-context.spec.ts +++ b/src/core/test/router/router-execution-context.spec.ts @@ -107,7 +107,7 @@ describe('RouterExecutionContext', () => { }); }); describe('reflectCallbackMetadata', () => { - const [ CustomDecorator ] = ReflectRouteParamDecorator('custom', () => {}); + const [ CustomDecorator ] = ReflectRouteParamDecorator(() => {}, 'custom'); class TestController { public callback(@Request() req, @Body() body, @CustomDecorator() custom) {} } From 95b49bee08b166f5c9a221b76ed3c049e07cc5e4 Mon Sep 17 00:00:00 2001 From: Wilson Hobbs Date: Tue, 14 Nov 2017 17:29:26 -0500 Subject: [PATCH 06/34] Create ISSUE_TEMPLATE to quickly sort out issues --- .github/ISSUE_TEMPLATE.md | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000000..46d863ca8e2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,44 @@ + + +## I'm submitting a... + +

+[ ] Regression (a behavior that used to work and stopped working in a new release)
+[ ] Bug report  
+[ ] Feature request
+[ ] Documentation issue or request
+[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
+
+ +## Current behavior + + + +## Expected behavior + + + +## Minimal reproduction of the problem with instructions + + +## What is the motivation / use case for changing the behavior? + + + +## Environment + +

+Nest version: X.Y.Z
+
+ 
+For Tooling issues:
+- Node version: XX  
+- Platform:  
+
+Others:
+
+
From ec4afe046123f9d81442891026c517556e503327 Mon Sep 17 00:00:00 2001 From: Wilson Hobbs Date: Wed, 15 Nov 2017 10:09:57 -0500 Subject: [PATCH 07/34] Update ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 46d863ca8e2..0d3b913f040 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -7,7 +7,7 @@ ISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION. ## I'm submitting a...

-[ ] Regression (a behavior that used to work and stopped working in a new release)
+[ ] Regression 
 [ ] Bug report  
 [ ] Feature request
 [ ] Documentation issue or request

From d059732a7f5fa76c657b8813876813236e2c8c69 Mon Sep 17 00:00:00 2001
From: Wilson Hobbs 
Date: Wed, 15 Nov 2017 10:11:49 -0500
Subject: [PATCH 08/34] Add request to search for existing issue

---
 .github/ISSUE_TEMPLATE.md | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 0d3b913f040..24552941641 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -5,10 +5,12 @@ ISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION.
 -->
 
 ## I'm submitting a...
-
+
 

 [ ] Regression 
-[ ] Bug report  
+[ ] Bug report
 [ ] Feature request
 [ ] Documentation issue or request
 [ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

From aaa5fd1cba83587ccbeb748c9e2b22573e8200df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Tue, 21 Nov 2017 13:35:17 +0100
Subject: [PATCH 09/34] update(@nestjs) update to 4.3.0 version

---
 CHANGELOG.md                                  |  8 ++
 package.json                                  |  4 +-
 .../undefined-dependency.exception.ts         |  4 +-
 .../unknown-dependencies.exception.ts         |  4 +-
 src/core/errors/messages.ts                   | 15 +++-
 src/core/injector/injector.ts                 | 79 +++++++++++++++----
 src/core/middlewares/middlewares-module.ts    | 53 ++++++++-----
 src/core/nest-application.ts                  | 17 +++-
 src/core/router/router-execution-context.ts   |  4 +-
 src/core/test/injector/injector.spec.ts       | 38 ++++-----
 .../middlewares/middlewares-module.spec.ts    | 13 +--
 src/testing/testing-module.ts                 |  9 ++-
 12 files changed, 172 insertions(+), 76 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9f6a8a50d36..d2b9c2016f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 4.3.0
+- **core**: `json` and `urlencoded` (`body-parser`) middlewares are applied by default now, bugfix #252
+- **core** more informative error message (injector) #223
+example: `[ExceptionHandler] Nest can't resolve dependencies of the UsersService (+, +, ?, +, +, +). Please verify whether [2] argument is available in the current context.`
+- **core**: bugfix #240 - middlewares container state
+- **core**: bugifx #257 - `@Next()` issue
+- **testing**: testing module is now independent from `@nestjs/microservices`
+
 ## 4.2.2
 - **websockets**: bugfix #242
 
diff --git a/package.json b/package.json
index f881e0c1b2c..50fb81c91ed 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "nestjs",
-  "version": "4.2.0",
+  "version": "4.3.0",
   "description": "Modern, fast, powerful node.js web framework",
   "main": "index.js",
   "scripts": {
@@ -41,7 +41,7 @@
   "devDependencies": {
     "@types/chai": "^3.5.2",
     "@types/chai-as-promised": "0.0.31",
-    "@types/express": "^4.0.36",
+    "@types/express": "^4.0.39",
     "@types/mocha": "^2.2.38",
     "@types/node": "^7.0.5",
     "@types/redis": "^0.12.36",
diff --git a/src/core/errors/exceptions/undefined-dependency.exception.ts b/src/core/errors/exceptions/undefined-dependency.exception.ts
index d7cdfaf8d71..b8116f2f9f8 100644
--- a/src/core/errors/exceptions/undefined-dependency.exception.ts
+++ b/src/core/errors/exceptions/undefined-dependency.exception.ts
@@ -2,7 +2,7 @@ import { RuntimeException } from './runtime.exception';
 import { UnknownDependenciesMessage } from '../messages';
 
 export class UndefinedDependencyException extends RuntimeException {
-    constructor(type: string) {
-        super(UnknownDependenciesMessage(type));
+    constructor(type: string, index: number, length: number) {
+        super(UnknownDependenciesMessage(type, index, length));
     }
 }
\ No newline at end of file
diff --git a/src/core/errors/exceptions/unknown-dependencies.exception.ts b/src/core/errors/exceptions/unknown-dependencies.exception.ts
index c9b96604d47..e2c52f2a9ed 100644
--- a/src/core/errors/exceptions/unknown-dependencies.exception.ts
+++ b/src/core/errors/exceptions/unknown-dependencies.exception.ts
@@ -2,7 +2,7 @@ import { RuntimeException } from './runtime.exception';
 import { UnknownDependenciesMessage } from '../messages';
 
 export class UnknownDependenciesException extends RuntimeException {
-    constructor(type: string) {
-        super(UnknownDependenciesMessage(type));
+    constructor(type: string, index: number, length: number) {
+        super(UnknownDependenciesMessage(type, index, length));
     }
 }
\ No newline at end of file
diff --git a/src/core/errors/messages.ts b/src/core/errors/messages.ts
index f98801a7930..62b08e8fa70 100644
--- a/src/core/errors/messages.ts
+++ b/src/core/errors/messages.ts
@@ -1,12 +1,21 @@
+export const UnknownDependenciesMessage = (type: string, index: number, length: number) => {
+  let message = `Nest can't resolve dependencies of the ${type}`;
+  message += ` (`;
+
+  const args = new Array(length).fill('+');
+  args[index] = '?';
+  message += args.join(', ');
+
+  message += `). Please verify whether [${index}] argument is available in the current context.`;
+  return message;
+};
+
 export const InvalidMiddlewareMessage = (name: string) =>
     `The middleware doesn't provide the 'resolve' method (${name})`;
 
 export const InvalidModuleMessage = (scope: string) =>
     `Nest can't create the module instance. The frequent reason of this exception is the circular dependency between modules. Use forwardRef() to avoid it (read more https://docs.nestjs.com/advanced/circular-dependency). Scope [${scope}]`;
 
-export const UnknownDependenciesMessage = (type: string) =>
-    `Nest can't resolve dependencies of the ${type}. Please verify whether all of them are available in the current context.`;
-
 export const UnknownExportMessage = (name: string) =>
     `You are trying to export unknown component (${name}). Remember - your component should be listed both in exports and components arrays!`;
 
diff --git a/src/core/injector/injector.ts b/src/core/injector/injector.ts
index 7e1c6d6484a..f058bd26f44 100644
--- a/src/core/injector/injector.ts
+++ b/src/core/injector/injector.ts
@@ -100,8 +100,14 @@ export class Injector {
     let isResolved = true;
     const args = isNil(inject) ? this.reflectConstructorParams(wrapper.metatype) : inject;
 
-    const instances = await Promise.all(args.map(async (param) => {
-      const paramWrapper = await this.resolveSingleParam(wrapper, param, module, context);
+    const instances = await Promise.all(args.map(async (param, index) => {
+      const paramWrapper = await this.resolveSingleParam(
+        wrapper,
+        param,
+        { index, length: args.length },
+        module,
+        context,
+      );
       if (!paramWrapper.isResolved && !paramWrapper.forwardRef) {
         isResolved = false;
       }
@@ -125,16 +131,18 @@ export class Injector {
   public async resolveSingleParam(
     wrapper: InstanceWrapper,
     param: Metatype | string | symbol | any,
+    { index, length }: { index: number, length: number },
     module: Module,
-    context: Module[]) {
-
+    context: Module[],
+  ) {
     if (isUndefined(param)) {
-      throw new UndefinedDependencyException(wrapper.name);
+      throw new UndefinedDependencyException(wrapper.name, index, length);
     }
     const token = this.resolveParamToken(wrapper, param);
     return await this.resolveComponentInstance(
       module,
       isFunction(token) ? (token as Metatype).name : token,
+      { index, length },
       wrapper,
       context,
     );
@@ -151,10 +159,21 @@ export class Injector {
     return param.forwardRef();
   }
 
-  public async resolveComponentInstance(module: Module, name: any, wrapper: InstanceWrapper, context: Module[]) {
+  public async resolveComponentInstance(
+    module: Module,
+    name: any,
+    { index, length }: { index: number, length: number },
+    wrapper: InstanceWrapper,
+    context: Module[],
+  ) {
     const components = module.components;
-    const instanceWrapper = await this.scanForComponent(components, name, module, wrapper, context);
-
+    const instanceWrapper = await this.scanForComponent(
+      components,
+      module,
+      { name, index, length },
+      wrapper,
+      context,
+    );
     if (!instanceWrapper.isResolved && !instanceWrapper.forwardRef) {
       await this.loadInstanceOfComponent(instanceWrapper, module);
     }
@@ -164,36 +183,62 @@ export class Injector {
     return instanceWrapper;
   }
 
-  public async scanForComponent(components: Map, name: any, module: Module, { metatype }, context: Module[] = []) {
-    const component = await this.scanForComponentInScopes(context, name, metatype);
+  public async scanForComponent(
+    components: Map,
+    module: Module,
+    { name, index, length }: { name: any, index: number, length: number },
+    { metatype },
+    context: Module[] = [],
+  ) {
+    const component = await this.scanForComponentInScopes(context, { name, index, length }, metatype);
     if (component) {
       return component;
     }
-    const scanInExports = () => this.scanForComponentInExports(components, name, module, metatype, context);
+    const scanInExports = () => this.scanForComponentInExports(
+      components,
+      { name, index, length },
+      module,
+      metatype,
+      context,
+    );
     return components.has(name) ? components.get(name) : await scanInExports();
   }
 
-  public async scanForComponentInExports(components: Map, name: any, module: Module, metatype, context: Module[] = []) {
+  public async scanForComponentInExports(
+    components: Map,
+    { name, index, length }: { name: any, index: number, length: number },
+    module: Module,
+    metatype,
+    context: Module[] = [],
+  ) {
     const instanceWrapper = await this.scanForComponentInRelatedModules(module, name, context);
     if (isNil(instanceWrapper)) {
-      throw new UnknownDependenciesException(metatype.name);
+      throw new UnknownDependenciesException(metatype.name, index, length);
     }
     return instanceWrapper;
   }
 
-  public async scanForComponentInScopes(context: Module[], name: any, metatype) {
+  public async scanForComponentInScopes(
+    context: Module[],
+    { name, index, length }: { name: any, index: number, length: number },
+    metatype,
+  ) {
     context = context || [];
     for (const ctx of context) {
-      const component = await this.scanForComponentInScope(ctx, name, metatype);
+      const component = await this.scanForComponentInScope(ctx, { name, index, length }, metatype);
       if (component) return component;
     }
     return null;
   }
 
-  public async scanForComponentInScope(context: Module, name: any, metatype) {
+  public async scanForComponentInScope(
+    context: Module,
+    { name, index, length }: { name: any, index: number, length: number },
+    metatype,
+  ) {
     try {
       const component = await this.scanForComponent(
-        context.components, name, context, { metatype }, null,
+        context.components, context, { name, index, length }, { metatype }, null,
       );
       if (!component.isResolved && !component.forwardRef) {
         await this.loadInstanceOfComponent(component, context);
diff --git a/src/core/middlewares/middlewares-module.ts b/src/core/middlewares/middlewares-module.ts
index 697edd61e94..43a563f4e31 100644
--- a/src/core/middlewares/middlewares-module.ts
+++ b/src/core/middlewares/middlewares-module.ts
@@ -21,71 +21,84 @@ import { RouterExceptionFilters } from './../router/router-exception-filters';
 
 export class MiddlewaresModule {
     private static readonly routesMapper = new RoutesMapper();
-    private static readonly container = new MiddlewaresContainer();
     private static readonly routerProxy = new RouterProxy();
     private static readonly routerMethodFactory = new RouterMethodFactory();
     private static routerExceptionFilter: RouterExceptionFilters;
     private static resolver: MiddlewaresResolver;
 
-    public static async setup(container: NestContainer, config: ApplicationConfig) {
+    public static async setup(
+        middlewaresContainer: MiddlewaresContainer,
+        container: NestContainer,
+        config: ApplicationConfig,
+    ) {
         this.routerExceptionFilter = new RouterExceptionFilters(config);
-        this.resolver = new MiddlewaresResolver(this.container);
+        this.resolver = new MiddlewaresResolver(middlewaresContainer);
 
         const modules = container.getModules();
-        await this.resolveMiddlewares(modules);
+        await this.resolveMiddlewares(middlewaresContainer, modules);
     }
 
-    public static getContainer(): MiddlewaresContainer {
-        return this.container;
-    }
-
-    public static async resolveMiddlewares(modules: Map) {
+    public static async resolveMiddlewares(
+        middlewaresContainer: MiddlewaresContainer,
+        modules: Map,
+    ) {
         await Promise.all([...modules.entries()].map(async ([name, module]) => {
             const instance = module.instance;
 
-            this.loadConfiguration(instance, name);
+            this.loadConfiguration(middlewaresContainer, instance, name);
             await this.resolver.resolveInstances(module, name);
         }));
     }
 
-    public static loadConfiguration(instance: NestModule, module: string) {
+    public static loadConfiguration(
+        middlewaresContainer: MiddlewaresContainer,
+        instance: NestModule,
+        module: string,
+    ) {
         if (!instance.configure) return;
 
         const middlewaresBuilder = new MiddlewareBuilder(this.routesMapper);
         instance.configure(middlewaresBuilder);
+
         if (!(middlewaresBuilder instanceof MiddlewareBuilder)) return;
 
         const config = middlewaresBuilder.build();
-        this.container.addConfig(config, module);
+        middlewaresContainer.addConfig(config, module);
     }
 
-    public static async setupMiddlewares(app) {
-        const configs = this.container.getConfigs();
+    public static async setupMiddlewares(middlewaresContainer: MiddlewaresContainer, app) {
+        const configs = middlewaresContainer.getConfigs();
         await Promise.all([...configs.entries()].map(async ([module, moduleConfigs]) => {
             await Promise.all([...moduleConfigs].map(async (config: MiddlewareConfiguration) => {
-                await this.setupMiddlewareConfig(config, module, app);
+                await this.setupMiddlewareConfig(middlewaresContainer, config, module, app);
             }));
         }));
     }
 
-    public static async setupMiddlewareConfig(config: MiddlewareConfiguration, module: string, app) {
+    public static async setupMiddlewareConfig(
+        middlewaresContainer: MiddlewaresContainer, 
+        config: MiddlewareConfiguration, 
+        module: string,
+        app,
+    ) {
         const { forRoutes } = config;
         await Promise.all(forRoutes.map(async (route: ControllerMetadata & { method: RequestMethod }) => {
-            await this.setupRouteMiddleware(route, config, module, app);
+            await this.setupRouteMiddleware(middlewaresContainer, route, config, module, app);
         }));
     }
 
     public static async setupRouteMiddleware(
+        middlewaresContainer: MiddlewaresContainer,
         route: ControllerMetadata & { method: RequestMethod },
         config: MiddlewareConfiguration,
         module: string,
-        app) {
-
+        app,
+    ) {
         const { path, method } = route;
 
         const middlewares = [].concat(config.middlewares);
         await Promise.all(middlewares.map(async (metatype: Metatype) => {
-            const collection = this.container.getMiddlewares(module);
+            const collection = middlewaresContainer.getMiddlewares(module);
             const middleware = collection.get(metatype.name);
             if (isUndefined(middleware)) {
                 throw new RuntimeException();
diff --git a/src/core/nest-application.ts b/src/core/nest-application.ts
index a7a2c5d5ff9..312524ee354 100644
--- a/src/core/nest-application.ts
+++ b/src/core/nest-application.ts
@@ -1,5 +1,6 @@
 import * as http from 'http';
 import * as optional from 'optional';
+import * as bodyParser from 'body-parser';
 import iterate from 'iterare';
 import {
     CanActivate,
@@ -22,6 +23,7 @@ import { MiddlewaresModule } from './middlewares/middlewares-module';
 import { Resolver } from './router/interfaces/resolver.interface';
 import { RoutesResolver } from './router/routes-resolver';
 import { MicroservicesPackageNotFoundException } from './errors/exceptions/microservices-package-not-found.exception';
+import { MiddlewaresContainer } from './middlewares/container';
 
 const { SocketModule } = optional('@nestjs/websockets/socket-module') || {} as any;
 const { MicroservicesModule } = optional('@nestjs/microservices/microservices-module') || {} as any;
@@ -29,6 +31,7 @@ const { NestMicroservice } = optional('@nestjs/microservices/nest-microservice')
 const { IoAdapter } = optional('@nestjs/websockets/adapters/io-adapter') || {} as any;
 
 export class NestApplication implements INestApplication {
+    private readonly middlewaresContainer = new MiddlewaresContainer();
     private readonly logger = new Logger(NestApplication.name, true);
     private readonly httpServer: http.Server = null;
     private readonly routesResolver: Resolver = null;
@@ -40,6 +43,7 @@ export class NestApplication implements INestApplication {
         private readonly container: NestContainer,
         private readonly express,
     ) {
+        this.setupParserMiddlewares();
         this.httpServer = http.createServer(express);
 
         const ioAdapter = IoAdapter ? new IoAdapter(this.httpServer) : null;
@@ -49,6 +53,11 @@ export class NestApplication implements INestApplication {
         );
     }
 
+    public setupParserMiddlewares() {
+      this.express.use(bodyParser.json());
+      this.express.use(bodyParser.urlencoded({ extended: true }));
+    }
+
     public async setupModules() {
         SocketModule && SocketModule.setup(this.container, this.config);
 
@@ -56,7 +65,11 @@ export class NestApplication implements INestApplication {
           MicroservicesModule.setup(this.container, this.config);
           MicroservicesModule.setupClients(this.container);
         }
-        await MiddlewaresModule.setup(this.container, this.config);
+        await MiddlewaresModule.setup(
+          this.middlewaresContainer,
+          this.container,
+          this.config,
+        );
     }
 
     public async init() {
@@ -158,7 +171,7 @@ export class NestApplication implements INestApplication {
     }
 
     private async setupMiddlewares(instance) {
-        await MiddlewaresModule.setupMiddlewares(instance);
+        await MiddlewaresModule.setupMiddlewares(this.middlewaresContainer, instance);
     }
 
     private listenToPromise(microservice: INestMicroservice) {
diff --git a/src/core/router/router-execution-context.ts b/src/core/router/router-execution-context.ts
index 575044d68f9..427c600d1fc 100644
--- a/src/core/router/router-execution-context.ts
+++ b/src/core/router/router-execution-context.ts
@@ -45,7 +45,7 @@ export class RouterExecutionContext {
         const interceptors = this.interceptorsContextCreator.create(instance, callback, module);
         const httpCode = this.reflectHttpStatusCode(callback);
         const paramsMetadata = this.exchangeKeysForValues(keys, metadata);
-        const isResponseObj = paramsMetadata.some(({ type }) => type === RouteParamtypes.RESPONSE);
+        const isResponseHandled = paramsMetadata.some(({ type }) => type === RouteParamtypes.RESPONSE || type === RouteParamtypes.NEXT);
         const paramsOptions = this.mergeParamsMetatypes(paramsMetadata, paramtypes);
 
         return async (req, res, next) => {
@@ -68,7 +68,7 @@ export class RouterExecutionContext {
             const result = await this.interceptorsConsumer.intercept(
                 interceptors, req, instance, callback, handler,
             );
-            return !isResponseObj ?
+            return !isResponseHandled ?
                 this.responseController.apply(result, res, requestMethod, httpCode) :
                 undefined;
         };
diff --git a/src/core/test/injector/injector.spec.ts b/src/core/test/injector/injector.spec.ts
index 0d6f80a94fe..dccafde6152 100644
--- a/src/core/test/injector/injector.spec.ts
+++ b/src/core/test/injector/injector.spec.ts
@@ -163,7 +163,7 @@ describe('Injector', () => {
     describe('resolveSingleParam', () => {
         it('should throw "RuntimeException" when param is undefined', async () => {
             return expect(
-                injector.resolveSingleParam(null, undefined, null, []),
+                injector.resolveSingleParam(null, undefined, { index: 0, length: 5 }, null, []),
             ).to.eventually.be.rejected;
         });
     });
@@ -263,7 +263,7 @@ describe('Injector', () => {
                 has: () => true,
                 get: () => instance,
             };
-            const result = await injector.scanForComponent(collection as any, metatype.name, null, metatype);
+            const result = await injector.scanForComponent(collection as any, null, { name: metatype.name, index: 0, length: 10 }, metatype);
             expect(result).to.be.equal(instance);
         });
 
@@ -272,7 +272,7 @@ describe('Injector', () => {
             const collection = {
                 has: () => false,
             };
-            await injector.scanForComponent(collection as any, metatype.name, null, metatype);
+            await injector.scanForComponent(collection as any, null, { name: metatype.name, index: 0, length: 10 }, metatype);
             expect(scanForComponentInRelatedModules.called).to.be.true;
         });
 
@@ -283,7 +283,7 @@ describe('Injector', () => {
             };
             const module = { exports: collection };
             expect(
-                injector.scanForComponent(collection as any, metatype.name, module as any, { metatype }),
+                injector.scanForComponent(collection as any, module as any, { name: metatype.name, index: 0, length: 10 }, { metatype }),
             ).to.eventually.be.rejected;
         });
 
@@ -294,7 +294,7 @@ describe('Injector', () => {
             };
             const module = { exports: collection };
             expect(
-                injector.scanForComponent(collection as any, metatype.name, module as any, metatype),
+                injector.scanForComponent(collection as any, module as any, { name: metatype.name, index: 0, length: 10 }, metatype),
             ).to.eventually.be.not.rejected;
         });
 
@@ -389,24 +389,24 @@ describe('Injector', () => {
 
     describe('scanForComponentInScopes', () => {
         it('should returns null when component is not available in any scope', () => {
-            expect(injector.scanForComponentInScopes([], '', {})).to.eventually.be.null;
+            expect(injector.scanForComponentInScopes([], { name: '', index: 0, length: 10 }, {})).to.eventually.be.null;
         });
         it('should returns wrapper when component is available in any scope', () => {
             const component = 'test';
             sinon.stub(injector, 'scanForComponentInScope').returns(component);
-            expect(injector.scanForComponentInScopes([{}] as any, '', {})).to.eventually.be.eql(component);
+            expect(injector.scanForComponentInScopes([{}] as any, { name: '', index: 0, length: 10 }, {})).to.eventually.be.eql(component);
         });
     });
 
     describe('scanForComponentInScope', () => {
         it('should returns null when scope throws exception', () => {
             sinon.stub(injector, 'scanForComponent').throws('exception');
-            expect(injector.scanForComponentInScope({} as any, '', {})).to.eventually.be.null;
+            expect(injector.scanForComponentInScope({} as any, { name: '', index: 0, length: 10 }, {})).to.eventually.be.null;
         });
 
         it('should rethrow UndefinedDependencyException', () => {
-          sinon.stub(injector, 'scanForComponent').throws(new UndefinedDependencyException('type'));
-          expect(injector.scanForComponentInScope({} as any, '', {})).to.eventually.throw();
+          sinon.stub(injector, 'scanForComponent').throws(new UndefinedDependencyException('type', 0, 10));
+          expect(injector.scanForComponentInScope({} as any, { name: 'type', index: 0, length: 10 }, {})).to.eventually.throw();
         });
 
         describe('when instanceWrapper is not resolved and does not have forward ref', () => {
@@ -414,21 +414,21 @@ describe('Injector', () => {
             const loadStub = sinon.stub(injector, 'loadInstanceOfComponent').callsFake(() => null);
             sinon.stub(injector, 'scanForComponent').returns({ isResolved: false });
   
-            await injector.scanForComponentInScope([] as any, 'name', {} as any);
+            await injector.scanForComponentInScope([] as any, { name: 'name', index: 0, length: 10 }, {} as any);
             expect(loadStub.called).to.be.true;
           });
           it('should not call loadInstanceOfComponent (isResolved)', async () => {
             const loadStub = sinon.stub(injector, 'loadInstanceOfComponent').callsFake(() => null);
             sinon.stub(injector, 'scanForComponent').returns({ isResolved: true });
     
-            await injector.scanForComponentInScope([] as any, 'name', {} as any);
+            await injector.scanForComponentInScope([] as any, { name: 'name', index: 0, length: 10 }, {} as any);
             expect(loadStub.called).to.be.false;
           });
           it('should not call loadInstanceOfComponent (forwardRef)', async () => {
             const loadStub = sinon.stub(injector, 'loadInstanceOfComponent').callsFake(() => null);
             sinon.stub(injector, 'scanForComponent').returns({ isResolved: false, forwardRef: true });
   
-            await injector.scanForComponentInScope([] as any, 'name', {} as any);
+            await injector.scanForComponentInScope([] as any, { name: 'name', index: 0, length: 10 }, {} as any);
             expect(loadStub.called).to.be.false;
           });
         });
@@ -484,21 +484,21 @@ describe('Injector', () => {
           const loadStub = sinon.stub(injector, 'loadInstanceOfComponent').callsFake(() => null);
           sinon.stub(injector, 'scanForComponent').returns({ isResolved: false });
 
-          await injector.resolveComponentInstance(module, '', {} as any, []);
+          await injector.resolveComponentInstance(module, '', { index: 0, length: 10 }, {} as any, []);
           expect(loadStub.called).to.be.true;
         });
         it('should not call loadInstanceOfComponent (isResolved)', async () => {
           const loadStub = sinon.stub(injector, 'loadInstanceOfComponent').callsFake(() => null);
           sinon.stub(injector, 'scanForComponent').returns({ isResolved: true });
   
-          await injector.resolveComponentInstance(module, '', {} as any, []);
+          await injector.resolveComponentInstance(module, '', { index: 0, length: 10 }, {} as any, []);
           expect(loadStub.called).to.be.false;
         });
         it('should not call loadInstanceOfComponent (forwardRef)', async () => {
           const loadStub = sinon.stub(injector, 'loadInstanceOfComponent').callsFake(() => null);
           sinon.stub(injector, 'scanForComponent').returns({ isResolved: false, forwardRef: true });
 
-          await injector.resolveComponentInstance(module, '', {} as any, []);
+          await injector.resolveComponentInstance(module, '', { index: 0, length: 10 }, {} as any, []);
           expect(loadStub.called).to.be.false;
         });
       });
@@ -508,13 +508,13 @@ describe('Injector', () => {
           const loadStub = sinon.stub(injector, 'loadInstanceOfComponent').callsFake(() => null);
 
           const instance = Promise.resolve(true);
-          sinon.stub(injector, 'scanForComponent').returns({ 
-            isResolved: false, 
+          sinon.stub(injector, 'scanForComponent').returns({
+            isResolved: false,
             forwardRef: true,
             async: true,
             instance,
           });
-          const result = await injector.resolveComponentInstance(module, '', {} as any, []);
+          const result = await injector.resolveComponentInstance(module, '', { index: 0, length: 10 }, {} as any, []);
           expect(result.instance).to.be.true;
         });
       });
diff --git a/src/core/test/middlewares/middlewares-module.spec.ts b/src/core/test/middlewares/middlewares-module.spec.ts
index 3770634e3c2..2c348bd983f 100644
--- a/src/core/test/middlewares/middlewares-module.spec.ts
+++ b/src/core/test/middlewares/middlewares-module.spec.ts
@@ -12,6 +12,7 @@ import { RuntimeException } from '../../errors/exceptions/runtime.exception';
 import { RoutesMapper } from '../../middlewares/routes-mapper';
 import { RouterExceptionFilters } from '../../router/router-exception-filters';
 import { ApplicationConfig } from '../../application-config';
+import { MiddlewaresContainer } from "../../middlewares/container";
 
 describe('MiddlewaresModule', () => {
     @Controller('test')
@@ -48,7 +49,7 @@ describe('MiddlewaresModule', () => {
                 configure: configureSpy,
             };
 
-            MiddlewaresModule.loadConfiguration(mockModule as any, 'Test' as any);
+            MiddlewaresModule.loadConfiguration(new MiddlewaresContainer(), mockModule as any, 'Test' as any);
 
             expect(configureSpy.calledOnce).to.be.true;
             expect(configureSpy.calledWith(new MiddlewareBuilder(new RoutesMapper()))).to.be.true;
@@ -68,7 +69,7 @@ describe('MiddlewaresModule', () => {
             const app = { use: useSpy };
 
             expect(
-                MiddlewaresModule.setupRouteMiddleware(route as any, configuration, 'Test' as any, app as any),
+                MiddlewaresModule.setupRouteMiddleware(new MiddlewaresContainer(), route as any, configuration, 'Test' as any, app as any),
             ).to.eventually.be.rejectedWith(RuntimeException);
         });
 
@@ -85,7 +86,7 @@ describe('MiddlewaresModule', () => {
             const useSpy = sinon.spy();
             const app = { use: useSpy };
 
-            const container = MiddlewaresModule.getContainer();
+            const container = new MiddlewaresContainer();
             const moduleKey = 'Test' as any;
             container.addConfig([ configuration as any ], moduleKey);
 
@@ -96,7 +97,7 @@ describe('MiddlewaresModule', () => {
             } as any);
 
             expect(
-                MiddlewaresModule.setupRouteMiddleware(route as any, configuration, moduleKey, app as any),
+                MiddlewaresModule.setupRouteMiddleware(container, route as any, configuration, moduleKey, app as any),
             ).to.be.rejectedWith(InvalidMiddlewareException);
         });
 
@@ -112,7 +113,7 @@ describe('MiddlewaresModule', () => {
                 get: useSpy,
             };
 
-            const container = MiddlewaresModule.getContainer();
+            const container = new MiddlewaresContainer();
             const moduleKey = 'Test' as any;
             container.addConfig([ configuration ], moduleKey);
 
@@ -122,7 +123,7 @@ describe('MiddlewaresModule', () => {
                 instance,
             });
 
-            MiddlewaresModule.setupRouteMiddleware(route, configuration, moduleKey, app as any);
+            MiddlewaresModule.setupRouteMiddleware(container, route, configuration, moduleKey, app as any);
             expect(useSpy.calledOnce).to.be.true;
         });
 
diff --git a/src/testing/testing-module.ts b/src/testing/testing-module.ts
index 1753f3689cd..756ea12d53b 100644
--- a/src/testing/testing-module.ts
+++ b/src/testing/testing-module.ts
@@ -1,3 +1,4 @@
+import * as optional from 'optional';
 import { NestContainer, InstanceWrapper } from '@nestjs/core/injector/container';
 import { DependenciesScanner } from '@nestjs/core/scanner';
 import { MetadataScanner } from '@nestjs/core/metadata-scanner';
@@ -8,7 +9,10 @@ import { NestModuleMetatype } from '@nestjs/common/interfaces/modules/module-met
 import { UnknownModuleException } from './errors/unknown-module.exception';
 import { NestApplication } from '@nestjs/core';
 import { INestApplication, INestMicroservice } from '@nestjs/common';
-import { MicroserviceConfiguration, NestMicroservice } from '@nestjs/microservices';
+import { MicroserviceConfiguration } from '@nestjs/common/interfaces/microservices/microservice-configuration.interface';
+import { MicroservicesPackageNotFoundException } from '@nestjs/core/errors/exceptions/microservices-package-not-found.exception';
+
+const { NestMicroservice } = optional('@nestjs/microservices/nest-microservice') || {} as any;
 
 export class TestingModule {
     private readonly moduleTokenFactory = new ModuleTokenFactory();
@@ -23,6 +27,9 @@ export class TestingModule {
     }
 
     public createNestMicroservice(config: MicroserviceConfiguration): INestMicroservice {
+        if (!NestMicroservice) {
+            throw new MicroservicesPackageNotFoundException();
+        }
         return new NestMicroservice(this.container, config);
     }
 

From ada0b2ddf167b76070eac0e5e72347161158110d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Tue, 21 Nov 2017 13:59:33 +0100
Subject: [PATCH 10/34] Update CHANGELOG.md

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d2b9c2016f2..5f9c7235e01 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,5 @@
 ## 4.3.0
+- **common**: `ValidationPipe` is now available out-of-the-box
 - **core**: `json` and `urlencoded` (`body-parser`) middlewares are applied by default now, bugfix #252
 - **core** more informative error message (injector) #223
 example: `[ExceptionHandler] Nest can't resolve dependencies of the UsersService (+, +, ?, +, +, +). Please verify whether [2] argument is available in the current context.`

From 702324a2c7d174cff27dbf6cd6dcd9ea82be348e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Tue, 21 Nov 2017 14:00:36 +0100
Subject: [PATCH 11/34] Update lerna.json

---
 lerna.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lerna.json b/lerna.json
index 113d407abe9..53fbd36a5a9 100644
--- a/lerna.json
+++ b/lerna.json
@@ -3,5 +3,5 @@
   "packages": [
     "lib/*"
   ],
-  "version": "4.2.2"
+  "version": "4.3.0"
 }

From 7245cd5183d8c47d830baf51732c3c93a2c73aab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Tue, 21 Nov 2017 14:06:46 +0100
Subject: [PATCH 12/34] Update examples package.json

---
 examples/01-cats-app/package.json      | 10 +++++-----
 examples/02-gateways/package.json      | 10 +++++-----
 examples/03-microservices/package.json | 10 +++++-----
 examples/04-injector/package.json      | 10 +++++-----
 examples/05-sql-typeorm/package.json   | 10 +++++-----
 examples/06-mongoose/package.json      | 10 +++++-----
 examples/07-sequelize/package.json     | 10 +++++-----
 examples/08-passport/package.json      | 10 +++++-----
 examples/09-babel-example/package.json | 10 +++++-----
 9 files changed, 45 insertions(+), 45 deletions(-)

diff --git a/examples/01-cats-app/package.json b/examples/01-cats-app/package.json
index 0de0dacdee7..c8b55877d85 100644
--- a/examples/01-cats-app/package.json
+++ b/examples/01-cats-app/package.json
@@ -14,11 +14,11 @@
     "e2e:watch": "jest --watch --config=e2e/jest-e2e.json"
   },
   "dependencies": {
-    "@nestjs/common": "^4.0.1",
-    "@nestjs/core": "^4.0.1",
-    "@nestjs/microservices": "^4.0.1",
-    "@nestjs/testing": "^4.0.1",
-    "@nestjs/websockets": "^4.0.1",
+    "@nestjs/common": "^4.3.0",
+    "@nestjs/core": "^4.3.0",
+    "@nestjs/microservices": "^4.3.0",
+    "@nestjs/testing": "^4.3.0",
+    "@nestjs/websockets": "^4.3.0",
     "class-transformer": "^0.1.7",
     "class-validator": "^0.7.2",
     "redis": "^2.7.1",
diff --git a/examples/02-gateways/package.json b/examples/02-gateways/package.json
index f1227dea299..beb0e1b6da1 100644
--- a/examples/02-gateways/package.json
+++ b/examples/02-gateways/package.json
@@ -9,11 +9,11 @@
     "start:prod": "node dist/server.js"
   },
   "dependencies": {
-    "@nestjs/common": "^4.0.1",
-    "@nestjs/core": "^4.0.1",
-    "@nestjs/microservices": "^4.0.1",
-    "@nestjs/testing": "^4.0.1",
-    "@nestjs/websockets": "^4.0.1",
+    "@nestjs/common": "^4.3.0",
+    "@nestjs/core": "^4.3.0",
+    "@nestjs/microservices": "^4.3.0",
+    "@nestjs/testing": "^4.3.0",
+    "@nestjs/websockets": "^4.3.0",
     "class-transformer": "^0.1.7",
     "class-validator": "^0.7.2",
     "redis": "^2.7.1",
diff --git a/examples/03-microservices/package.json b/examples/03-microservices/package.json
index 2017d6bf167..1c5bba735d6 100644
--- a/examples/03-microservices/package.json
+++ b/examples/03-microservices/package.json
@@ -9,11 +9,11 @@
     "start:prod": "node dist/server.js"
   },
   "dependencies": {
-    "@nestjs/common": "^4.0.1",
-    "@nestjs/core": "^4.0.1",
-    "@nestjs/microservices": "^4.0.1",
-    "@nestjs/testing": "^4.0.1",
-    "@nestjs/websockets": "^4.0.1",
+    "@nestjs/common": "^4.3.0",
+    "@nestjs/core": "^4.3.0",
+    "@nestjs/microservices": "^4.3.0",
+    "@nestjs/testing": "^4.3.0",
+    "@nestjs/websockets": "^4.3.0",
     "amqplib": "^0.5.1",
     "class-transformer": "^0.1.7",
     "class-validator": "^0.7.2",
diff --git a/examples/04-injector/package.json b/examples/04-injector/package.json
index 9eb336071df..a83bc112dcb 100644
--- a/examples/04-injector/package.json
+++ b/examples/04-injector/package.json
@@ -9,11 +9,11 @@
     "start:prod": "node dist/server.js"
   },
   "dependencies": {
-    "@nestjs/common": "^4.0.1",
-    "@nestjs/core": "^4.0.1",
-    "@nestjs/microservices": "^4.0.1",
-    "@nestjs/testing": "^4.0.1",
-    "@nestjs/websockets": "^4.0.1",
+    "@nestjs/common": "^4.3.0",
+    "@nestjs/core": "^4.3.0",
+    "@nestjs/microservices": "^4.3.0",
+    "@nestjs/testing": "^4.3.0",
+    "@nestjs/websockets": "^4.3.0",
     "redis": "^2.7.1",
     "reflect-metadata": "^0.1.10",
     "rxjs": "^5.4.3",
diff --git a/examples/05-sql-typeorm/package.json b/examples/05-sql-typeorm/package.json
index 8ff753b1819..df5372d0852 100644
--- a/examples/05-sql-typeorm/package.json
+++ b/examples/05-sql-typeorm/package.json
@@ -9,11 +9,11 @@
     "start:prod": "node dist/server.js"
   },
   "dependencies": {
-    "@nestjs/common": "^4.0.1",
-    "@nestjs/core": "^4.0.1",
-    "@nestjs/microservices": "^4.0.1",
-    "@nestjs/testing": "^4.0.1",
-    "@nestjs/websockets": "^4.0.1",
+    "@nestjs/common": "^4.3.0",
+    "@nestjs/core": "^4.3.0",
+    "@nestjs/microservices": "^4.3.0",
+    "@nestjs/testing": "^4.3.0",
+    "@nestjs/websockets": "^4.3.0",
     "mysql": "^2.14.1",
     "redis": "^2.7.1",
     "reflect-metadata": "^0.1.10",
diff --git a/examples/06-mongoose/package.json b/examples/06-mongoose/package.json
index 58c9fa73f17..1be3e7c93fe 100644
--- a/examples/06-mongoose/package.json
+++ b/examples/06-mongoose/package.json
@@ -9,11 +9,11 @@
     "start:prod": "node dist/server.js"
   },
   "dependencies": {
-    "@nestjs/common": "^4.0.1",
-    "@nestjs/core": "^4.0.1",
-    "@nestjs/microservices": "^4.0.1",
-    "@nestjs/testing": "^4.0.1",
-    "@nestjs/websockets": "^4.0.1",
+    "@nestjs/common": "^4.3.0",
+    "@nestjs/core": "^4.3.0",
+    "@nestjs/microservices": "^4.3.0",
+    "@nestjs/testing": "^4.3.0",
+    "@nestjs/websockets": "^4.3.0",
     "mongoose": "^4.11.13",
     "redis": "^2.7.1",
     "reflect-metadata": "^0.1.10",
diff --git a/examples/07-sequelize/package.json b/examples/07-sequelize/package.json
index 3702ff8c1e4..ff0e712a828 100644
--- a/examples/07-sequelize/package.json
+++ b/examples/07-sequelize/package.json
@@ -9,11 +9,11 @@
     "start:prod": "node dist/server.js"
   },
   "dependencies": {
-    "@nestjs/common": "^4.0.1",
-    "@nestjs/core": "^4.0.1",
-    "@nestjs/microservices": "^4.0.1",
-    "@nestjs/testing": "^4.0.1",
-    "@nestjs/websockets": "^4.0.1",
+    "@nestjs/common": "^4.3.0",
+    "@nestjs/core": "^4.3.0",
+    "@nestjs/microservices": "^4.3.0",
+    "@nestjs/testing": "^4.3.0",
+    "@nestjs/websockets": "^4.3.0",
     "mysql2": "^1.4.2",
     "redis": "^2.7.1",
     "reflect-metadata": "^0.1.10",
diff --git a/examples/08-passport/package.json b/examples/08-passport/package.json
index 27a00946e47..09f7d65c2ec 100644
--- a/examples/08-passport/package.json
+++ b/examples/08-passport/package.json
@@ -9,11 +9,11 @@
     "start:prod": "node dist/server.js"
   },
   "dependencies": {
-    "@nestjs/common": "^4.0.1",
-    "@nestjs/core": "^4.0.1",
-    "@nestjs/microservices": "^4.0.1",
-    "@nestjs/testing": "^4.0.1",
-    "@nestjs/websockets": "^4.0.1",
+    "@nestjs/common": "^4.3.0",
+    "@nestjs/core": "^4.3.0",
+    "@nestjs/microservices": "^4.3.0",
+    "@nestjs/testing": "^4.3.0",
+    "@nestjs/websockets": "^4.3.0",
     "@types/passport-jwt": "^2.0.24",
     "jsonwebtoken": "^8.0.1",
     "passport": "^0.4.0",
diff --git a/examples/09-babel-example/package.json b/examples/09-babel-example/package.json
index 2c1a12e0c90..f60a2f54bce 100644
--- a/examples/09-babel-example/package.json
+++ b/examples/09-babel-example/package.json
@@ -9,11 +9,11 @@
     "start": "node index.js"
   },
   "dependencies": {
-    "@nestjs/common": "^4.0.1",
-    "@nestjs/core": "^4.0.1",
-    "@nestjs/microservices": "^4.0.1",
-    "@nestjs/testing": "^4.0.1",
-    "@nestjs/websockets": "^4.0.1",
+    "@nestjs/common": "^4.3.0",
+    "@nestjs/core": "^4.3.0",
+    "@nestjs/microservices": "^4.3.0",
+    "@nestjs/testing": "^4.3.0",
+    "@nestjs/websockets": "^4.3.0",
     "babel-core": "^6.26.0",
     "babel-polyfill": "^6.26.0",
     "body-parser": "^1.17.2",

From fb324886a4aa8c8f002d28e67294197904cc1905 Mon Sep 17 00:00:00 2001
From: Michael Yali 
Date: Tue, 21 Nov 2017 23:00:38 +0200
Subject: [PATCH 13/34] feature(@nest): custom params simplifying

---
 .../custom-route-param-reflector.interface.ts |  5 --
 .../interfaces/nest-application.interface.ts  | 10 ----
 .../reflect-route-param-metadata.spec.ts      | 19 +------
 .../reflect-route-param-metadata.decorator.ts | 21 ++-----
 src/core/application-config.ts                | 10 ----
 src/core/nest-application.ts                  |  5 --
 .../route-custom-params-factory.interface.ts  |  3 -
 .../router/route-custom-params-factory.ts     | 24 --------
 src/core/router/router-execution-context.ts   | 17 +++---
 src/core/router/router-explorer.ts            |  2 -
 src/core/test/application-config.spec.ts      |  8 ---
 .../route-custom-params.factory.spec.ts       | 56 -------------------
 .../router/router-execution-context.spec.ts   | 14 +++--
 13 files changed, 27 insertions(+), 167 deletions(-)
 delete mode 100644 src/core/router/interfaces/route-custom-params-factory.interface.ts
 delete mode 100644 src/core/router/route-custom-params-factory.ts
 delete mode 100644 src/core/test/router/route-custom-params.factory.spec.ts

diff --git a/src/common/interfaces/custom-route-param-reflector.interface.ts b/src/common/interfaces/custom-route-param-reflector.interface.ts
index 07a223def36..5084c453d8d 100644
--- a/src/common/interfaces/custom-route-param-reflector.interface.ts
+++ b/src/common/interfaces/custom-route-param-reflector.interface.ts
@@ -1,6 +1 @@
 export type CustomParamReflector = (data, req, res, next) => any;
-
-export interface ICustomParamReflector {
-  paramtype: number|string,
-  reflector: CustomParamReflector;
-}
\ No newline at end of file
diff --git a/src/common/interfaces/nest-application.interface.ts b/src/common/interfaces/nest-application.interface.ts
index cce19ad442e..0aa254de441 100644
--- a/src/common/interfaces/nest-application.interface.ts
+++ b/src/common/interfaces/nest-application.interface.ts
@@ -3,7 +3,6 @@ import { INestMicroservice, ExceptionFilter, PipeTransform } from './index';
 import { WebSocketAdapter } from './web-socket-adapter.interface';
 import { CanActivate } from './can-activate.interface';
 import { NestInterceptor } from './nest-interceptor.interface';
-import { ICustomParamReflector } from './custom-route-param-reflector.interface';
 
 export interface INestApplication {
     /**
@@ -117,15 +116,6 @@ export interface INestApplication {
      */
     useGlobalGuards(...guards: CanActivate[]);
 
-    /**
-     * Setups creating custom param decorators for controllers
-     * 
-     * @param {...ICustomParamReflector[]} decorators 
-     * @returns {*} 
-     * @memberof INestApplication
-     */
-    useCustomParamDecorators(...decorators: ICustomParamReflector[]): any;
-
     /**
      * Terminates the application (both NestApplication, Web Socket Gateways and every connected microservice)
      *
diff --git a/src/common/test/utils/reflect-route-param-metadata.spec.ts b/src/common/test/utils/reflect-route-param-metadata.spec.ts
index bb1bb8837d7..afca2a66003 100644
--- a/src/common/test/utils/reflect-route-param-metadata.spec.ts
+++ b/src/common/test/utils/reflect-route-param-metadata.spec.ts
@@ -12,24 +12,7 @@ describe('ReflectRouteParamDecorator', () => {
     reflector = (data, req, res, next) => true;
     result = ReflectRouteParamDecorator(reflector, key);
   });
-  it('should return an array', () => {
-    expect(result).to.be.an('array');
-  });
   it('should return a function as a first element', () => {
-    expect(result[0]).to.be.a('function');
-  });
-  it('should return reflector object as a second element', () => {
-    expect(result[1]).to.be.an('object');
-    expect(result[1]).to.have.property('paramtype');
-    expect(result[1]).to.have.property('reflector');
-    expect(result[1].reflector).to.be.eql(reflector);
-  });
-  it('should return paramtype with a key string', () => {
-    expect(result[1].paramtype).to.be.eql(`${key}${CUSTOM_ROUTE_AGRS_METADATA}`);
-  });
-  it('should return paramtype as a rundom string', () => {
-    result = ReflectRouteParamDecorator(reflector);
-    expect(result[1].paramtype).to.not.be.eql(`${key}${CUSTOM_ROUTE_AGRS_METADATA}`);
+    expect(result).to.be.a('function');
   });
 });
-
diff --git a/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts b/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts
index 67036961a8b..81faac356d4 100644
--- a/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts
+++ b/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts
@@ -1,16 +1,18 @@
 import { ROUTE_ARGS_METADATA, CUSTOM_ROUTE_AGRS_METADATA } from '../../constants';
-import { ICustomParamReflector, CustomParamReflector } from '../../interfaces/custom-route-param-reflector.interface';
+import { CustomParamReflector } from '../../interfaces/custom-route-param-reflector.interface';
 import { RouteParamsMetadata, ParamData } from './route-params.decorator';
 
 const assignCustomMetadata = (
   args: RouteParamsMetadata,
   paramtype: number|string,
   index: number,
+  reflector: CustomParamReflector,
   data?: ParamData,
 ) => ({
   ...args,
   [`${paramtype}${CUSTOM_ROUTE_AGRS_METADATA}:${index}`]: {
     index,
+    reflector,
     data,
   },
 });
@@ -25,26 +27,15 @@ const randomString = () => Math.random().toString(36).substring(2, 15);
 export const ReflectRouteParamDecorator = (
   reflector: CustomParamReflector,
   key: number|string = null,
-): [
-  (data?: ParamData) => ParameterDecorator,
-  ICustomParamReflector
-] => {
+) => {
   const paramtype = key === null ? randomString() + randomString() : key;
-  const decorator = (data?: ParamData): ParameterDecorator => (target, key, index) => {
+  return (data?: ParamData): ParameterDecorator => (target, key, index) => {
     const args = Reflect.getMetadata(ROUTE_ARGS_METADATA, target, key) || {};
     Reflect.defineMetadata(
       ROUTE_ARGS_METADATA,
-      assignCustomMetadata(args, paramtype, index, data),
+      assignCustomMetadata(args, paramtype, index, reflector, data),
       target,
       key,
     );
   };
-
-  return [
-    decorator,
-    {
-      paramtype: `${paramtype}${CUSTOM_ROUTE_AGRS_METADATA}`,
-      reflector,
-    },
-  ]
 };
diff --git a/src/core/application-config.ts b/src/core/application-config.ts
index 49a7acdf3ba..ba5e2710905 100644
--- a/src/core/application-config.ts
+++ b/src/core/application-config.ts
@@ -1,14 +1,12 @@
 import * as optional from 'optional';
 import { PipeTransform, WebSocketAdapter, ExceptionFilter, NestInterceptor, CanActivate } from '@nestjs/common';
 import { ConfigurationProvider } from '@nestjs/common/interfaces/configuration-provider.interface';
-import { ICustomParamReflector } from '@nestjs/common/interfaces/custom-route-param-reflector.interface';
 
 export class ApplicationConfig implements ConfigurationProvider {
     private globalPipes: PipeTransform[] = [];
     private globalFilters: ExceptionFilter[] = [];
     private globalInterceptors: NestInterceptor[] = [];
     private globalGuards: CanActivate[] = [];
-    private customParamDecorators: ICustomParamReflector[] = [];
     private globalPrefix = '';
 
     constructor(private ioAdapter: WebSocketAdapter | null = null) {}
@@ -60,12 +58,4 @@ export class ApplicationConfig implements ConfigurationProvider {
     public useGlobalGuards(...guards: CanActivate[]) {
         this.globalGuards = guards;
     }
-
-    public getCustomParamDecorators() {
-        return this.customParamDecorators;
-    }
-
-    public useCustomParamDecorators(...decorators: ICustomParamReflector[]) {
-        this.customParamDecorators = decorators;
-    }
 }
\ No newline at end of file
diff --git a/src/core/nest-application.ts b/src/core/nest-application.ts
index 419a502e28a..e30baf13f31 100644
--- a/src/core/nest-application.ts
+++ b/src/core/nest-application.ts
@@ -13,7 +13,6 @@ import { INestApplication, INestMicroservice, OnModuleInit } from '@nestjs/commo
 import { Logger } from '@nestjs/common/services/logger.service';
 import { isNil, isUndefined, validatePath } from '@nestjs/common/utils/shared.utils';
 import { MicroserviceConfiguration } from '@nestjs/common/interfaces/microservices/microservice-configuration.interface';
-import { ICustomParamReflector } from '@nestjs/common/interfaces/custom-route-param-reflector.interface';
 import { ExpressAdapter } from './adapters/express-adapter';
 import { ApplicationConfig } from './application-config';
 import { messages } from './constants';
@@ -158,10 +157,6 @@ export class NestApplication implements INestApplication {
         this.config.useGlobalGuards(...guards);
     }
 
-    public useCustomParamDecorators(...decorators: ICustomParamReflector[]) {
-        this.config.useCustomParamDecorators(...decorators);
-    }
-
     private async setupMiddlewares(instance) {
         await MiddlewaresModule.setupMiddlewares(instance);
     }
diff --git a/src/core/router/interfaces/route-custom-params-factory.interface.ts b/src/core/router/interfaces/route-custom-params-factory.interface.ts
deleted file mode 100644
index 1a2a5f5095c..00000000000
--- a/src/core/router/interfaces/route-custom-params-factory.interface.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export interface IRouteCustomParamsFactory {
-  exchangeKeyForValue(paramtype: number|string, data, { req, res, next });
-}
\ No newline at end of file
diff --git a/src/core/router/route-custom-params-factory.ts b/src/core/router/route-custom-params-factory.ts
deleted file mode 100644
index 8b54381f07b..00000000000
--- a/src/core/router/route-custom-params-factory.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { ApplicationConfig } from './../application-config';
-import { IRouteCustomParamsFactory } from './interfaces/route-custom-params-factory.interface';
-
-export class RouteCustomParamsFactory implements IRouteCustomParamsFactory {
-  constructor(private readonly config?: ApplicationConfig) {}
-
-  public exchangeKeyForValue(paramtype, data, { req, res, next }) {
-    const customParamDecorators = this.config && this.config.getCustomParamDecorators();
-    if (customParamDecorators) {
-      const decorator = customParamDecorators.find((one) => one.paramtype === paramtype);
-      if (decorator && decorator.reflector) {
-        try {
-          return decorator.reflector(data, req, res, next);
-        } catch (error) {
-          return null;
-        }
-      }
-
-      return null;
-    }
-
-    return null;
-  }
-}
\ No newline at end of file
diff --git a/src/core/router/router-execution-context.ts b/src/core/router/router-execution-context.ts
index 582ea9459c5..f6cdcc63ded 100644
--- a/src/core/router/router-execution-context.ts
+++ b/src/core/router/router-execution-context.ts
@@ -1,11 +1,10 @@
 import 'reflect-metadata';
 import { ROUTE_ARGS_METADATA, PARAMTYPES_METADATA, HTTP_CODE_METADATA, CUSTOM_ROUTE_AGRS_METADATA } from '@nestjs/common/constants';
-import { isUndefined } from '@nestjs/common/utils/shared.utils';
+import { isUndefined, isFunction } from '@nestjs/common/utils/shared.utils';
 import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum';
 import { Controller, Transform } from '@nestjs/common/interfaces';
 import { RouteParamsMetadata } from '@nestjs/common/utils';
 import { IRouteParamsFactory } from './interfaces/route-params-factory.interface';
-import { IRouteCustomParamsFactory } from './interfaces/route-custom-params-factory.interface';
 import { PipesContextCreator } from './../pipes/pipes-context-creator';
 import { PipesConsumer } from './../pipes/pipes-consumer';
 import { ParamData, PipeTransform, HttpStatus, RequestMethod } from '@nestjs/common';
@@ -29,7 +28,6 @@ export class RouterExecutionContext {
     private readonly responseController = new RouterResponseController();
     constructor(
         private readonly paramsFactory: IRouteParamsFactory,
-        private readonly customParamsFactory: IRouteCustomParamsFactory,
         private readonly pipesContextCreator: PipesContextCreator,
         private readonly pipesConsumer: PipesConsumer,
         private readonly guardsContextCreator: GuardsContextCreator,
@@ -112,13 +110,18 @@ export class RouterExecutionContext {
             let type, extractValue;
 
             if (key.includes(CUSTOM_ROUTE_AGRS_METADATA)) {
+                const { reflector } = metadata[key];
                 type = this.mapCustomParamType(key);
-                extractValue = (req, res, next) => this.customParamsFactory.exchangeKeyForValue(type, data, { req, res, next });
-            } else {
-                type = this.mapParamType(key);
-                extractValue = (req, res, next) => this.paramsFactory.exchangeKeyForValue(type, data, { req, res, next });
+                extractValue = (req, res, next) => !isUndefined(reflector) && isFunction(reflector)
+                    ? reflector(data, req, res, next)
+                    : () => {};
+
+                return { index, extractValue, type, data, pipes };
             }
 
+            type = this.mapParamType(key);
+            extractValue = (req, res, next) => this.paramsFactory.exchangeKeyForValue(type, data, { req, res, next });
+
             return { index, extractValue, type, data, pipes };
         });
     }
diff --git a/src/core/router/router-explorer.ts b/src/core/router/router-explorer.ts
index 635933e0676..4cba4ec87fc 100644
--- a/src/core/router/router-explorer.ts
+++ b/src/core/router/router-explorer.ts
@@ -13,7 +13,6 @@ import { RouteMappedMessage } from '../helpers/messages';
 import { RouterExecutionContext } from './router-execution-context';
 import { ExceptionsFilter } from './interfaces/exceptions-filter.interface';
 import { RouteParamsFactory } from './route-params-factory';
-import { RouteCustomParamsFactory } from './route-custom-params-factory';
 import { RouterExplorer } from './interfaces/explorer.inteface';
 import { MetadataScanner } from '../metadata-scanner';
 import { ApplicationConfig } from './../application-config';
@@ -40,7 +39,6 @@ export class ExpressRouterExplorer implements RouterExplorer {
 
         this.executionContextCreator = new RouterExecutionContext(
             new RouteParamsFactory(),
-            new RouteCustomParamsFactory(config),
             new PipesContextCreator(config),
             new PipesConsumer(),
             new GuardsContextCreator(container, config),
diff --git a/src/core/test/application-config.spec.ts b/src/core/test/application-config.spec.ts
index 13207ca2728..908ae3145eb 100644
--- a/src/core/test/application-config.spec.ts
+++ b/src/core/test/application-config.spec.ts
@@ -58,12 +58,4 @@ describe('ApplicationConfig', () => {
       expect(appConfig.getGlobalInterceptors()).to.be.eql(interceptors);
     });
   });
-  describe('Custom Param Decorators', () => {
-    it('should set and get custom param decorators', () => {
-      const decorators = ['test', 'test2'];
-      appConfig.useCustomParamDecorators(...decorators as any);
-
-      expect(appConfig.getCustomParamDecorators()).to.be.eql(decorators);
-    });
-  });
 });
\ No newline at end of file
diff --git a/src/core/test/router/route-custom-params.factory.spec.ts b/src/core/test/router/route-custom-params.factory.spec.ts
deleted file mode 100644
index 410f49c2cbd..00000000000
--- a/src/core/test/router/route-custom-params.factory.spec.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { expect } from 'chai';
-import { RouteCustomParamsFactory } from '../../router/route-custom-params-factory';
-import { ICustomParamReflector } from '../../../common/interfaces/custom-route-param-reflector.interface';
-import { ApplicationConfig } from '../../application-config';
-
-describe('RouteCustomParamsFactory', () => {
-    let factory: RouteCustomParamsFactory;
-    let config: ApplicationConfig;
-    beforeEach(() => {
-        config = new ApplicationConfig();
-        factory = new RouteCustomParamsFactory(config);
-    });
-    describe('exchangeKeyForValue', () => {
-        const res = {};
-        const next = () => ({});
-        const req = {
-            session: null,
-            body: {
-                foo: 'bar',
-            },
-            headers: {
-                foo: 'bar',
-            },
-            params: {
-                foo: 'bar',
-            },
-            query: {
-                foo: 'bar',
-            },
-        };
-        const args = ['key', null, { req, res, next }];
-        it('should return null if config is nil', () => {
-            let factory2 = new RouteCustomParamsFactory();
-            expect((factory2 as any).exchangeKeyForValue(...args)).to.be.eql(null);
-        });
-        it('should return null if no custom decorators found', () => {
-            expect((factory as any).exchangeKeyForValue(...args)).to.be.eql(null);
-        });
-        it('should return null is reflector throws an error', () => {
-            const reflector = {
-                paramtype: 'key',
-                reflector: (data, req, res, next) => { throw new Error },
-            } as ICustomParamReflector;
-            config.useCustomParamDecorators(reflector);
-            expect((factory as any).exchangeKeyForValue(...args)).to.be.eql(null);
-        });
-        it('should return reflector result', () => {
-            const reflector = {
-                paramtype: 'key',
-                reflector: (data, req, res, next) => true,
-            } as ICustomParamReflector;
-            config.useCustomParamDecorators(reflector);
-            expect((factory as any).exchangeKeyForValue(...args)).to.be.eql(true);
-        });
-    });
-});
\ No newline at end of file
diff --git a/src/core/test/router/router-execution-context.spec.ts b/src/core/test/router/router-execution-context.spec.ts
index fa37c482fbf..c3782cc6c3a 100644
--- a/src/core/test/router/router-execution-context.spec.ts
+++ b/src/core/test/router/router-execution-context.spec.ts
@@ -6,7 +6,6 @@ import { ReflectRouteParamDecorator } from '../../../common/utils/decorators/ref
 import { RouterExecutionContext } from '../../router/router-execution-context';
 import { RouteParamsMetadata, Request, Body } from '../../../index';
 import { RouteParamsFactory } from '../../router/route-params-factory';
-import { RouteCustomParamsFactory } from '../../router/route-custom-params-factory';
 import { PipesContextCreator } from '../../pipes/pipes-context-creator';
 import { PipesConsumer } from '../../pipes/pipes-consumer';
 import { ApplicationConfig } from '../../application-config';
@@ -36,7 +35,7 @@ describe('RouterExecutionContext', () => {
         consumer = new PipesConsumer();
 
         contextCreator = new RouterExecutionContext(
-            factory, new RouteCustomParamsFactory(new ApplicationConfig()), new PipesContextCreator(new ApplicationConfig()), consumer,
+            factory, new PipesContextCreator(new ApplicationConfig()), consumer,
             new GuardsContextCreator(new NestContainer()), new GuardsConsumer(),
             new InterceptorsContextCreator(new NestContainer()), new InterceptorsConsumer(),
         );
@@ -107,13 +106,15 @@ describe('RouterExecutionContext', () => {
         });
     });
     describe('reflectCallbackMetadata', () => {
-        const [ CustomDecorator ] = ReflectRouteParamDecorator(() => {}, 'custom');
+        const CustomDecorator = ReflectRouteParamDecorator(() => {}, 'custom');
         class TestController {
             public callback(@Request() req, @Body() body, @CustomDecorator() custom) {}
         }
         it('should returns ROUTE_ARGS_METADATA callback metadata', () => {
             const instance = new TestController();
             const metadata = contextCreator.reflectCallbackMetadata(instance, 'callback');
+            console.log(metadata);
+            
             const expectedMetadata = {
                 [`${RouteParamtypes.REQUEST}:0`]: {
                     index: 0,
@@ -127,10 +128,15 @@ describe('RouterExecutionContext', () => {
                 },
                 [`custom${CUSTOM_ROUTE_AGRS_METADATA}:2`]: {
                     index: 2,
+                    reflector: (() => {}).toString(),
                     data: undefined,
                 },
             };
-            expect(metadata).to.deep.equal(expectedMetadata);
+            expect(metadata[`${RouteParamtypes.REQUEST}:0`]).to.deep.equal(expectedMetadata[`${RouteParamtypes.REQUEST}:0`]);
+            expect(metadata[`${RouteParamtypes.REQUEST}:1`]).to.deep.equal(expectedMetadata[`${RouteParamtypes.REQUEST}:1`]);
+            expect(metadata[`custom${CUSTOM_ROUTE_AGRS_METADATA}:2`].index).to.be.eq(2);
+            expect(metadata[`custom${CUSTOM_ROUTE_AGRS_METADATA}:2`].data).to.be.eq(undefined);
+            expect(metadata[`custom${CUSTOM_ROUTE_AGRS_METADATA}:2`].reflector).to.be.a('function');
         });
     });
     describe('getArgumentsLength', () => {

From 813796c171095c2d191e8dae809e1e766a626a13 Mon Sep 17 00:00:00 2001
From: Michael Yali 
Date: Tue, 21 Nov 2017 23:09:20 +0200
Subject: [PATCH 14/34] feature(@nest): custom params - test fix

---
 src/core/test/router/router-execution-context.spec.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/core/test/router/router-execution-context.spec.ts b/src/core/test/router/router-execution-context.spec.ts
index c3782cc6c3a..ea94c8d3500 100644
--- a/src/core/test/router/router-execution-context.spec.ts
+++ b/src/core/test/router/router-execution-context.spec.ts
@@ -128,7 +128,7 @@ describe('RouterExecutionContext', () => {
                 },
                 [`custom${CUSTOM_ROUTE_AGRS_METADATA}:2`]: {
                     index: 2,
-                    reflector: (() => {}).toString(),
+                    reflector: () => {},
                     data: undefined,
                 },
             };

From 098ac7975d875c2615c4dc424604c01491263812 Mon Sep 17 00:00:00 2001
From: Michael Yali 
Date: Tue, 21 Nov 2017 23:23:24 +0200
Subject: [PATCH 15/34] feature(@nest): custom params update

---
 src/common/interfaces/custom-route-param-reflector.interface.ts | 2 +-
 src/core/router/router-execution-context.ts                     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/common/interfaces/custom-route-param-reflector.interface.ts b/src/common/interfaces/custom-route-param-reflector.interface.ts
index 5084c453d8d..a89d2e439e6 100644
--- a/src/common/interfaces/custom-route-param-reflector.interface.ts
+++ b/src/common/interfaces/custom-route-param-reflector.interface.ts
@@ -1 +1 @@
-export type CustomParamReflector = (data, req, res, next) => any;
+export type CustomParamReflector = (data, req) => any;
diff --git a/src/core/router/router-execution-context.ts b/src/core/router/router-execution-context.ts
index f6cdcc63ded..49b48e95b9d 100644
--- a/src/core/router/router-execution-context.ts
+++ b/src/core/router/router-execution-context.ts
@@ -113,7 +113,7 @@ export class RouterExecutionContext {
                 const { reflector } = metadata[key];
                 type = this.mapCustomParamType(key);
                 extractValue = (req, res, next) => !isUndefined(reflector) && isFunction(reflector)
-                    ? reflector(data, req, res, next)
+                    ? reflector(data, req)
                     : () => {};
 
                 return { index, extractValue, type, data, pipes };

From fd3d745e6df9195bb73f79d2f3578545ee36c22a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Tue, 21 Nov 2017 23:44:48 +0100
Subject: [PATCH 16/34] update(@nestjs) update to 4.3.3 version

---
 CHANGELOG.md                                  |  7 ++-
 .../common/exceptions/forbidden.exception.ts  |  2 +-
 .../common/filters/http-exception.filter.ts   |  2 +-
 .../interceptors/exception.interceptor.ts     |  2 +-
 .../modules/common/pipes/parse-int.pipe.ts    |  2 +-
 .../modules/common/pipes/validation.pipe.ts   |  2 +-
 lerna.json                                    |  2 +-
 package.json                                  |  3 +-
 .../exceptions/bad-gateway.exception.ts       | 12 +++++
 .../exceptions/bad-request.exception.ts       | 12 +++++
 src/common/exceptions/conflict.exception.ts   | 12 +++++
 src/common/exceptions/forbidden.exception.ts  | 12 +++++
 .../exceptions/gateway-timeout.exception.ts   | 12 +++++
 src/common/exceptions/gone.exception.ts       | 12 +++++
 src/common/exceptions/http.exception.ts       | 28 ++++++++++
 src/common/exceptions/index.ts                | 18 +++++++
 .../internal-server-error.exception.ts        | 12 +++++
 .../method-not-allowed.exception.ts           | 12 +++++
 .../exceptions/not-acceptable.exception.ts    | 12 +++++
 src/common/exceptions/not-found.exception.ts  | 12 +++++
 .../exceptions/not-implemented.exception.ts   | 12 +++++
 .../exceptions/payload-too-large.exception.ts | 12 +++++
 .../exceptions/request-timeout.exception.ts   | 12 +++++
 .../service-unavailable.exception.ts          | 12 +++++
 .../exceptions/unauthorized.exception.ts      | 12 +++++
 .../unprocessable-entity.exception.ts         | 12 +++++
 .../unsupported-media-type.exception.ts       | 12 +++++
 src/common/index.ts                           |  3 +-
 src/common/pipes/index.ts                     |  3 +-
 src/common/pipes/parse-int.pipe.ts            | 14 +++++
 src/common/pipes/validation.pipe.ts           | 13 ++---
 src/common/test/pipes/parse-int.pipe.spec.ts  | 27 ++++++++++
 src/common/test/pipes/validation.pipe.spec.ts |  9 +---
 .../test/utils/module.decorator.spec.ts       |  2 +-
 .../decorators}/exceptions/constants.ts       |  0
 .../invalid-module-config.exception.ts        |  0
 .../utils/decorators/module.decorator.ts      |  2 +-
 src/common/utils/http-exception-body.util.ts  |  8 +++
 src/core/exceptions/exceptions-handler.ts     |  5 +-
 src/core/exceptions/http-exception.ts         | 54 +++++++++++--------
 src/core/guards/guards-consumer.ts            |  1 -
 .../interceptors/interceptors-consumer.ts     |  1 -
 src/core/router/router-execution-context.ts   |  3 +-
 src/index.ts                                  |  1 -
 44 files changed, 359 insertions(+), 59 deletions(-)
 create mode 100644 src/common/exceptions/bad-gateway.exception.ts
 create mode 100644 src/common/exceptions/bad-request.exception.ts
 create mode 100644 src/common/exceptions/conflict.exception.ts
 create mode 100644 src/common/exceptions/forbidden.exception.ts
 create mode 100644 src/common/exceptions/gateway-timeout.exception.ts
 create mode 100644 src/common/exceptions/gone.exception.ts
 create mode 100644 src/common/exceptions/http.exception.ts
 create mode 100644 src/common/exceptions/index.ts
 create mode 100644 src/common/exceptions/internal-server-error.exception.ts
 create mode 100644 src/common/exceptions/method-not-allowed.exception.ts
 create mode 100644 src/common/exceptions/not-acceptable.exception.ts
 create mode 100644 src/common/exceptions/not-found.exception.ts
 create mode 100644 src/common/exceptions/not-implemented.exception.ts
 create mode 100644 src/common/exceptions/payload-too-large.exception.ts
 create mode 100644 src/common/exceptions/request-timeout.exception.ts
 create mode 100644 src/common/exceptions/service-unavailable.exception.ts
 create mode 100644 src/common/exceptions/unauthorized.exception.ts
 create mode 100644 src/common/exceptions/unprocessable-entity.exception.ts
 create mode 100644 src/common/exceptions/unsupported-media-type.exception.ts
 create mode 100644 src/common/pipes/parse-int.pipe.ts
 create mode 100644 src/common/test/pipes/parse-int.pipe.spec.ts
 rename src/common/{ => utils/decorators}/exceptions/constants.ts (100%)
 rename src/common/{ => utils/decorators}/exceptions/invalid-module-config.exception.ts (100%)
 create mode 100644 src/common/utils/http-exception-body.util.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5f9c7235e01..9831dd6c4ac 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
+## 4.3.3
+- **common**: `ParseIntPipe` is now available out-of-the-box (`@nestjs/common`)
+- **common**: package contains a set of useful HTTP exceptions now, such as `ForbiddenException`, `UnauthorizedException`, `BadRequestException` etc
+- **core**: `HttpException` was moved to `@nestjs/common`. This one from `core` packages is now DEPRECATED and will be removed in the next MAJOR release
+
 ## 4.3.0
-- **common**: `ValidationPipe` is now available out-of-the-box
+- **common**: `ValidationPipe` is now available out-of-the-box (`@nestjs/common`)
 - **core**: `json` and `urlencoded` (`body-parser`) middlewares are applied by default now, bugfix #252
 - **core** more informative error message (injector) #223
 example: `[ExceptionHandler] Nest can't resolve dependencies of the UsersService (+, +, ?, +, +, +). Please verify whether [2] argument is available in the current context.`
diff --git a/examples/01-cats-app/src/modules/common/exceptions/forbidden.exception.ts b/examples/01-cats-app/src/modules/common/exceptions/forbidden.exception.ts
index 5636f830df6..d615a19a63d 100644
--- a/examples/01-cats-app/src/modules/common/exceptions/forbidden.exception.ts
+++ b/examples/01-cats-app/src/modules/common/exceptions/forbidden.exception.ts
@@ -1,4 +1,4 @@
-import { HttpException } from '@nestjs/core';
+import { HttpException } from '@nestjs/common';
 import { HttpStatus } from '@nestjs/common';
 
 export class ForbiddenException extends HttpException {
diff --git a/examples/01-cats-app/src/modules/common/filters/http-exception.filter.ts b/examples/01-cats-app/src/modules/common/filters/http-exception.filter.ts
index 6bb0253be27..489ea32dd8b 100644
--- a/examples/01-cats-app/src/modules/common/filters/http-exception.filter.ts
+++ b/examples/01-cats-app/src/modules/common/filters/http-exception.filter.ts
@@ -1,5 +1,5 @@
 import { ExceptionFilter, Catch } from '@nestjs/common';
-import { HttpException } from '@nestjs/core';
+import { HttpException } from '@nestjs/common';
 
 @Catch(HttpException)
 export class HttpExceptionFilter implements ExceptionFilter {
diff --git a/examples/01-cats-app/src/modules/common/interceptors/exception.interceptor.ts b/examples/01-cats-app/src/modules/common/interceptors/exception.interceptor.ts
index 6cd10a627e4..d9c462f5232 100644
--- a/examples/01-cats-app/src/modules/common/interceptors/exception.interceptor.ts
+++ b/examples/01-cats-app/src/modules/common/interceptors/exception.interceptor.ts
@@ -1,5 +1,5 @@
 import { Interceptor, NestInterceptor, ExecutionContext, HttpStatus } from '@nestjs/common';
-import { HttpException } from '@nestjs/core';
+import { HttpException } from '@nestjs/common';
 import { Observable } from 'rxjs/Observable';
 import 'rxjs/add/operator/catch';
 import 'rxjs/add/observable/throw';
diff --git a/examples/01-cats-app/src/modules/common/pipes/parse-int.pipe.ts b/examples/01-cats-app/src/modules/common/pipes/parse-int.pipe.ts
index 0e388a0b634..8406be8954e 100644
--- a/examples/01-cats-app/src/modules/common/pipes/parse-int.pipe.ts
+++ b/examples/01-cats-app/src/modules/common/pipes/parse-int.pipe.ts
@@ -1,4 +1,4 @@
-import { HttpException } from '@nestjs/core';
+import { HttpException } from '@nestjs/common';
 import { PipeTransform, Pipe, ArgumentMetadata, HttpStatus } from '@nestjs/common';
 
 @Pipe()
diff --git a/examples/01-cats-app/src/modules/common/pipes/validation.pipe.ts b/examples/01-cats-app/src/modules/common/pipes/validation.pipe.ts
index 0ca74954aa0..b0e140f4d53 100644
--- a/examples/01-cats-app/src/modules/common/pipes/validation.pipe.ts
+++ b/examples/01-cats-app/src/modules/common/pipes/validation.pipe.ts
@@ -1,4 +1,4 @@
-import { HttpException } from '@nestjs/core';
+import { HttpException } from '@nestjs/common';
 import { PipeTransform, Pipe, ArgumentMetadata, HttpStatus } from '@nestjs/common';
 import { validate } from 'class-validator';
 import { plainToClass } from 'class-transformer';
diff --git a/lerna.json b/lerna.json
index 53fbd36a5a9..40e1b61b4cf 100644
--- a/lerna.json
+++ b/lerna.json
@@ -3,5 +3,5 @@
   "packages": [
     "lib/*"
   ],
-  "version": "4.3.0"
+  "version": "4.3.3"
 }
diff --git a/package.json b/package.json
index a01da74889f..b20644f30b8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "nestjs",
-  "version": "4.3.0",
+  "version": "4.3.3",
   "description": "Modern, fast, powerful node.js web framework",
   "main": "index.js",
   "scripts": {
@@ -88,6 +88,7 @@
       "src/websockets/adapters/*.ts",
       "src/core/nest-application.ts",
       "src/core/nest-factory.ts",
+      "src/common/exceptions/*.ts",
       "src/common/services/logger.service.ts",
       "src/core/errors/exceptions",
       "src/microservices/exceptions/",
diff --git a/src/common/exceptions/bad-gateway.exception.ts b/src/common/exceptions/bad-gateway.exception.ts
new file mode 100644
index 00000000000..91fb4b96029
--- /dev/null
+++ b/src/common/exceptions/bad-gateway.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class BadGatewayException extends HttpException {
+	constructor(message?: string | object | any, error = 'Bad Gateway') {
+		super(
+			createHttpExceptionBody(message, error, HttpStatus.BAD_GATEWAY),
+			HttpStatus.BAD_GATEWAY,
+		);
+	}
+}
diff --git a/src/common/exceptions/bad-request.exception.ts b/src/common/exceptions/bad-request.exception.ts
new file mode 100644
index 00000000000..e068ebdeab6
--- /dev/null
+++ b/src/common/exceptions/bad-request.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class BadRequestException extends HttpException {
+	constructor(message?: string | object | any, error = 'Bad Request') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.BAD_REQUEST),
+			HttpStatus.BAD_REQUEST,
+		);
+	}
+}
diff --git a/src/common/exceptions/conflict.exception.ts b/src/common/exceptions/conflict.exception.ts
new file mode 100644
index 00000000000..74769326dfe
--- /dev/null
+++ b/src/common/exceptions/conflict.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class ConflictException extends HttpException {
+	constructor(message?: string | object | any, error = 'Conflict') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.CONFLICT),
+			HttpStatus.CONFLICT,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/forbidden.exception.ts b/src/common/exceptions/forbidden.exception.ts
new file mode 100644
index 00000000000..510d196e0ef
--- /dev/null
+++ b/src/common/exceptions/forbidden.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class ForbiddenException extends HttpException {
+  constructor(message?: string | object | any, error = 'Forbidden') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.FORBIDDEN),
+			HttpStatus.FORBIDDEN,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/gateway-timeout.exception.ts b/src/common/exceptions/gateway-timeout.exception.ts
new file mode 100644
index 00000000000..4061bdd134d
--- /dev/null
+++ b/src/common/exceptions/gateway-timeout.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class GatewayTimeoutException extends HttpException {
+  constructor(message?: string | object | any, error = 'Gateway Timeout') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.GATEWAY_TIMEOUT),
+			HttpStatus.GATEWAY_TIMEOUT,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/gone.exception.ts b/src/common/exceptions/gone.exception.ts
new file mode 100644
index 00000000000..d7b13789539
--- /dev/null
+++ b/src/common/exceptions/gone.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class GoneException extends HttpException {
+  constructor(message?: string | object | any, error = 'Gone') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.GONE),
+			HttpStatus.GONE,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/http.exception.ts b/src/common/exceptions/http.exception.ts
new file mode 100644
index 00000000000..7e6b0527662
--- /dev/null
+++ b/src/common/exceptions/http.exception.ts
@@ -0,0 +1,28 @@
+export class HttpException {
+  /**
+   * The base Nest Application exception, which is handled by the default Exceptions Handler.
+   * If you throw an exception from your HTTP route handlers, Nest will map them to the appropriate HTTP response and send to the client.
+   *
+   * When `response` is an object:
+   * - object will be stringified and returned to the user as a JSON response,
+   *
+   * When `response` is a string:
+   * - Nest will create a response with two properties:
+   * ```
+   * message: response,
+   * statusCode: X
+   * ```
+   */
+  constructor(
+      private readonly response: string | object,
+      private readonly status: number,
+  ) {}
+
+  public getResponse(): string | object {
+      return this.response;
+  }
+
+  public getStatus(): number {
+      return this.status;
+  }
+}
diff --git a/src/common/exceptions/index.ts b/src/common/exceptions/index.ts
new file mode 100644
index 00000000000..edaea318b96
--- /dev/null
+++ b/src/common/exceptions/index.ts
@@ -0,0 +1,18 @@
+export * from './bad-request.exception';
+export * from './http.exception';
+export * from './unauthorized.exception';
+export * from './method-not-allowed.exception';
+export * from './not-found.exception';
+export * from './forbidden.exception';
+export * from './not-acceptable.exception';
+export * from './request-timeout.exception';
+export * from './conflict.exception';
+export * from './gone.exception';
+export * from './payload-too-large.exception';
+export * from './unsupported-media-type.exception';
+export * from './unprocessable-entity.exception';
+export * from './internal-server-error.exception';
+export * from './not-implemented.exception';
+export * from './bad-gateway.exception';
+export * from './service-unavailable.exception';
+export * from './gateway-timeout.exception';
\ No newline at end of file
diff --git a/src/common/exceptions/internal-server-error.exception.ts b/src/common/exceptions/internal-server-error.exception.ts
new file mode 100644
index 00000000000..0fe6fbe830c
--- /dev/null
+++ b/src/common/exceptions/internal-server-error.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class InternalServerErrorException extends HttpException {
+  constructor(message?: string | object | any, error = 'Internal Server Error') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.INTERNAL_SERVER_ERROR),
+			HttpStatus.INTERNAL_SERVER_ERROR,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/method-not-allowed.exception.ts b/src/common/exceptions/method-not-allowed.exception.ts
new file mode 100644
index 00000000000..6418a233a02
--- /dev/null
+++ b/src/common/exceptions/method-not-allowed.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class MethodNotAllowedException extends HttpException {
+  constructor(message?: string | object | any, error = 'Method Not Allowed') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.METHOD_NOT_ALLOWED),
+			HttpStatus.METHOD_NOT_ALLOWED,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/not-acceptable.exception.ts b/src/common/exceptions/not-acceptable.exception.ts
new file mode 100644
index 00000000000..ad263171e20
--- /dev/null
+++ b/src/common/exceptions/not-acceptable.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class NotAcceptableException extends HttpException {
+  constructor(message?: string | object | any, error = 'Not Acceptable') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.NOT_ACCEPTABLE),
+			HttpStatus.NOT_ACCEPTABLE,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/not-found.exception.ts b/src/common/exceptions/not-found.exception.ts
new file mode 100644
index 00000000000..e293f6fd6e1
--- /dev/null
+++ b/src/common/exceptions/not-found.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class NotFoundException extends HttpException {
+  constructor(message?: string | object | any, error = 'Not Found') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.NOT_FOUND),
+			HttpStatus.NOT_FOUND,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/not-implemented.exception.ts b/src/common/exceptions/not-implemented.exception.ts
new file mode 100644
index 00000000000..faf426606b2
--- /dev/null
+++ b/src/common/exceptions/not-implemented.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class NotImplementedException extends HttpException {
+  constructor(message?: string | object | any, error = 'Not Implemented') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.NOT_IMPLEMENTED),
+			HttpStatus.NOT_IMPLEMENTED,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/payload-too-large.exception.ts b/src/common/exceptions/payload-too-large.exception.ts
new file mode 100644
index 00000000000..3f3d1078fdb
--- /dev/null
+++ b/src/common/exceptions/payload-too-large.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class PayloadTooLargeException extends HttpException {
+  constructor(message?: string | object | any, error = 'Payload Too Large') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.PAYLOAD_TOO_LARGE),
+			HttpStatus.PAYLOAD_TOO_LARGE,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/request-timeout.exception.ts b/src/common/exceptions/request-timeout.exception.ts
new file mode 100644
index 00000000000..ee4941e7865
--- /dev/null
+++ b/src/common/exceptions/request-timeout.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class RequestTimeoutException extends HttpException {
+  constructor(message?: string | object | any, error = 'Request Timeout') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.REQUEST_TIMEOUT),
+			HttpStatus.REQUEST_TIMEOUT,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/service-unavailable.exception.ts b/src/common/exceptions/service-unavailable.exception.ts
new file mode 100644
index 00000000000..a4569c17a3e
--- /dev/null
+++ b/src/common/exceptions/service-unavailable.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class ServiceUnavailableException extends HttpException {
+  constructor(message?: string | object | any, error = 'Service Unavailable') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.SERVICE_UNAVAILABLE),
+			HttpStatus.SERVICE_UNAVAILABLE,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/unauthorized.exception.ts b/src/common/exceptions/unauthorized.exception.ts
new file mode 100644
index 00000000000..92d63bbd14c
--- /dev/null
+++ b/src/common/exceptions/unauthorized.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class UnauthorizedException extends HttpException {
+  constructor(message?: string | object | any, error = 'Unauthorized') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.UNAUTHORIZED),
+			HttpStatus.UNAUTHORIZED,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/unprocessable-entity.exception.ts b/src/common/exceptions/unprocessable-entity.exception.ts
new file mode 100644
index 00000000000..9114b5aceb9
--- /dev/null
+++ b/src/common/exceptions/unprocessable-entity.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class UnprocessableEntityException extends HttpException {
+  constructor(message?: string | object | any, error = 'Unprocessable Entity') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.UNPROCESSABLE_ENTITY),
+			HttpStatus.UNPROCESSABLE_ENTITY,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/exceptions/unsupported-media-type.exception.ts b/src/common/exceptions/unsupported-media-type.exception.ts
new file mode 100644
index 00000000000..536b5c80f6f
--- /dev/null
+++ b/src/common/exceptions/unsupported-media-type.exception.ts
@@ -0,0 +1,12 @@
+import { HttpException } from './http.exception';
+import { HttpStatus } from '../enums/http-status.enum';
+import { createHttpExceptionBody } from './../utils/http-exception-body.util';
+
+export class UnsupportedMediaTypeException extends HttpException {
+  constructor(message?: string | object | any, error = 'Unsupported Media Type') {
+    super(
+			createHttpExceptionBody(message, error, HttpStatus.UNSUPPORTED_MEDIA_TYPE),
+			HttpStatus.UNSUPPORTED_MEDIA_TYPE,
+		);
+	}
+}
\ No newline at end of file
diff --git a/src/common/index.ts b/src/common/index.ts
index bb9d10aaf7b..25243a13d45 100644
--- a/src/common/index.ts
+++ b/src/common/index.ts
@@ -29,5 +29,6 @@ export {
     WsExceptionFilter,
     NestInterceptor,
 } from './interfaces';
+export * from './services/logger.service';
 export * from './pipes';
-export * from './services/logger.service';
\ No newline at end of file
+export * from './exceptions';
\ No newline at end of file
diff --git a/src/common/pipes/index.ts b/src/common/pipes/index.ts
index 978bc67ad7c..a8bd608e789 100644
--- a/src/common/pipes/index.ts
+++ b/src/common/pipes/index.ts
@@ -1 +1,2 @@
-export * from './validation.pipe';
\ No newline at end of file
+export * from './validation.pipe';
+export * from './parse-int.pipe';
\ No newline at end of file
diff --git a/src/common/pipes/parse-int.pipe.ts b/src/common/pipes/parse-int.pipe.ts
new file mode 100644
index 00000000000..5171854d62e
--- /dev/null
+++ b/src/common/pipes/parse-int.pipe.ts
@@ -0,0 +1,14 @@
+import { BadRequestException } from '../exceptions/bad-request.exception';
+import { PipeTransform } from '../interfaces/pipe-transform.interface';
+import { Pipe, ArgumentMetadata } from '../index';
+
+@Pipe()
+export class ParseIntPipe implements PipeTransform {
+  public async transform(value: string, metadata: ArgumentMetadata) {
+    const val = parseInt(value, 10);
+    if (isNaN(val)) {
+      throw new BadRequestException('Validation failed');
+    }
+    return val;
+  }
+}
\ No newline at end of file
diff --git a/src/common/pipes/validation.pipe.ts b/src/common/pipes/validation.pipe.ts
index 1ac8c5ee4f3..a2cc3a7d4cf 100644
--- a/src/common/pipes/validation.pipe.ts
+++ b/src/common/pipes/validation.pipe.ts
@@ -1,12 +1,7 @@
-import { HttpException } from '@nestjs/core';
-import {
-	PipeTransform,
-	Pipe,
-	ArgumentMetadata,
-	HttpStatus,
-} from '@nestjs/common';
 import { validate } from 'class-validator';
 import { plainToClass } from 'class-transformer';
+import { PipeTransform } from '../interfaces/pipe-transform.interface';
+import { Pipe, ArgumentMetadata, BadRequestException } from '../index';
 
 @Pipe()
 export class ValidationPipe implements PipeTransform {
@@ -18,9 +13,9 @@ export class ValidationPipe implements PipeTransform {
 		const entity = plainToClass(metatype, value);
 		const errors = await validate(entity);
 		if (errors.length > 0) {
-			throw new HttpException('Validation failed', HttpStatus.BAD_REQUEST);
+			throw new BadRequestException(errors);
 		}
-		return entity;
+		return value;
 	}
 
 	private toValidate(metatype): boolean {
diff --git a/src/common/test/pipes/parse-int.pipe.spec.ts b/src/common/test/pipes/parse-int.pipe.spec.ts
new file mode 100644
index 00000000000..e1ce281bb0e
--- /dev/null
+++ b/src/common/test/pipes/parse-int.pipe.spec.ts
@@ -0,0 +1,27 @@
+import * as sinon from 'sinon';
+import { expect } from 'chai';
+import { ArgumentMetadata } from './../../interfaces';
+import { ParseIntPipe } from './../../pipes/parse-int.pipe';
+
+describe('ParseIntPipe', () => {
+	let target: ParseIntPipe;
+	beforeEach(() => {
+		target = new ParseIntPipe();
+	});
+	describe('transform', () => {
+		describe('when validation passes', () => {
+			it('should return number', async () => {
+				const num = '3';
+				expect(await target.transform(num, {} as any)).to.equal(
+					parseInt(num, 10),
+				);
+			});
+		});
+		describe('when validation vails', () => {
+			it('should throw an error', async () => {
+				return expect(target.transform('notanumber!', {} as any)).to.be
+					.rejected;
+			});
+		});
+	});
+});
diff --git a/src/common/test/pipes/validation.pipe.spec.ts b/src/common/test/pipes/validation.pipe.spec.ts
index e841b8214ef..a8c55369672 100644
--- a/src/common/test/pipes/validation.pipe.spec.ts
+++ b/src/common/test/pipes/validation.pipe.spec.ts
@@ -22,7 +22,7 @@ describe('ValidationPipe', () => {
 		target = new ValidationPipe();
 	});
 	describe('transform', () => {
-		describe('when metadata is empty or undefined', () => {
+		describe('when validation passes', () => {
 			it('should return the value unchanged', async () => {
 				const testObj = { prop1: 'value1', prop2: 'value2' };
 				expect(await target.transform(testObj, {} as any)).to.equal(testObj);
@@ -31,13 +31,6 @@ describe('ValidationPipe', () => {
 				);
 			});
 		});
-		describe('when metadata contains a class', () => {
-			it('should return an instance of the class', async () => {
-				const testObj = { prop1: 'value1', prop2: 'value2' };
-				const result = await target.transform(testObj, metadata);
-				expect(result).to.be.instanceOf(TestModel);
-			});
-		});
 		describe('when validation vails', () => {
 			it('should throw an error', async () => {
 				const testObj = { prop1: 'value1' };
diff --git a/src/common/test/utils/module.decorator.spec.ts b/src/common/test/utils/module.decorator.spec.ts
index 6d23bb1cfaf..3041135dde4 100644
--- a/src/common/test/utils/module.decorator.spec.ts
+++ b/src/common/test/utils/module.decorator.spec.ts
@@ -1,7 +1,7 @@
 import 'reflect-metadata';
 import { expect } from 'chai';
 import { Module } from '../../utils/decorators/module.decorator';
-import { InvalidModuleConfigException } from '../../exceptions/invalid-module-config.exception';
+import { InvalidModuleConfigException } from '../../utils/decorators/exceptions/invalid-module-config.exception';
 
 describe('@Module', () => {
     const moduleProps = {
diff --git a/src/common/exceptions/constants.ts b/src/common/utils/decorators/exceptions/constants.ts
similarity index 100%
rename from src/common/exceptions/constants.ts
rename to src/common/utils/decorators/exceptions/constants.ts
diff --git a/src/common/exceptions/invalid-module-config.exception.ts b/src/common/utils/decorators/exceptions/invalid-module-config.exception.ts
similarity index 100%
rename from src/common/exceptions/invalid-module-config.exception.ts
rename to src/common/utils/decorators/exceptions/invalid-module-config.exception.ts
diff --git a/src/common/utils/decorators/module.decorator.ts b/src/common/utils/decorators/module.decorator.ts
index 0cf89958c08..a1b8751e1c0 100644
--- a/src/common/utils/decorators/module.decorator.ts
+++ b/src/common/utils/decorators/module.decorator.ts
@@ -1,6 +1,6 @@
 import 'reflect-metadata';
 import { ModuleMetadata } from '../../interfaces/modules/module-metadata.interface';
-import { InvalidModuleConfigException } from '../../exceptions/invalid-module-config.exception';
+import { InvalidModuleConfigException } from './exceptions/invalid-module-config.exception';
 import { metadata } from '../../constants';
 
 const metadataKeys = [
diff --git a/src/common/utils/http-exception-body.util.ts b/src/common/utils/http-exception-body.util.ts
new file mode 100644
index 00000000000..2d5809d12d2
--- /dev/null
+++ b/src/common/utils/http-exception-body.util.ts
@@ -0,0 +1,8 @@
+export const createHttpExceptionBody = (
+	message: any,
+	error: string,
+	status: number,
+) =>
+	message
+		? { statusCode: status, error, message }
+		: { statusCode: status, error };
diff --git a/src/core/exceptions/exceptions-handler.ts b/src/core/exceptions/exceptions-handler.ts
index 1ab306ba1f9..88b6f1217d7 100644
--- a/src/core/exceptions/exceptions-handler.ts
+++ b/src/core/exceptions/exceptions-handler.ts
@@ -1,9 +1,10 @@
-import { HttpException } from './http-exception';
+import { HttpException as DeprecatedHttpException } from './http-exception';
 import { messages } from '../constants';
 import { Logger } from '@nestjs/common';
 import { ExceptionFilterMetadata } from '@nestjs/common/interfaces/exceptions/exception-filter-metadata.interface';
 import { isEmpty, isObject } from '@nestjs/common/utils/shared.utils';
 import { InvalidExceptionFilterException } from '../errors/exceptions/invalid-exception-filter.exception';
+import { HttpException } from '@nestjs/common';
 
 export class ExceptionsHandler {
     private static readonly logger = new Logger(ExceptionsHandler.name);
@@ -12,7 +13,7 @@ export class ExceptionsHandler {
     public next(exception: Error | HttpException | any, response) {
         if (this.invokeCustomFilters(exception, response)) return;
 
-        if (!(exception instanceof HttpException)) {
+        if (!(exception instanceof HttpException || exception instanceof DeprecatedHttpException)) {
             response.status(500).json({
                 statusCode: 500,
                 message: messages.UNKNOWN_EXCEPTION_MESSAGE,
diff --git a/src/core/exceptions/http-exception.ts b/src/core/exceptions/http-exception.ts
index 15ad1b864b1..a6057e9577a 100644
--- a/src/core/exceptions/http-exception.ts
+++ b/src/core/exceptions/http-exception.ts
@@ -1,27 +1,35 @@
+import { Logger } from '@nestjs/common';
+
 export class HttpException {
-    /**
-     * The base Nest Application exception, which is handled by the default Exceptions Handler.
-     * If you throw an exception from your HTTP route handlers, Nest will map them to the appropriate HTTP response and send to the client.
-     *
-     * When `response` is an object:
-     * - object will be stringified and returned to the user as a JSON response,
-     *
-     * When `response` is a string:
-     * - Nest will create a response with two properties:
-     * ```
-     * message: response,
-     * statusCode: X
-     * ```
-     */
-    constructor(
-        private readonly response: string | object,
-        private readonly status: number) {}
+  private readonly logger = new Logger(HttpException.name);
+
+  /**
+   * The base Nest Application exception, which is handled by the default Exceptions Handler.
+   * If you throw an exception from your HTTP route handlers, Nest will map them to the appropriate HTTP response and send to the client.
+   *
+   * When `response` is an object:
+   * - object will be stringified and returned to the user as a JSON response,
+   *
+   * When `response` is a string:
+   * - Nest will create a response with two properties:
+   * ```
+   * message: response,
+   * statusCode: X
+   * ```
+   * @deprecated
+   */
+  constructor(
+      private readonly response: string | object,
+      private readonly status: number,
+  ) {
+      this.logger.warn('DEPRECATED! Since version [4.3.2] HttpException class was moved to the @nestjs/common package!');
+  }
 
-    public getResponse(): string | object {
-        return this.response;
-    }
+  public getResponse(): string | object {
+      return this.response;
+  }
 
-    public getStatus(): number {
-        return this.status;
-    }
+  public getStatus(): number {
+      return this.status;
+  }
 }
diff --git a/src/core/guards/guards-consumer.ts b/src/core/guards/guards-consumer.ts
index caad16e3f23..7ac769e4a00 100644
--- a/src/core/guards/guards-consumer.ts
+++ b/src/core/guards/guards-consumer.ts
@@ -4,7 +4,6 @@ import { isUndefined, isFunction, isNil, isEmpty } from '@nestjs/common/utils/sh
 import { Controller } from '@nestjs/common/interfaces';
 import { CanActivate, HttpStatus, ExecutionContext } from '@nestjs/common';
 import { Observable } from 'rxjs/Observable';
-import { HttpException } from '../index';
 import { FORBIDDEN_MESSAGE } from './constants';
 import 'rxjs/add/operator/toPromise';
 
diff --git a/src/core/interceptors/interceptors-consumer.ts b/src/core/interceptors/interceptors-consumer.ts
index 03bc09a77d7..01dcb87157f 100644
--- a/src/core/interceptors/interceptors-consumer.ts
+++ b/src/core/interceptors/interceptors-consumer.ts
@@ -4,7 +4,6 @@ import { isUndefined, isFunction, isNil, isEmpty } from '@nestjs/common/utils/sh
 import { Controller } from '@nestjs/common/interfaces';
 import { HttpStatus, ExecutionContext, NestInterceptor } from '@nestjs/common';
 import { Observable } from 'rxjs/Observable';
-import { HttpException } from '../index';
 import 'rxjs/add/operator/toPromise';
 import 'rxjs/add/observable/defer';
 import 'rxjs/add/operator/take';
diff --git a/src/core/router/router-execution-context.ts b/src/core/router/router-execution-context.ts
index 427c600d1fc..441bb5b571f 100644
--- a/src/core/router/router-execution-context.ts
+++ b/src/core/router/router-execution-context.ts
@@ -7,11 +7,10 @@ import { RouteParamsMetadata } from '@nestjs/common/utils';
 import { IRouteParamsFactory } from './interfaces/route-params-factory.interface';
 import { PipesContextCreator } from './../pipes/pipes-context-creator';
 import { PipesConsumer } from './../pipes/pipes-consumer';
-import { ParamData, PipeTransform, HttpStatus, RequestMethod } from '@nestjs/common';
+import { ParamData, PipeTransform, HttpStatus, RequestMethod, HttpException } from '@nestjs/common';
 import { GuardsContextCreator } from '../guards/guards-context-creator';
 import { GuardsConsumer } from '../guards/guards-consumer';
 import { FORBIDDEN_MESSAGE } from '../guards/constants';
-import { HttpException } from '../index';
 import { RouterResponseController } from './router-response-controller';
 import { InterceptorsContextCreator } from '../interceptors/interceptors-context-creator';
 import { InterceptorsConsumer } from '../interceptors/interceptors-consumer';
diff --git a/src/index.ts b/src/index.ts
index 4a40fe9281c..ad72ba367fb 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -6,6 +6,5 @@
  */
 
 export * from './common';
-export * from './core';
 export * from './core/nest-factory';
 export * from './core/nest-application';
\ No newline at end of file

From 6a8facd77e7091bc6b65eb8dee3c0623e31bf57f Mon Sep 17 00:00:00 2001
From: Michael Yali 
Date: Wed, 22 Nov 2017 10:23:09 +0200
Subject: [PATCH 17/34] feature(@nest): custorm params update

---
 .../custom-route-param-factory.interface.ts   |  1 +
 .../custom-route-param-reflector.interface.ts |  1 -
 src/common/interfaces/index.ts                |  2 +-
 ...ts => create-route-param-metadata.spec.ts} |  4 ++--
 ... create-route-param-metadata.decorator.ts} | 17 +++++++---------
 src/common/utils/index.ts                     |  2 +-
 src/core/router/router-execution-context.ts   | 20 +++++++------------
 .../router/router-execution-context.spec.ts   | 17 ++++++++++------
 8 files changed, 30 insertions(+), 34 deletions(-)
 create mode 100644 src/common/interfaces/custom-route-param-factory.interface.ts
 delete mode 100644 src/common/interfaces/custom-route-param-reflector.interface.ts
 rename src/common/test/utils/{reflect-route-param-metadata.spec.ts => create-route-param-metadata.spec.ts} (70%)
 rename src/common/utils/decorators/{reflect-route-param-metadata.decorator.ts => create-route-param-metadata.decorator.ts} (61%)

diff --git a/src/common/interfaces/custom-route-param-factory.interface.ts b/src/common/interfaces/custom-route-param-factory.interface.ts
new file mode 100644
index 00000000000..534d39e7601
--- /dev/null
+++ b/src/common/interfaces/custom-route-param-factory.interface.ts
@@ -0,0 +1 @@
+export type CustomParamFactory = (data, req) => any;
diff --git a/src/common/interfaces/custom-route-param-reflector.interface.ts b/src/common/interfaces/custom-route-param-reflector.interface.ts
deleted file mode 100644
index a89d2e439e6..00000000000
--- a/src/common/interfaces/custom-route-param-reflector.interface.ts
+++ /dev/null
@@ -1 +0,0 @@
-export type CustomParamReflector = (data, req) => any;
diff --git a/src/common/interfaces/index.ts b/src/common/interfaces/index.ts
index a134c700801..82f8cc0169c 100644
--- a/src/common/interfaces/index.ts
+++ b/src/common/interfaces/index.ts
@@ -20,4 +20,4 @@ export * from './exceptions/rpc-exception-filter.interface';
 export * from './exceptions/ws-exception-filter.interface';
 export * from './execution-context.interface';
 export * from './nest-interceptor.interface';
-export * from './custom-route-param-reflector.interface';
\ No newline at end of file
+export * from './custom-route-param-factory.interface';
\ No newline at end of file
diff --git a/src/common/test/utils/reflect-route-param-metadata.spec.ts b/src/common/test/utils/create-route-param-metadata.spec.ts
similarity index 70%
rename from src/common/test/utils/reflect-route-param-metadata.spec.ts
rename to src/common/test/utils/create-route-param-metadata.spec.ts
index afca2a66003..fb6ede15444 100644
--- a/src/common/test/utils/reflect-route-param-metadata.spec.ts
+++ b/src/common/test/utils/create-route-param-metadata.spec.ts
@@ -1,5 +1,5 @@
 import { expect } from 'chai';
-import { ReflectRouteParamDecorator } from '../../utils/decorators/reflect-route-param-metadata.decorator';
+import { createRouteParamDecorator } from '../../utils/decorators/create-route-param-metadata.decorator';
 import { CUSTOM_ROUTE_AGRS_METADATA } from '../../constants';
 
 describe('ReflectRouteParamDecorator', () => {
@@ -10,7 +10,7 @@ describe('ReflectRouteParamDecorator', () => {
   beforeEach(() => {
     key = 'key';
     reflector = (data, req, res, next) => true;
-    result = ReflectRouteParamDecorator(reflector, key);
+    result = createRouteParamDecorator(reflector);
   });
   it('should return a function as a first element', () => {
     expect(result).to.be.a('function');
diff --git a/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts b/src/common/utils/decorators/create-route-param-metadata.decorator.ts
similarity index 61%
rename from src/common/utils/decorators/reflect-route-param-metadata.decorator.ts
rename to src/common/utils/decorators/create-route-param-metadata.decorator.ts
index 81faac356d4..688fea6caf6 100644
--- a/src/common/utils/decorators/reflect-route-param-metadata.decorator.ts
+++ b/src/common/utils/decorators/create-route-param-metadata.decorator.ts
@@ -1,18 +1,18 @@
 import { ROUTE_ARGS_METADATA, CUSTOM_ROUTE_AGRS_METADATA } from '../../constants';
-import { CustomParamReflector } from '../../interfaces/custom-route-param-reflector.interface';
+import { CustomParamFactory } from '../../interfaces/custom-route-param-factory.interface';
 import { RouteParamsMetadata, ParamData } from './route-params.decorator';
 
 const assignCustomMetadata = (
   args: RouteParamsMetadata,
   paramtype: number|string,
   index: number,
-  reflector: CustomParamReflector,
+  factory: CustomParamFactory,
   data?: ParamData,
 ) => ({
   ...args,
-  [`${paramtype}${CUSTOM_ROUTE_AGRS_METADATA}:${index}`]: {
+  [`${index}:${paramtype}${CUSTOM_ROUTE_AGRS_METADATA}:${index}`]: {
     index,
-    reflector,
+    factory,
     data,
   },
 });
@@ -24,16 +24,13 @@ const randomString = () => Math.random().toString(36).substring(2, 15);
  * @param reflector 
  * @param key 
  */
-export const ReflectRouteParamDecorator = (
-  reflector: CustomParamReflector,
-  key: number|string = null,
-) => {
-  const paramtype = key === null ? randomString() + randomString() : key;
+export const createRouteParamDecorator = (factory: CustomParamFactory) => {
+  const paramtype = randomString() + randomString();
   return (data?: ParamData): ParameterDecorator => (target, key, index) => {
     const args = Reflect.getMetadata(ROUTE_ARGS_METADATA, target, key) || {};
     Reflect.defineMetadata(
       ROUTE_ARGS_METADATA,
-      assignCustomMetadata(args, paramtype, index, reflector, data),
+      assignCustomMetadata(args, paramtype, index, factory, data),
       target,
       key,
     );
diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts
index 87b58ccfb76..18616b85e30 100644
--- a/src/common/utils/index.ts
+++ b/src/common/utils/index.ts
@@ -16,4 +16,4 @@ export * from './decorators/use-interceptors.decorator';
 export * from './decorators/http-code.decorator';
 export * from './decorators/bind.decorator';
 export * from './forward-ref.util';
-export * from './decorators/reflect-route-param-metadata.decorator';
\ No newline at end of file
+export * from './decorators/create-route-param-metadata.decorator';
\ No newline at end of file
diff --git a/src/core/router/router-execution-context.ts b/src/core/router/router-execution-context.ts
index 49b48e95b9d..efcb9866c39 100644
--- a/src/core/router/router-execution-context.ts
+++ b/src/core/router/router-execution-context.ts
@@ -74,16 +74,11 @@ export class RouterExecutionContext {
         };
     }
 
-    public mapParamType(key: string): RouteParamtypes {
+    public mapParamType(key: string): RouteParamtypes | number {
         const keyPair = key.split(':');
         return Number(keyPair[0]);
     }
 
-    public mapCustomParamType(key: string) {
-        const keyPair = key.split(':');
-        return keyPair[0];
-    }
-
     public reflectCallbackMetadata(instance: Controller, methodName: string): RouteParamsMetadata {
         return Reflect.getMetadata(ROUTE_ARGS_METADATA, instance, methodName);
     }
@@ -107,19 +102,18 @@ export class RouterExecutionContext {
     public exchangeKeysForValues(keys: string[], metadata: RouteParamsMetadata): ParamProperties[] {
         return keys.map(key => {
             const { index, data, pipes } = metadata[key];
-            let type, extractValue;
+            const type = this.mapParamType(key);
+            let extractValue;
 
             if (key.includes(CUSTOM_ROUTE_AGRS_METADATA)) {
-                const { reflector } = metadata[key];
-                type = this.mapCustomParamType(key);
-                extractValue = (req, res, next) => !isUndefined(reflector) && isFunction(reflector)
-                    ? reflector(data, req)
-                    : () => {};
+                const { factory } = metadata[key];
+
+                extractValue = !isUndefined(factory) && isFunction(factory)
+                    ? (req, res, next) => factory(data, req) : () => ({});
 
                 return { index, extractValue, type, data, pipes };
             }
 
-            type = this.mapParamType(key);
             extractValue = (req, res, next) => this.paramsFactory.exchangeKeyForValue(type, data, { req, res, next });
 
             return { index, extractValue, type, data, pipes };
diff --git a/src/core/test/router/router-execution-context.spec.ts b/src/core/test/router/router-execution-context.spec.ts
index ea94c8d3500..d2347cb8b37 100644
--- a/src/core/test/router/router-execution-context.spec.ts
+++ b/src/core/test/router/router-execution-context.spec.ts
@@ -2,7 +2,7 @@ import * as sinon from 'sinon';
 import { expect } from 'chai';
 import { RouteParamtypes } from '../../../common/enums/route-paramtypes.enum';
 import { CUSTOM_ROUTE_AGRS_METADATA } from '../../../common/constants';
-import { ReflectRouteParamDecorator } from '../../../common/utils/decorators/reflect-route-param-metadata.decorator';
+import { createRouteParamDecorator } from '../../../common/utils/decorators/create-route-param-metadata.decorator';
 import { RouterExecutionContext } from '../../router/router-execution-context';
 import { RouteParamsMetadata, Request, Body } from '../../../index';
 import { RouteParamsFactory } from '../../router/route-params-factory';
@@ -106,7 +106,7 @@ describe('RouterExecutionContext', () => {
         });
     });
     describe('reflectCallbackMetadata', () => {
-        const CustomDecorator = ReflectRouteParamDecorator(() => {}, 'custom');
+        const CustomDecorator = createRouteParamDecorator(() => {});
         class TestController {
             public callback(@Request() req, @Body() body, @CustomDecorator() custom) {}
         }
@@ -128,15 +128,20 @@ describe('RouterExecutionContext', () => {
                 },
                 [`custom${CUSTOM_ROUTE_AGRS_METADATA}:2`]: {
                     index: 2,
-                    reflector: () => {},
+                    factory: () => {},
                     data: undefined,
                 },
             };
             expect(metadata[`${RouteParamtypes.REQUEST}:0`]).to.deep.equal(expectedMetadata[`${RouteParamtypes.REQUEST}:0`]);
             expect(metadata[`${RouteParamtypes.REQUEST}:1`]).to.deep.equal(expectedMetadata[`${RouteParamtypes.REQUEST}:1`]);
-            expect(metadata[`custom${CUSTOM_ROUTE_AGRS_METADATA}:2`].index).to.be.eq(2);
-            expect(metadata[`custom${CUSTOM_ROUTE_AGRS_METADATA}:2`].data).to.be.eq(undefined);
-            expect(metadata[`custom${CUSTOM_ROUTE_AGRS_METADATA}:2`].reflector).to.be.a('function');
+
+            const keys = Object.keys(metadata);
+            const custom = keys.find((key) => key.includes(CUSTOM_ROUTE_AGRS_METADATA));
+
+            expect(metadata[custom]).to.be.an('object');
+            expect(metadata[custom].index).to.be.eq(2);
+            expect(metadata[custom].data).to.be.eq(undefined);
+            expect(metadata[custom].factory).to.be.a('function');
         });
     });
     describe('getArgumentsLength', () => {

From ae7676ed3952c90a805c1ef27488fc89faf5b928 Mon Sep 17 00:00:00 2001
From: Michael Yali 
Date: Wed, 22 Nov 2017 10:25:58 +0200
Subject: [PATCH 18/34] feature(@nest): custom params update tests

---
 src/common/test/utils/create-route-param-metadata.spec.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/common/test/utils/create-route-param-metadata.spec.ts b/src/common/test/utils/create-route-param-metadata.spec.ts
index fb6ede15444..b28cec148a0 100644
--- a/src/common/test/utils/create-route-param-metadata.spec.ts
+++ b/src/common/test/utils/create-route-param-metadata.spec.ts
@@ -2,7 +2,7 @@ import { expect } from 'chai';
 import { createRouteParamDecorator } from '../../utils/decorators/create-route-param-metadata.decorator';
 import { CUSTOM_ROUTE_AGRS_METADATA } from '../../constants';
 
-describe('ReflectRouteParamDecorator', () => {
+describe('createRouteParamDecorator', () => {
   let key;
   let reflector;
   let result;

From f6e18f16a18d2e7086e3d4e414823bffa56b5487 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Wed, 22 Nov 2017 20:13:05 +0100
Subject: [PATCH 19/34] update(@nestjs/core) adjust code style

---
 src/common/constants.ts                       |  1 +
 .../custom-route-param-factory.interface.ts   |  1 +
 src/common/interfaces/index.ts                |  3 +-
 .../utils/create-route-param-metadata.spec.ts | 18 +++++++++
 .../create-route-param-metadata.decorator.ts  | 37 +++++++++++++++++++
 src/common/utils/index.ts                     |  3 +-
 src/core/router/router-execution-context.ts   | 16 ++++++--
 .../router/router-execution-context.spec.ts   | 31 ++++++++++++----
 8 files changed, 97 insertions(+), 13 deletions(-)
 create mode 100644 src/common/interfaces/custom-route-param-factory.interface.ts
 create mode 100644 src/common/test/utils/create-route-param-metadata.spec.ts
 create mode 100644 src/common/utils/decorators/create-route-param-metadata.decorator.ts

diff --git a/src/common/constants.ts b/src/common/constants.ts
index 4ab5c2e9db0..4ad5a879681 100644
--- a/src/common/constants.ts
+++ b/src/common/constants.ts
@@ -11,6 +11,7 @@ export const PARAMTYPES_METADATA = 'design:paramtypes';
 export const SELF_DECLARED_DEPS_METADATA = 'self:paramtypes';
 export const METHOD_METADATA = 'method';
 export const ROUTE_ARGS_METADATA = '__routeArguments__';
+export const CUSTOM_ROUTE_AGRS_METADATA = '__customRouteArgs__';
 export const EXCEPTION_FILTERS_METADATA = '__exceptionFilters__';
 export const FILTER_CATCH_EXCEPTIONS = '__filterCatchExceptions__';
 export const PIPES_METADATA = '__pipes__';
diff --git a/src/common/interfaces/custom-route-param-factory.interface.ts b/src/common/interfaces/custom-route-param-factory.interface.ts
new file mode 100644
index 00000000000..534d39e7601
--- /dev/null
+++ b/src/common/interfaces/custom-route-param-factory.interface.ts
@@ -0,0 +1 @@
+export type CustomParamFactory = (data, req) => any;
diff --git a/src/common/interfaces/index.ts b/src/common/interfaces/index.ts
index a0129eba36b..82f8cc0169c 100644
--- a/src/common/interfaces/index.ts
+++ b/src/common/interfaces/index.ts
@@ -19,4 +19,5 @@ export * from './can-activate.interface';
 export * from './exceptions/rpc-exception-filter.interface';
 export * from './exceptions/ws-exception-filter.interface';
 export * from './execution-context.interface';
-export * from './nest-interceptor.interface';
\ No newline at end of file
+export * from './nest-interceptor.interface';
+export * from './custom-route-param-factory.interface';
\ No newline at end of file
diff --git a/src/common/test/utils/create-route-param-metadata.spec.ts b/src/common/test/utils/create-route-param-metadata.spec.ts
new file mode 100644
index 00000000000..b28cec148a0
--- /dev/null
+++ b/src/common/test/utils/create-route-param-metadata.spec.ts
@@ -0,0 +1,18 @@
+import { expect } from 'chai';
+import { createRouteParamDecorator } from '../../utils/decorators/create-route-param-metadata.decorator';
+import { CUSTOM_ROUTE_AGRS_METADATA } from '../../constants';
+
+describe('createRouteParamDecorator', () => {
+  let key;
+  let reflector;
+  let result;
+
+  beforeEach(() => {
+    key = 'key';
+    reflector = (data, req, res, next) => true;
+    result = createRouteParamDecorator(reflector);
+  });
+  it('should return a function as a first element', () => {
+    expect(result).to.be.a('function');
+  });
+});
diff --git a/src/common/utils/decorators/create-route-param-metadata.decorator.ts b/src/common/utils/decorators/create-route-param-metadata.decorator.ts
new file mode 100644
index 00000000000..19072a5274a
--- /dev/null
+++ b/src/common/utils/decorators/create-route-param-metadata.decorator.ts
@@ -0,0 +1,37 @@
+import { ROUTE_ARGS_METADATA, CUSTOM_ROUTE_AGRS_METADATA } from '../../constants';
+import { CustomParamFactory } from '../../interfaces/custom-route-param-factory.interface';
+import { RouteParamsMetadata, ParamData } from './route-params.decorator';
+
+const assignCustomMetadata = (
+  args: RouteParamsMetadata,
+  paramtype: number|string,
+  index: number,
+  factory: CustomParamFactory,
+  data?: ParamData,
+) => ({
+  ...args,
+  [`${index}:${paramtype}${CUSTOM_ROUTE_AGRS_METADATA}:${index}`]: {
+    index,
+    factory,
+    data,
+  },
+});
+
+const randomString = () => Math.random().toString(36).substring(2, 15);
+
+/**
+ * Create route params custom decorator
+ * @param factory 
+ */
+export const createRouteParamDecorator = (factory: CustomParamFactory) => {
+  const paramtype = randomString() + randomString();
+  return (data?: ParamData): ParameterDecorator => (target, key, index) => {
+    const args = Reflect.getMetadata(ROUTE_ARGS_METADATA, target, key) || {};
+    Reflect.defineMetadata(
+      ROUTE_ARGS_METADATA,
+      assignCustomMetadata(args, paramtype, index, factory, data),
+      target,
+      key,
+    );
+  };
+};
diff --git a/src/common/utils/index.ts b/src/common/utils/index.ts
index 6e71813dee0..18616b85e30 100644
--- a/src/common/utils/index.ts
+++ b/src/common/utils/index.ts
@@ -15,4 +15,5 @@ export * from './decorators/reflect-metadata.decorator';
 export * from './decorators/use-interceptors.decorator';
 export * from './decorators/http-code.decorator';
 export * from './decorators/bind.decorator';
-export * from './forward-ref.util';
\ No newline at end of file
+export * from './forward-ref.util';
+export * from './decorators/create-route-param-metadata.decorator';
\ No newline at end of file
diff --git a/src/core/router/router-execution-context.ts b/src/core/router/router-execution-context.ts
index 441bb5b571f..7089cf99e23 100644
--- a/src/core/router/router-execution-context.ts
+++ b/src/core/router/router-execution-context.ts
@@ -1,6 +1,6 @@
 import 'reflect-metadata';
-import { ROUTE_ARGS_METADATA, PARAMTYPES_METADATA, HTTP_CODE_METADATA } from '@nestjs/common/constants';
-import { isUndefined } from '@nestjs/common/utils/shared.utils';
+import { ROUTE_ARGS_METADATA, PARAMTYPES_METADATA, HTTP_CODE_METADATA, CUSTOM_ROUTE_AGRS_METADATA } from '@nestjs/common/constants';
+import { isUndefined, isFunction } from '@nestjs/common/utils/shared.utils';
 import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum';
 import { Controller, Transform } from '@nestjs/common/interfaces';
 import { RouteParamsMetadata } from '@nestjs/common/utils';
@@ -73,7 +73,7 @@ export class RouterExecutionContext {
         };
     }
 
-    public mapParamType(key: string): RouteParamtypes {
+    public mapParamType(key: string): RouteParamtypes | number {
         const keyPair = key.split(':');
         return Number(keyPair[0]);
     }
@@ -100,9 +100,17 @@ export class RouterExecutionContext {
 
     public exchangeKeysForValues(keys: string[], metadata: RouteParamsMetadata): ParamProperties[] {
         return keys.map(key => {
-            const type = this.mapParamType(key);
             const { index, data, pipes } = metadata[key];
+            const type = this.mapParamType(key);
 
+            if (key.includes(CUSTOM_ROUTE_AGRS_METADATA)) {
+                const { factory } = metadata[key];
+                const customExtractValue = !isUndefined(factory) && isFunction(factory)
+                  ? (req, res, next) => factory(data, req)
+                  : () => ({});
+
+                return { index, extractValue: customExtractValue, type, data, pipes };
+            }
             const extractValue = (req, res, next) => this.paramsFactory.exchangeKeyForValue(type, data, { req, res, next });
             return { index, extractValue, type, data, pipes };
         });
diff --git a/src/core/test/router/router-execution-context.spec.ts b/src/core/test/router/router-execution-context.spec.ts
index 96b621fd04c..d2347cb8b37 100644
--- a/src/core/test/router/router-execution-context.spec.ts
+++ b/src/core/test/router/router-execution-context.spec.ts
@@ -1,6 +1,8 @@
 import * as sinon from 'sinon';
 import { expect } from 'chai';
 import { RouteParamtypes } from '../../../common/enums/route-paramtypes.enum';
+import { CUSTOM_ROUTE_AGRS_METADATA } from '../../../common/constants';
+import { createRouteParamDecorator } from '../../../common/utils/decorators/create-route-param-metadata.decorator';
 import { RouterExecutionContext } from '../../router/router-execution-context';
 import { RouteParamsMetadata, Request, Body } from '../../../index';
 import { RouteParamsFactory } from '../../router/route-params-factory';
@@ -104,12 +106,15 @@ describe('RouterExecutionContext', () => {
         });
     });
     describe('reflectCallbackMetadata', () => {
+        const CustomDecorator = createRouteParamDecorator(() => {});
         class TestController {
-            public callback(@Request() req, @Body() body) {}
+            public callback(@Request() req, @Body() body, @CustomDecorator() custom) {}
         }
         it('should returns ROUTE_ARGS_METADATA callback metadata', () => {
             const instance = new TestController();
             const metadata = contextCreator.reflectCallbackMetadata(instance, 'callback');
+            console.log(metadata);
+            
             const expectedMetadata = {
                 [`${RouteParamtypes.REQUEST}:0`]: {
                     index: 0,
@@ -121,8 +126,22 @@ describe('RouterExecutionContext', () => {
                     data: undefined,
                     pipes: [],
                 },
+                [`custom${CUSTOM_ROUTE_AGRS_METADATA}:2`]: {
+                    index: 2,
+                    factory: () => {},
+                    data: undefined,
+                },
             };
-            expect(metadata).to.deep.equal(expectedMetadata);
+            expect(metadata[`${RouteParamtypes.REQUEST}:0`]).to.deep.equal(expectedMetadata[`${RouteParamtypes.REQUEST}:0`]);
+            expect(metadata[`${RouteParamtypes.REQUEST}:1`]).to.deep.equal(expectedMetadata[`${RouteParamtypes.REQUEST}:1`]);
+
+            const keys = Object.keys(metadata);
+            const custom = keys.find((key) => key.includes(CUSTOM_ROUTE_AGRS_METADATA));
+
+            expect(metadata[custom]).to.be.an('object');
+            expect(metadata[custom].index).to.be.eq(2);
+            expect(metadata[custom].data).to.be.eq(undefined);
+            expect(metadata[custom].factory).to.be.a('function');
         });
     });
     describe('getArgumentsLength', () => {
@@ -153,17 +172,15 @@ describe('RouterExecutionContext', () => {
         it('should exchange arguments keys for appropriate values', () => {
             const metadata = {
                 [RouteParamtypes.REQUEST]: { index: 0, data: 'test', pipes: [] },
-                [RouteParamtypes.BODY]: {
-                    index: 2,
-                    data: 'test',
-                    pipes: [],
-                },
+                [RouteParamtypes.BODY]: { index: 2, data: 'test', pipes: [] },
+                [`key${CUSTOM_ROUTE_AGRS_METADATA}`]: { index: 3, data: 'custom', pipes: [] },
             };
             const keys = Object.keys(metadata);
             const values = contextCreator.exchangeKeysForValues(keys, metadata);
             const expectedValues = [
                 { index: 0, type: RouteParamtypes.REQUEST, data: 'test' },
                 { index: 2, type: RouteParamtypes.BODY, data: 'test' },
+                { index: 3, type: `key${CUSTOM_ROUTE_AGRS_METADATA}`, data: 'custom' },
             ];
             expect(values[0]).to.deep.include(expectedValues[0]);
             expect(values[1]).to.deep.include(expectedValues[1]);

From 513586ecc21a984a3a5608b3d81c83384fb24231 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Wed, 22 Nov 2017 20:28:39 +0100
Subject: [PATCH 20/34] Update package.json

---
 lerna.json   | 2 +-
 package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/lerna.json b/lerna.json
index 40e1b61b4cf..3b40b6bd23e 100644
--- a/lerna.json
+++ b/lerna.json
@@ -3,5 +3,5 @@
   "packages": [
     "lib/*"
   ],
-  "version": "4.3.3"
+  "version": "4.3.4"
 }
diff --git a/package.json b/package.json
index b20644f30b8..57c279f5d3e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "nestjs",
-  "version": "4.3.3",
+  "version": "4.3.4",
   "description": "Modern, fast, powerful node.js web framework",
   "main": "index.js",
   "scripts": {

From 84d1bec26a598291b1c0e9c17b9e6aa99b37a33e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Wed, 22 Nov 2017 21:22:30 +0100
Subject: [PATCH 21/34] cov(@nestjs/core) increase test coverage

---
 src/core/router/router-execution-context.ts   | 11 +++---
 .../router/router-execution-context.spec.ts   | 34 ++++++++++++++++++-
 2 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/src/core/router/router-execution-context.ts b/src/core/router/router-execution-context.ts
index 7089cf99e23..2d17ecf4d06 100644
--- a/src/core/router/router-execution-context.ts
+++ b/src/core/router/router-execution-context.ts
@@ -105,10 +105,7 @@ export class RouterExecutionContext {
 
             if (key.includes(CUSTOM_ROUTE_AGRS_METADATA)) {
                 const { factory } = metadata[key];
-                const customExtractValue = !isUndefined(factory) && isFunction(factory)
-                  ? (req, res, next) => factory(data, req)
-                  : () => ({});
-
+                const customExtractValue = this.getCustomFactory(factory, data);
                 return { index, extractValue: customExtractValue, type, data, pipes };
             }
             const extractValue = (req, res, next) => this.paramsFactory.exchangeKeyForValue(type, data, { req, res, next });
@@ -116,6 +113,12 @@ export class RouterExecutionContext {
         });
     }
 
+    public getCustomFactory(factory: (...args) => void, data): (...args) => any {
+      return !isUndefined(factory) && isFunction(factory)
+        ? (req, res, next) => factory(data, req)
+        : () => null;
+    }
+
     public mergeParamsMetatypes(
       paramsProperties: ParamProperties[],
       paramtypes: any[],
diff --git a/src/core/test/router/router-execution-context.spec.ts b/src/core/test/router/router-execution-context.spec.ts
index d2347cb8b37..4c4cfc6e773 100644
--- a/src/core/test/router/router-execution-context.spec.ts
+++ b/src/core/test/router/router-execution-context.spec.ts
@@ -22,6 +22,7 @@ describe('RouterExecutionContext', () => {
     let bindSpy: sinon.SinonSpy;
     let factory: RouteParamsFactory;
     let consumer: PipesConsumer;
+    let guardsConsumer: GuardsConsumer;
 
     beforeEach(() => {
         callback = {
@@ -33,10 +34,11 @@ describe('RouterExecutionContext', () => {
 
         factory = new RouteParamsFactory();
         consumer = new PipesConsumer();
+        guardsConsumer = new GuardsConsumer();
 
         contextCreator = new RouterExecutionContext(
             factory, new PipesContextCreator(new ApplicationConfig()), consumer,
-            new GuardsContextCreator(new NestContainer()), new GuardsConsumer(),
+            new GuardsContextCreator(new NestContainer()), guardsConsumer,
             new InterceptorsContextCreator(new NestContainer()), new InterceptorsConsumer(),
         );
     });
@@ -101,6 +103,12 @@ describe('RouterExecutionContext', () => {
                             done();
                         });
                     });
+                    it('should throw exception when "tryActivate" returns false', () => {
+                        sinon.stub(guardsConsumer, 'tryActivate', () => false);
+                        expect(
+                          proxyContext(request, response, next),
+                        ).to.eventually.throw();
+                    });
                 });
             });
         });
@@ -186,6 +194,30 @@ describe('RouterExecutionContext', () => {
             expect(values[1]).to.deep.include(expectedValues[1]);
         });
     });
+    describe('getCustomFactory', () => {
+      describe('when factory is function', () => {
+        it('should return curried factory', () => {
+          const data = 3;
+          const result = 10;
+          const customFactory = (_, req) => result;
+
+          expect(contextCreator.getCustomFactory(customFactory, data)()).to.be.eql(result);
+        });
+      });
+      describe('when factory is undefined / is not a function', () => {
+        it('should return curried null identity', () => {
+          const result = 10;
+          const customFactory = undefined;
+          expect(contextCreator.getCustomFactory(customFactory, undefined)()).to.be.eql(null);
+        });
+      });
+    });
+    describe('mergeParamsMetatypes', () => {
+      it('should return "paramsProperties" when paramtypes array doesnt exists', () => {
+        const paramsProperties = ['1'];
+        expect(contextCreator.mergeParamsMetatypes(paramsProperties as any, null)).to.be.eql(paramsProperties);
+      });
+    });
     describe('getParamValue', () => {
         let consumerApplySpy: sinon.SinonSpy;
         const value = 3, metatype = null, transforms = [];

From 5568bfd15898c1b81ff52424a919b08cba6a1512 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Wed, 22 Nov 2017 23:15:04 +0100
Subject: [PATCH 22/34] ci(@nestjs) update travis.yml

---
 .travis.yml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index 0349a0d4aba..2ba7be20e84 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,9 @@ addons:
 before_script:
      - export DISPLAY=:99.0
      - sh -e /etc/init.d/xvfb start
+install:
+     - npm install
+     - npm build
 script:
       - npm build
       - npm test

From 33cb5892ea9110b95dfc5cfdb8220332a79df919 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Wed, 22 Nov 2017 23:20:25 +0100
Subject: [PATCH 23/34] ci(@nestjs) update travis.yml

---
 .travis.yml | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 2ba7be20e84..164fed26638 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,8 +8,7 @@ before_script:
      - sh -e /etc/init.d/xvfb start
 install:
      - npm install
-     - npm build
+     - gulp build
 script:
-      - npm build
       - npm test
 after_success: npm run coverage
\ No newline at end of file

From ee66fafdfc9a519320fe7d667acf97f369fe1885 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Wed, 22 Nov 2017 23:25:20 +0100
Subject: [PATCH 24/34] feature(@nejsts/core) create nest application context
 feature #201

---
 package.json                                  |  3 +-
 src/common/index.ts                           |  1 +
 src/common/interfaces/index.ts                |  1 +
 .../nest-application-context.interface.ts     | 15 +++++++
 src/core/nest-application-context.ts          | 44 +++++++++++++++++++
 src/core/nest-application.ts                  | 12 ++---
 src/core/nest-factory.ts                      | 23 ++++++++--
 7 files changed, 88 insertions(+), 11 deletions(-)
 create mode 100644 src/common/interfaces/nest-application-context.interface.ts
 create mode 100644 src/core/nest-application-context.ts

diff --git a/package.json b/package.json
index 57c279f5d3e..18ef6d15db4 100644
--- a/package.json
+++ b/package.json
@@ -86,8 +86,7 @@
       "src/**/*.spec.ts",
       "src/core/adapters/*.ts",
       "src/websockets/adapters/*.ts",
-      "src/core/nest-application.ts",
-      "src/core/nest-factory.ts",
+      "src/core/nest-*.ts",
       "src/common/exceptions/*.ts",
       "src/common/services/logger.service.ts",
       "src/core/errors/exceptions",
diff --git a/src/common/index.ts b/src/common/index.ts
index 25243a13d45..ea68afd261c 100644
--- a/src/common/index.ts
+++ b/src/common/index.ts
@@ -28,6 +28,7 @@ export {
     RpcExceptionFilter,
     WsExceptionFilter,
     NestInterceptor,
+    INestApplicationContext,
 } from './interfaces';
 export * from './services/logger.service';
 export * from './pipes';
diff --git a/src/common/interfaces/index.ts b/src/common/interfaces/index.ts
index 82f8cc0169c..8ac232ed87e 100644
--- a/src/common/interfaces/index.ts
+++ b/src/common/interfaces/index.ts
@@ -8,6 +8,7 @@ export * from './modules/module-metadata.interface';
 export * from './metatype.interface';
 export * from './nest-application.interface';
 export * from './nest-microservice.interface';
+export * from './nest-application-context.interface';
 export * from './modules/on-init.interface';
 export * from './modules/on-destroy.interface';
 export * from './exceptions/exception-filter.interface';
diff --git a/src/common/interfaces/nest-application-context.interface.ts b/src/common/interfaces/nest-application-context.interface.ts
new file mode 100644
index 00000000000..1400a9be998
--- /dev/null
+++ b/src/common/interfaces/nest-application-context.interface.ts
@@ -0,0 +1,15 @@
+import { Metatype } from './metatype.interface';
+
+export interface INestApplicationContext {
+    /**
+     * Allows you to navigate through the modules tree, for example, to pull out a specific instance from the selected module.
+     * @returns INestApplicationContext
+     */
+    select(module: Metatype): INestApplicationContext;
+
+    /**
+     * Makes possible to retrieve the instance of the component or controller available inside the processed module.
+     * @returns T
+     */
+    get(metatypeOrToken: Metatype | string): T;
+}
\ No newline at end of file
diff --git a/src/core/nest-application-context.ts b/src/core/nest-application-context.ts
new file mode 100644
index 00000000000..1732783f474
--- /dev/null
+++ b/src/core/nest-application-context.ts
@@ -0,0 +1,44 @@
+
+import { ModuleTokenFactory } from './injector/module-token-factory';
+import { NestContainer, InstanceWrapper } from './injector/container';
+import { NestModuleMetatype } from '@nestjs/common/interfaces/modules/module-metatype.interface';
+import { Metatype } from '@nestjs/common/interfaces';
+import { isFunction } from '@nestjs/common/utils/shared.utils';
+import { INestApplicationContext } from '@nestjs/common';
+
+export class NestApplicationContext {
+    private readonly moduleTokenFactory = new ModuleTokenFactory();
+
+    constructor(
+        private readonly container: NestContainer,
+        private readonly scope: NestModuleMetatype[],
+        private readonly contextModule) {}
+
+    public select(module: Metatype): INestApplicationContext {
+        const modules = this.container.getModules();
+        const moduleMetatype = this.contextModule.metatype;
+        const scope = this.scope.concat(moduleMetatype);
+
+        const token = this.moduleTokenFactory.create(module as any, scope);
+        const selectedModule = modules.get(token);
+        return selectedModule
+          ? new NestApplicationContext(this.container, scope, selectedModule)
+          : null;
+    }
+
+    public get(metatypeOrToken: Metatype | string): T {
+        return this.findInstanceByPrototypeOrToken(metatypeOrToken);
+    }
+
+    private findInstanceByPrototypeOrToken(metatypeOrToken: Metatype | string) {
+        const dependencies = new Map([
+            ...this.contextModule.components,
+            ...this.contextModule.routes,
+        ]);
+        const name = isFunction(metatypeOrToken) ? (metatypeOrToken as any).name : metatypeOrToken;
+        const instanceWrapper = dependencies.get(name);
+        return instanceWrapper
+          ? (instanceWrapper as InstanceWrapper).instance
+          : null;
+    }
+}
\ No newline at end of file
diff --git a/src/core/nest-application.ts b/src/core/nest-application.ts
index 312524ee354..2d83656d33b 100644
--- a/src/core/nest-application.ts
+++ b/src/core/nest-application.ts
@@ -54,8 +54,8 @@ export class NestApplication implements INestApplication {
     }
 
     public setupParserMiddlewares() {
-      this.express.use(bodyParser.json());
-      this.express.use(bodyParser.urlencoded({ extended: true }));
+        this.express.use(bodyParser.json());
+        this.express.use(bodyParser.urlencoded({ extended: true }));
     }
 
     public async setupModules() {
@@ -82,11 +82,11 @@ export class NestApplication implements INestApplication {
     }
 
     public async setupRouter() {
-      const router = ExpressAdapter.createRouter();
-      await this.setupMiddlewares(router);
+        const router = ExpressAdapter.createRouter();
+        await this.setupMiddlewares(router);
 
-      this.routesResolver.resolve(router);
-      this.express.use(validatePath(this.config.getGlobalPrefix()), router);
+        this.routesResolver.resolve(router);
+        this.express.use(validatePath(this.config.getGlobalPrefix()), router);
     }
 
     public connectMicroservice(config: MicroserviceConfiguration): INestMicroservice {
diff --git a/src/core/nest-factory.ts b/src/core/nest-factory.ts
index be9b8996bbe..60476ce2cd8 100644
--- a/src/core/nest-factory.ts
+++ b/src/core/nest-factory.ts
@@ -10,9 +10,10 @@ import { NestApplication } from './nest-application';
 import { isFunction } from '@nestjs/common/utils/shared.utils';
 import { MicroserviceConfiguration } from '@nestjs/common/interfaces/microservices/microservice-configuration.interface';
 import { ExpressAdapter } from './adapters/express-adapter';
-import { INestApplication, INestMicroservice } from '@nestjs/common';
+import { INestApplication, INestMicroservice, INestApplicationContext } from '@nestjs/common';
 import { MetadataScanner } from './metadata-scanner';
 import { MicroservicesPackageNotFoundException } from './errors/exceptions/microservices-package-not-found.exception';
+import { NestApplicationContext } from './nest-application-context';
 
 const { NestMicroservice } = optional('@nestjs/microservices/nest-microservice') || {} as any;
 
@@ -27,7 +28,7 @@ export class NestFactoryStatic {
     /**
      * Creates an instance of the NestApplication (returns Promise)
      *
-     * @param  {} module Entry ApplicationModule class
+     * @param  {} module Entry (root) application module class
      * @param  {} express Optional express() server instance
      * @returns an `Promise` of the INestApplication instance
      */
@@ -41,7 +42,7 @@ export class NestFactoryStatic {
     /**
      * Creates an instance of the NestMicroservice (returns Promise)
      *
-     * @param  {} module Entry ApplicationModule class
+     * @param  {} module Entry (root) application module class
      * @param  {MicroserviceConfiguration} config Optional microservice configuration
      * @returns an `Promise` of the INestMicroservice instance
      */
@@ -59,6 +60,22 @@ export class NestFactoryStatic {
         );
     }
 
+    /**
+     * Creates an instance of the NestApplicationContext (returns Promise)
+     *
+     * @param  {} module Entry (root) application module class
+     * @returns an `Promise` of the INestApplicationContext instance
+     */
+    public async createApplicationContext(module): Promise {
+        await this.initialize(module);
+
+        const modules = this.container.getModules().values();
+        const root = modules.next().value;
+        return this.createNestInstance(
+            new NestApplicationContext(this.container, [], root),
+        );
+    }
+
     private createNestInstance(instance: T) {
         return this.createProxy(instance);
     }

From 842361c6cf4c889a056b661bc66b62e9a2e59f2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Wed, 22 Nov 2017 23:26:03 +0100
Subject: [PATCH 25/34] Update Readme.md

---
 Readme.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Readme.md b/Readme.md
index 24e9bcae0f7..2b56fa0814c 100644
--- a/Readme.md
+++ b/Readme.md
@@ -14,7 +14,7 @@
 NPM Downloads
 Travis
 Linux
-Coverage
+Coverage
 Gitter
 Backers on Open Collective
 Sponsors on Open Collective

From e73afb75abddf91a98f11e611b8efab61ec9c2fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Wed, 22 Nov 2017 23:47:28 +0100
Subject: [PATCH 26/34] feature(@nejsts/core) create nest application context
 feature #201

---
 CHANGELOG.md                                  |  4 ++
 package.json                                  |  2 +-
 src/core/index.ts                             |  3 +-
 src/core/nest-application-context.ts          |  5 +-
 .../errors/unknown-module.exception.ts        |  7 ---
 src/testing/testing-module.ts                 | 55 +++----------------
 6 files changed, 17 insertions(+), 59 deletions(-)
 delete mode 100644 src/testing/errors/unknown-module.exception.ts

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9831dd6c4ac..36f3fab3ebb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 4.4.0 @soon
+- **core**: possibility to create the `NestApplicationContext` using `NestFactory.createApplicationContext()` (Nest application without HTTP server / microservice in the background)
+- **core**: create custom params decorators feature (`createRouteParamDecorator()`)
+
 ## 4.3.3
 - **common**: `ParseIntPipe` is now available out-of-the-box (`@nestjs/common`)
 - **common**: package contains a set of useful HTTP exceptions now, such as `ForbiddenException`, `UnauthorizedException`, `BadRequestException` etc
diff --git a/package.json b/package.json
index 18ef6d15db4..c5222a5d75d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "nestjs",
-  "version": "4.3.4",
+  "version": "4.4.0",
   "description": "Modern, fast, powerful node.js web framework",
   "main": "index.js",
   "scripts": {
diff --git a/src/core/index.ts b/src/core/index.ts
index 19eaf66d75a..52bae15e0a9 100644
--- a/src/core/index.ts
+++ b/src/core/index.ts
@@ -10,4 +10,5 @@ export { MiddlewareBuilder } from './middlewares/builder';
 export { ModuleRef } from './injector/module-ref';
 export * from './services/reflector.service';
 export * from './nest-factory';
-export * from './nest-application';
\ No newline at end of file
+export * from './nest-application';
+export * from './nest-application-context';
\ No newline at end of file
diff --git a/src/core/nest-application-context.ts b/src/core/nest-application-context.ts
index 1732783f474..a8aba2f511c 100644
--- a/src/core/nest-application-context.ts
+++ b/src/core/nest-application-context.ts
@@ -6,11 +6,11 @@ import { Metatype } from '@nestjs/common/interfaces';
 import { isFunction } from '@nestjs/common/utils/shared.utils';
 import { INestApplicationContext } from '@nestjs/common';
 
-export class NestApplicationContext {
+export class NestApplicationContext implements INestApplicationContext {
     private readonly moduleTokenFactory = new ModuleTokenFactory();
 
     constructor(
-        private readonly container: NestContainer,
+        protected readonly container: NestContainer,
         private readonly scope: NestModuleMetatype[],
         private readonly contextModule) {}
 
@@ -34,6 +34,7 @@ export class NestApplicationContext {
         const dependencies = new Map([
             ...this.contextModule.components,
             ...this.contextModule.routes,
+            ...this.contextModule.injectables,
         ]);
         const name = isFunction(metatypeOrToken) ? (metatypeOrToken as any).name : metatypeOrToken;
         const instanceWrapper = dependencies.get(name);
diff --git a/src/testing/errors/unknown-module.exception.ts b/src/testing/errors/unknown-module.exception.ts
deleted file mode 100644
index 8f8a24f0838..00000000000
--- a/src/testing/errors/unknown-module.exception.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { RuntimeException } from '@nestjs/core/errors/exceptions/runtime.exception';
-
-export class UnknownModuleException extends RuntimeException {
-    constructor() {
-        super();
-    }
-}
\ No newline at end of file
diff --git a/src/testing/testing-module.ts b/src/testing/testing-module.ts
index 756ea12d53b..c64702668d5 100644
--- a/src/testing/testing-module.ts
+++ b/src/testing/testing-module.ts
@@ -1,26 +1,17 @@
 import * as optional from 'optional';
-import { NestContainer, InstanceWrapper } from '@nestjs/core/injector/container';
-import { DependenciesScanner } from '@nestjs/core/scanner';
-import { MetadataScanner } from '@nestjs/core/metadata-scanner';
-import { Metatype } from '@nestjs/common/interfaces';
-import { isFunction } from '@nestjs/common/utils/shared.utils';
-import { ModuleTokenFactory } from '@nestjs/core/injector/module-token-factory';
+import { NestContainer } from '@nestjs/core/injector/container';
 import { NestModuleMetatype } from '@nestjs/common/interfaces/modules/module-metatype.interface';
-import { UnknownModuleException } from './errors/unknown-module.exception';
-import { NestApplication } from '@nestjs/core';
+import { NestApplication, NestApplicationContext } from '@nestjs/core';
 import { INestApplication, INestMicroservice } from '@nestjs/common';
 import { MicroserviceConfiguration } from '@nestjs/common/interfaces/microservices/microservice-configuration.interface';
 import { MicroservicesPackageNotFoundException } from '@nestjs/core/errors/exceptions/microservices-package-not-found.exception';
 
 const { NestMicroservice } = optional('@nestjs/microservices/nest-microservice') || {} as any;
 
-export class TestingModule {
-    private readonly moduleTokenFactory = new ModuleTokenFactory();
-
-    constructor(
-        private readonly container: NestContainer,
-        private readonly scope: NestModuleMetatype[],
-        private readonly contextModule) {}
+export class TestingModule extends NestApplicationContext {
+    constructor(container: NestContainer, scope: NestModuleMetatype[], contextModule) {
+        super(container, scope, contextModule);
+    }
 
     public createNestApplication(express?): INestApplication {
         return new NestApplication(this.container, express);
@@ -32,36 +23,4 @@ export class TestingModule {
         }
         return new NestMicroservice(this.container, config);
     }
-
-    public select(module: Metatype): TestingModule {
-        const modules = this.container.getModules();
-        const moduleMetatype = this.contextModule.metatype;
-        const scope = this.scope.concat(moduleMetatype);
-
-        const token = this.moduleTokenFactory.create(module as any, scope);
-        const selectedModule = modules.get(token);
-        if (!selectedModule) {
-            throw new UnknownModuleException();
-        }
-        return new TestingModule(this.container, scope, selectedModule);
-    }
-
-    public get(metatypeOrToken: Metatype | string): T {
-        return this.findInstanceByPrototypeOrToken(metatypeOrToken);
-    }
-
-    private findInstanceByPrototypeOrToken(metatypeOrToken: Metatype | string) {
-        const dependencies = new Map([
-            ...this.contextModule.components,
-            ...this.contextModule.routes,
-            ...this.contextModule.injectables,
-        ]);
-        const name = isFunction(metatypeOrToken) ? (metatypeOrToken as any).name : metatypeOrToken;
-        const instanceWrapper = dependencies.get(name);
-        if (!instanceWrapper) {
-            return null;
-        }
-        return (instanceWrapper as InstanceWrapper).instance;
-    }
-}
-
+}
\ No newline at end of file

From 45d851897003b6ca28c8a8f3ce9d5792e86bd94a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= 
Date: Thu, 23 Nov 2017 20:28:31 +0100
Subject: [PATCH 27/34] Update Readme.md

---
 Readme.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Readme.md b/Readme.md
index 2b56fa0814c..a2a7dd4840f 100644
--- a/Readme.md
+++ b/Readme.md
@@ -47,6 +47,7 @@
     
  • Guards - attach additional logic in a declarative manner (e.g. role-based access control)
  • Interceptors - built on top of RxJS
  • Testing utilities (both e2e & unit tests)
  • +
  • More!
  • ## Installation From ac1303e529a41d0ea95fadc466be825e505073cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Thu, 23 Nov 2017 20:40:35 +0100 Subject: [PATCH 28/34] update(@nestjs) update to 4.4.0 --- gulpfile.js | 62 +++++++++++++------ package.json | 2 +- src/core/adapters/express-adapter.ts | 2 +- src/core/middlewares/middlewares-module.ts | 26 ++++---- src/core/nest-application.ts | 25 +++++--- .../middlewares/middlewares-module.spec.ts | 13 ++-- src/microservices/microservices-module.ts | 18 +++--- src/microservices/nest-microservice.ts | 15 +++-- src/websockets/socket-module.ts | 15 +++-- 9 files changed, 108 insertions(+), 70 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 55dabf683ef..41facf1defb 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,35 +1,59 @@ const gulp = require('gulp'); const ts = require('gulp-typescript'); -const gulpSequence = require('gulp-sequence') +const gulpSequence = require('gulp-sequence'); const packages = { - common: ts.createProject('src/common/tsconfig.json'), - core: ts.createProject('src/core/tsconfig.json'), - microservices: ts.createProject('src/microservices/tsconfig.json'), - websockets: ts.createProject('src/websockets/tsconfig.json'), - testing: ts.createProject('src/testing/tsconfig.json') + common: ts.createProject('src/common/tsconfig.json'), + core: ts.createProject('src/core/tsconfig.json'), + microservices: ts.createProject('src/microservices/tsconfig.json'), + websockets: ts.createProject('src/websockets/tsconfig.json'), + testing: ts.createProject('src/testing/tsconfig.json'), }; const modules = Object.keys(packages); const source = 'src'; const distId = process.argv.indexOf('--dist'); const dist = distId < 0 ? 'node_modules/@nestjs' : process.argv[distId + 1]; -gulp.task('default', function () { - modules.forEach((module) => { - gulp.watch([`${source}/${module}/**/*.ts`, `${source}/${module}/*.ts`], [module]); - }); +gulp.task('default', function() { + modules.forEach(module => { + gulp.watch( + [`${source}/${module}/**/*.ts`, `${source}/${module}/*.ts`], + [module] + ); + }); }); -modules.forEach((module) => { - gulp.task(module, () => { - return packages[module].src() - .pipe(packages[module]()) - .pipe(gulp.dest(`${dist}/${module}`)); - }); +modules.forEach(module => { + gulp.task(module, () => { + return packages[module] + .src() + .pipe(packages[module]()) + .pipe(gulp.dest(`${dist}/${module}`)); + }); }); -gulp.task('build', function (cb) { - gulpSequence(modules, cb); +gulp.task('build', function(cb) { + gulpSequence(modules, cb); }); - +gulp.task('move', function() { + gulp.src(['node_modules/@nestjs/**/*']).pipe( + gulp.dest('examples/01-cats-app/node_modules/@nestjs') + ).pipe( + gulp.dest('examples/02-gateways/node_modules/@nestjs') + ).pipe( + gulp.dest('examples/03-microservices/node_modules/@nestjs') + ).pipe( + gulp.dest('examples/04-injector/node_modules/@nestjs') + ).pipe( + gulp.dest('examples/05-sql-typeorm/node_modules/@nestjs') + ).pipe( + gulp.dest('examples/06-mongoose/node_modules/@nestjs') + ).pipe( + gulp.dest('examples/07-sequelize/node_modules/@nestjs') + ).pipe( + gulp.dest('examples/08-passport/node_modules/@nestjs') + ).pipe( + gulp.dest('examples/09-babel-example/node_modules/@nestjs') + ); +}); diff --git a/package.json b/package.json index c5222a5d75d..9e2d6149ab2 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "start:live": "nodemon -e ts --watch src index.js", "test": "nyc --require ts-node/register mocha src/**/*.spec.ts --reporter spec", "coverage": "nyc report --reporter=text-lcov | coveralls", - "build": "gulp build", + "build": "gulp build && gulp move", "build:lib": "gulp build --dist lib", "prepublish": "npm run build:lib", "publish": "./node_modules/.bin/lerna publish --skip-git" diff --git a/src/core/adapters/express-adapter.ts b/src/core/adapters/express-adapter.ts index 5aee2586fc1..9868d4410f7 100644 --- a/src/core/adapters/express-adapter.ts +++ b/src/core/adapters/express-adapter.ts @@ -6,6 +6,6 @@ export class ExpressAdapter { } public static createRouter(): any { - return express.Router(); + return express.Router({ mergeParams: true }); } } \ No newline at end of file diff --git a/src/core/middlewares/middlewares-module.ts b/src/core/middlewares/middlewares-module.ts index 43a563f4e31..be3d59603cf 100644 --- a/src/core/middlewares/middlewares-module.ts +++ b/src/core/middlewares/middlewares-module.ts @@ -20,13 +20,13 @@ import { ApplicationConfig } from './../application-config'; import { RouterExceptionFilters } from './../router/router-exception-filters'; export class MiddlewaresModule { - private static readonly routesMapper = new RoutesMapper(); - private static readonly routerProxy = new RouterProxy(); - private static readonly routerMethodFactory = new RouterMethodFactory(); - private static routerExceptionFilter: RouterExceptionFilters; - private static resolver: MiddlewaresResolver; + private readonly routesMapper = new RoutesMapper(); + private readonly routerProxy = new RouterProxy(); + private readonly routerMethodFactory = new RouterMethodFactory(); + private routerExceptionFilter: RouterExceptionFilters; + private resolver: MiddlewaresResolver; - public static async setup( + public async setup( middlewaresContainer: MiddlewaresContainer, container: NestContainer, config: ApplicationConfig, @@ -38,7 +38,7 @@ export class MiddlewaresModule { await this.resolveMiddlewares(middlewaresContainer, modules); } - public static async resolveMiddlewares( + public async resolveMiddlewares( middlewaresContainer: MiddlewaresContainer, modules: Map, ) { @@ -50,7 +50,7 @@ export class MiddlewaresModule { })); } - public static loadConfiguration( + public loadConfiguration( middlewaresContainer: MiddlewaresContainer, instance: NestModule, module: string, @@ -66,7 +66,7 @@ export class MiddlewaresModule { middlewaresContainer.addConfig(config, module); } - public static async setupMiddlewares(middlewaresContainer: MiddlewaresContainer, app) { + public async setupMiddlewares(middlewaresContainer: MiddlewaresContainer, app) { const configs = middlewaresContainer.getConfigs(); await Promise.all([...configs.entries()].map(async ([module, moduleConfigs]) => { await Promise.all([...moduleConfigs].map(async (config: MiddlewareConfiguration) => { @@ -75,7 +75,7 @@ export class MiddlewaresModule { })); } - public static async setupMiddlewareConfig( + public async setupMiddlewareConfig( middlewaresContainer: MiddlewaresContainer, config: MiddlewareConfiguration, module: string, @@ -87,7 +87,7 @@ export class MiddlewaresModule { })); } - public static async setupRouteMiddleware( + public async setupRouteMiddleware( middlewaresContainer: MiddlewaresContainer, route: ControllerMetadata & { method: RequestMethod }, config: MiddlewareConfiguration, @@ -109,7 +109,7 @@ export class MiddlewaresModule { })); } - private static async setupHandler( + private async setupHandler( instance: NestMiddleware, metatype: Metatype, app: any, @@ -134,7 +134,7 @@ export class MiddlewaresModule { setupWithProxy(middleware); } - private static setupHandlerWithProxy( + private setupHandlerWithProxy( exceptionsHandler: ExceptionsHandler, router: (...args) => void, middleware: (req, res, next) => void, diff --git a/src/core/nest-application.ts b/src/core/nest-application.ts index 2d83656d33b..31a840d68b7 100644 --- a/src/core/nest-application.ts +++ b/src/core/nest-application.ts @@ -31,8 +31,16 @@ const { NestMicroservice } = optional('@nestjs/microservices/nest-microservice') const { IoAdapter } = optional('@nestjs/websockets/adapters/io-adapter') || {} as any; export class NestApplication implements INestApplication { - private readonly middlewaresContainer = new MiddlewaresContainer(); private readonly logger = new Logger(NestApplication.name, true); + private readonly middlewaresModule = new MiddlewaresModule(); + private readonly middlewaresContainer = new MiddlewaresContainer(); + private readonly microservicesModule = MicroservicesModule + ? new MicroservicesModule() + : null; + private readonly socketModule = SocketModule + ? new SocketModule() + : null; + private readonly httpServer: http.Server = null; private readonly routesResolver: Resolver = null; private readonly config: ApplicationConfig; @@ -59,13 +67,13 @@ export class NestApplication implements INestApplication { } public async setupModules() { - SocketModule && SocketModule.setup(this.container, this.config); + this.socketModule && this.socketModule.setup(this.container, this.config); - if (MicroservicesModule) { - MicroservicesModule.setup(this.container, this.config); - MicroservicesModule.setupClients(this.container); + if (this.microservicesModule) { + this.microservicesModule.setup(this.container, this.config); + this.microservicesModule.setupClients(this.container); } - await MiddlewaresModule.setup( + await this.middlewaresModule.setup( this.middlewaresContainer, this.container, this.config, @@ -93,7 +101,6 @@ export class NestApplication implements INestApplication { if (!NestMicroservice) { throw new MicroservicesPackageNotFoundException(); } - const instance = new NestMicroservice(this.container as any, config as any); instance.setupListeners(); instance.setIsInitialized(true); @@ -137,7 +144,7 @@ export class NestApplication implements INestApplication { } public close() { - SocketModule && SocketModule.close(); + this.socketModule && this.socketModule.close(); this.httpServer && this.httpServer.close(); this.microservices.forEach((microservice) => { microservice.setIsTerminated(true); @@ -171,7 +178,7 @@ export class NestApplication implements INestApplication { } private async setupMiddlewares(instance) { - await MiddlewaresModule.setupMiddlewares(this.middlewaresContainer, instance); + await this.middlewaresModule.setupMiddlewares(this.middlewaresContainer, instance); } private listenToPromise(microservice: INestMicroservice) { diff --git a/src/core/test/middlewares/middlewares-module.spec.ts b/src/core/test/middlewares/middlewares-module.spec.ts index 2c348bd983f..7102cd6c5c9 100644 --- a/src/core/test/middlewares/middlewares-module.spec.ts +++ b/src/core/test/middlewares/middlewares-module.spec.ts @@ -15,6 +15,8 @@ import { ApplicationConfig } from '../../application-config'; import { MiddlewaresContainer } from "../../middlewares/container"; describe('MiddlewaresModule', () => { + let middlewaresModule: MiddlewaresModule; + @Controller('test') class AnotherRoute { } @@ -36,7 +38,8 @@ describe('MiddlewaresModule', () => { } beforeEach(() => { - (MiddlewaresModule as any).routerExceptionFilter = new RouterExceptionFilters( + middlewaresModule = new MiddlewaresModule(); + (middlewaresModule as any).routerExceptionFilter = new RouterExceptionFilters( new ApplicationConfig(), ); }); @@ -49,7 +52,7 @@ describe('MiddlewaresModule', () => { configure: configureSpy, }; - MiddlewaresModule.loadConfiguration(new MiddlewaresContainer(), mockModule as any, 'Test' as any); + middlewaresModule.loadConfiguration(new MiddlewaresContainer(), mockModule as any, 'Test' as any); expect(configureSpy.calledOnce).to.be.true; expect(configureSpy.calledWith(new MiddlewareBuilder(new RoutesMapper()))).to.be.true; @@ -69,7 +72,7 @@ describe('MiddlewaresModule', () => { const app = { use: useSpy }; expect( - MiddlewaresModule.setupRouteMiddleware(new MiddlewaresContainer(), route as any, configuration, 'Test' as any, app as any), + middlewaresModule.setupRouteMiddleware(new MiddlewaresContainer(), route as any, configuration, 'Test' as any, app as any), ).to.eventually.be.rejectedWith(RuntimeException); }); @@ -97,7 +100,7 @@ describe('MiddlewaresModule', () => { } as any); expect( - MiddlewaresModule.setupRouteMiddleware(container, route as any, configuration, moduleKey, app as any), + middlewaresModule.setupRouteMiddleware(container, route as any, configuration, moduleKey, app as any), ).to.be.rejectedWith(InvalidMiddlewareException); }); @@ -123,7 +126,7 @@ describe('MiddlewaresModule', () => { instance, }); - MiddlewaresModule.setupRouteMiddleware(container, route, configuration, moduleKey, app as any); + middlewaresModule.setupRouteMiddleware(container, route, configuration, moduleKey, app as any); expect(useSpy.calledOnce).to.be.true; }); diff --git a/src/microservices/microservices-module.ts b/src/microservices/microservices-module.ts index 17b8f9b4983..1e054fe8734 100644 --- a/src/microservices/microservices-module.ts +++ b/src/microservices/microservices-module.ts @@ -16,10 +16,10 @@ import { InterceptorsContextCreator } from '@nestjs/core/interceptors/intercepto import { InterceptorsConsumer } from '@nestjs/core/interceptors/interceptors-consumer'; export class MicroservicesModule { - private static readonly clientsContainer = new ClientsContainer(); - private static listenersController: ListenersController; + private readonly clientsContainer = new ClientsContainer(); + private listenersController: ListenersController; - public static setup(container, config) { + public setup(container, config) { const contextCreator = new RpcContextCreator( new RpcProxy(), new ExceptionFiltersContext(config), @@ -31,12 +31,12 @@ export class MicroservicesModule { new InterceptorsConsumer(), ); this.listenersController = new ListenersController( - MicroservicesModule.clientsContainer, + this.clientsContainer, contextCreator, ); } - public static setupListeners(container, server: Server & CustomTransportStrategy) { + public setupListeners(container, server: Server & CustomTransportStrategy) { if (!this.listenersController) { throw new RuntimeException(); } @@ -44,7 +44,7 @@ export class MicroservicesModule { modules.forEach(({ routes }, module) => this.bindListeners(routes, server, module)); } - public static setupClients(container) { + public setupClients(container) { if (!this.listenersController) { throw new RuntimeException(); } @@ -55,7 +55,7 @@ export class MicroservicesModule { }); } - public static bindListeners( + public bindListeners( controllers: Map>, server: Server & CustomTransportStrategy, module: string) { @@ -65,13 +65,13 @@ export class MicroservicesModule { }); } - public static bindClients(controllers: Map>) { + public bindClients(controllers: Map>) { controllers.forEach(({ instance, isNotMetatype }) => { !isNotMetatype && this.listenersController.bindClientsToProperties(instance); }); } - public static close() { + public close() { const clients = this.clientsContainer.getAllClients(); clients.forEach((client) => client.close()); this.clientsContainer.clear(); diff --git a/src/microservices/nest-microservice.ts b/src/microservices/nest-microservice.ts index c6f31d9d177..4a0d91b6792 100644 --- a/src/microservices/nest-microservice.ts +++ b/src/microservices/nest-microservice.ts @@ -20,6 +20,11 @@ const { IoAdapter } = optional('@nestjs/websockets/adapters/io-adapter') || {} a export class NestMicroservice implements INestMicroservice { private readonly logger = new Logger(NestMicroservice.name, true); + private readonly microservicesModule = new MicroservicesModule(); + private readonly socketModule = SocketModule + ? new SocketModule() + : null; + private readonly microserviceConfig: MicroserviceConfiguration; private readonly server: Server & CustomTransportStrategy; private readonly config: ApplicationConfig; @@ -34,7 +39,7 @@ export class NestMicroservice implements INestMicroservice { const ioAdapter = IoAdapter ? new IoAdapter() : null; this.config = new ApplicationConfig(ioAdapter); - MicroservicesModule.setup(container, this.config); + this.microservicesModule.setup(container, this.config); this.microserviceConfig = { transport: Transport.TCP, ...config, @@ -44,8 +49,8 @@ export class NestMicroservice implements INestMicroservice { } public setupModules() { - SocketModule && SocketModule.setup(this.container, this.config); - MicroservicesModule.setupClients(this.container); + this.socketModule && this.socketModule.setup(this.container, this.config); + this.microservicesModule.setupClients(this.container); this.setupListeners(); this.setIsInitialized(true); @@ -54,7 +59,7 @@ export class NestMicroservice implements INestMicroservice { } public setupListeners() { - MicroservicesModule.setupListeners(this.container, this.server); + this.microservicesModule.setupListeners(this.container, this.server); } public useWebSocketAdapter(adapter: WebSocketAdapter) { @@ -102,7 +107,7 @@ export class NestMicroservice implements INestMicroservice { } private closeApplication() { - SocketModule && SocketModule.close(); + this.socketModule && this.socketModule.close(); this.callDestroyHook(); this.setIsTerminated(true); diff --git a/src/websockets/socket-module.ts b/src/websockets/socket-module.ts index 00a2d5602c8..e7182f86af2 100644 --- a/src/websockets/socket-module.ts +++ b/src/websockets/socket-module.ts @@ -18,24 +18,23 @@ import { InterceptorsContextCreator } from '@nestjs/core/interceptors/intercepto import { InterceptorsConsumer } from '@nestjs/core/interceptors/interceptors-consumer'; export class SocketModule { - private static socketsContainer = new SocketsContainer(); - private static webSocketsController: WebSocketsController; + private socketsContainer = new SocketsContainer(); + private webSocketsController: WebSocketsController; - public static setup(container, config) { + public setup(container, config) { this.webSocketsController = new WebSocketsController( new SocketServerProvider(this.socketsContainer, config), container, config, this.getContextCreator(container), ); - const modules = container.getModules(); modules.forEach(({ components }, moduleName) => this.hookGatewaysIntoServers(components, moduleName)); } - public static hookGatewaysIntoServers(components: Map>, moduleName: string) { + public hookGatewaysIntoServers(components: Map>, moduleName: string) { components.forEach((wrapper) => this.hookGatewayIntoServer(wrapper, moduleName)); } - public static hookGatewayIntoServer(wrapper: InstanceWrapper, moduleName: string) { + public hookGatewayIntoServer(wrapper: InstanceWrapper, moduleName: string) { const { instance, metatype, isNotMetatype } = wrapper; if (isNotMetatype) { return; @@ -51,13 +50,13 @@ export class SocketModule { ); } - public static close() { + public close() { const servers = this.socketsContainer.getAllServers(); servers.forEach(({ server }) => server.close()); this.socketsContainer.clear(); } - private static getContextCreator(container): WsContextCreator { + private getContextCreator(container): WsContextCreator { return new WsContextCreator( new WsProxy(), new ExceptionFiltersContext(), From be23161bd4ede829cca24f4df692791050ce5751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Thu, 23 Nov 2017 20:47:35 +0100 Subject: [PATCH 29/34] v4.3.6 --- lerna.json | 2 +- lib/common/package.json | 18 ++++++++++++++++++ lib/core/package.json | 21 +++++++++++++++++++++ lib/microservices/package.json | 22 ++++++++++++++++++++++ lib/testing/package.json | 17 +++++++++++++++++ lib/websockets/package.json | 20 ++++++++++++++++++++ 6 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 lib/common/package.json create mode 100644 lib/core/package.json create mode 100644 lib/microservices/package.json create mode 100644 lib/testing/package.json create mode 100644 lib/websockets/package.json diff --git a/lerna.json b/lerna.json index 3b40b6bd23e..86c20526c0d 100644 --- a/lerna.json +++ b/lerna.json @@ -3,5 +3,5 @@ "packages": [ "lib/*" ], - "version": "4.3.4" + "version": "4.3.6" } diff --git a/lib/common/package.json b/lib/common/package.json new file mode 100644 index 00000000000..8c3adc98458 --- /dev/null +++ b/lib/common/package.json @@ -0,0 +1,18 @@ +{ + "name": "@nestjs/common", + "version": "4.3.6", + "description": "Nest - modern, fast, powerful node.js web framework (@common)", + "author": "Kamil Mysliwiec", + "license": "MIT", + "scripts": { + "compile": "tsc -p tsconfig.json" + }, + "dependencies": { + "class-transformer": "0.1.8", + "class-validator": "0.7.3", + "cli-color": "1.1.0" + }, + "peerDependencies": { + "reflect-metadata": "0.1.10" + } +} diff --git a/lib/core/package.json b/lib/core/package.json new file mode 100644 index 00000000000..a0d6fe90a48 --- /dev/null +++ b/lib/core/package.json @@ -0,0 +1,21 @@ +{ + "name": "@nestjs/core", + "version": "4.3.6", + "description": "Nest - modern, fast, powerful node.js web framework (@core)", + "author": "Kamil Mysliwiec", + "license": "MIT", + "scripts": { + "compile": "tsc -p tsconfig.json" + }, + "dependencies": { + "body-parser": "1.17.2", + "express": "4.16.2", + "iterare": "0.0.8", + "optional": "0.1.4" + }, + "peerDependencies": { + "@nestjs/common": "^4.*", + "reflect-metadata": "0.1.10", + "rxjs": "^5.4.2" + } +} diff --git a/lib/microservices/package.json b/lib/microservices/package.json new file mode 100644 index 00000000000..d472e57596c --- /dev/null +++ b/lib/microservices/package.json @@ -0,0 +1,22 @@ +{ + "name": "@nestjs/microservices", + "version": "4.3.6", + "description": "Nest - modern, fast, powerful node.js web framework (@microservices)", + "author": "Kamil Mysliwiec", + "license": "MIT", + "scripts": { + "compile": "tsc -p tsconfig.json" + }, + "dependencies": { + "iterare": "0.0.8", + "json-socket": "^0.2.1", + "optional": "0.1.4", + "redis": "^2.7.1" + }, + "peerDependencies": { + "@nestjs/common": "^4.*", + "@nestjs/core": "^4.*", + "reflect-metadata": "0.1.10", + "rxjs": "^5.4.2" + } +} diff --git a/lib/testing/package.json b/lib/testing/package.json new file mode 100644 index 00000000000..82fe3cad413 --- /dev/null +++ b/lib/testing/package.json @@ -0,0 +1,17 @@ +{ + "name": "@nestjs/testing", + "version": "4.3.6", + "description": "Nest - modern, fast, powerful node.js web framework (@testing)", + "author": "Kamil Mysliwiec", + "license": "MIT", + "scripts": { + "compile": "tsc -p tsconfig.json" + }, + "dependencies": { + "optional": "0.1.4" + }, + "peerDependencies": { + "@nestjs/common": "^4.*", + "@nestjs/core": "^4.*" + } +} diff --git a/lib/websockets/package.json b/lib/websockets/package.json new file mode 100644 index 00000000000..4400a504c56 --- /dev/null +++ b/lib/websockets/package.json @@ -0,0 +1,20 @@ +{ + "name": "@nestjs/websockets", + "version": "4.3.6", + "description": "Nest - modern, fast, powerful node.js web framework (@websockets)", + "author": "Kamil Mysliwiec", + "license": "MIT", + "scripts": { + "compile": "tsc -p tsconfig.json" + }, + "dependencies": { + "iterare": "0.0.8", + "socket.io": "^2.0.3" + }, + "peerDependencies": { + "@nestjs/common": "^4.*", + "@nestjs/core": "^4.*", + "reflect-metadata": "0.1.10", + "rxjs": "^5.4.2" + } +} From 21a901e8ffe1e857e0bfe0e42ac055a2e04b812a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Thu, 23 Nov 2017 20:50:56 +0100 Subject: [PATCH 30/34] Update .gitignore --- .gitignore | 3 --- lib/common/package.json | 18 ------------------ lib/core/package.json | 21 --------------------- lib/microservices/package.json | 22 ---------------------- lib/testing/package.json | 17 ----------------- lib/websockets/package.json | 20 -------------------- 6 files changed, 101 deletions(-) delete mode 100644 lib/common/package.json delete mode 100644 lib/core/package.json delete mode 100644 lib/microservices/package.json delete mode 100644 lib/testing/package.json delete mode 100644 lib/websockets/package.json diff --git a/.gitignore b/.gitignore index 6d09685aa6f..6aef99327ac 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,3 @@ npm-debug.log /test /coverage /.nyc_output - -# build -/lib \ No newline at end of file diff --git a/lib/common/package.json b/lib/common/package.json deleted file mode 100644 index 8c3adc98458..00000000000 --- a/lib/common/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "@nestjs/common", - "version": "4.3.6", - "description": "Nest - modern, fast, powerful node.js web framework (@common)", - "author": "Kamil Mysliwiec", - "license": "MIT", - "scripts": { - "compile": "tsc -p tsconfig.json" - }, - "dependencies": { - "class-transformer": "0.1.8", - "class-validator": "0.7.3", - "cli-color": "1.1.0" - }, - "peerDependencies": { - "reflect-metadata": "0.1.10" - } -} diff --git a/lib/core/package.json b/lib/core/package.json deleted file mode 100644 index a0d6fe90a48..00000000000 --- a/lib/core/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "@nestjs/core", - "version": "4.3.6", - "description": "Nest - modern, fast, powerful node.js web framework (@core)", - "author": "Kamil Mysliwiec", - "license": "MIT", - "scripts": { - "compile": "tsc -p tsconfig.json" - }, - "dependencies": { - "body-parser": "1.17.2", - "express": "4.16.2", - "iterare": "0.0.8", - "optional": "0.1.4" - }, - "peerDependencies": { - "@nestjs/common": "^4.*", - "reflect-metadata": "0.1.10", - "rxjs": "^5.4.2" - } -} diff --git a/lib/microservices/package.json b/lib/microservices/package.json deleted file mode 100644 index d472e57596c..00000000000 --- a/lib/microservices/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@nestjs/microservices", - "version": "4.3.6", - "description": "Nest - modern, fast, powerful node.js web framework (@microservices)", - "author": "Kamil Mysliwiec", - "license": "MIT", - "scripts": { - "compile": "tsc -p tsconfig.json" - }, - "dependencies": { - "iterare": "0.0.8", - "json-socket": "^0.2.1", - "optional": "0.1.4", - "redis": "^2.7.1" - }, - "peerDependencies": { - "@nestjs/common": "^4.*", - "@nestjs/core": "^4.*", - "reflect-metadata": "0.1.10", - "rxjs": "^5.4.2" - } -} diff --git a/lib/testing/package.json b/lib/testing/package.json deleted file mode 100644 index 82fe3cad413..00000000000 --- a/lib/testing/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "@nestjs/testing", - "version": "4.3.6", - "description": "Nest - modern, fast, powerful node.js web framework (@testing)", - "author": "Kamil Mysliwiec", - "license": "MIT", - "scripts": { - "compile": "tsc -p tsconfig.json" - }, - "dependencies": { - "optional": "0.1.4" - }, - "peerDependencies": { - "@nestjs/common": "^4.*", - "@nestjs/core": "^4.*" - } -} diff --git a/lib/websockets/package.json b/lib/websockets/package.json deleted file mode 100644 index 4400a504c56..00000000000 --- a/lib/websockets/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "@nestjs/websockets", - "version": "4.3.6", - "description": "Nest - modern, fast, powerful node.js web framework (@websockets)", - "author": "Kamil Mysliwiec", - "license": "MIT", - "scripts": { - "compile": "tsc -p tsconfig.json" - }, - "dependencies": { - "iterare": "0.0.8", - "socket.io": "^2.0.3" - }, - "peerDependencies": { - "@nestjs/common": "^4.*", - "@nestjs/core": "^4.*", - "reflect-metadata": "0.1.10", - "rxjs": "^5.4.2" - } -} From 3085b983bb2e235f3af656a93e47d7ff1f8c48bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Thu, 23 Nov 2017 21:14:38 +0100 Subject: [PATCH 31/34] v4.3.10 --- lerna.json | 2 +- lib/common/package.json | 18 ++++++++++++++++++ lib/core/package.json | 21 +++++++++++++++++++++ lib/microservices/package.json | 22 ++++++++++++++++++++++ lib/testing/package.json | 17 +++++++++++++++++ lib/websockets/package.json | 20 ++++++++++++++++++++ 6 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 lib/common/package.json create mode 100644 lib/core/package.json create mode 100644 lib/microservices/package.json create mode 100644 lib/testing/package.json create mode 100644 lib/websockets/package.json diff --git a/lerna.json b/lerna.json index 86c20526c0d..8010ce4885d 100644 --- a/lerna.json +++ b/lerna.json @@ -3,5 +3,5 @@ "packages": [ "lib/*" ], - "version": "4.3.6" + "version": "4.3.10" } diff --git a/lib/common/package.json b/lib/common/package.json new file mode 100644 index 00000000000..5922bf10d70 --- /dev/null +++ b/lib/common/package.json @@ -0,0 +1,18 @@ +{ + "name": "@nestjs/common", + "version": "4.3.10", + "description": "Nest - modern, fast, powerful node.js web framework (@common)", + "author": "Kamil Mysliwiec", + "license": "MIT", + "scripts": { + "compile": "tsc -p tsconfig.json" + }, + "dependencies": { + "class-transformer": "0.1.8", + "class-validator": "0.7.3", + "cli-color": "1.1.0" + }, + "peerDependencies": { + "reflect-metadata": "0.1.10" + } +} diff --git a/lib/core/package.json b/lib/core/package.json new file mode 100644 index 00000000000..3c6055d0fbf --- /dev/null +++ b/lib/core/package.json @@ -0,0 +1,21 @@ +{ + "name": "@nestjs/core", + "version": "4.3.10", + "description": "Nest - modern, fast, powerful node.js web framework (@core)", + "author": "Kamil Mysliwiec", + "license": "MIT", + "scripts": { + "compile": "tsc -p tsconfig.json" + }, + "dependencies": { + "body-parser": "1.17.2", + "express": "4.16.2", + "iterare": "0.0.8", + "optional": "0.1.4" + }, + "peerDependencies": { + "@nestjs/common": "^4.*", + "reflect-metadata": "0.1.10", + "rxjs": "^5.4.2" + } +} diff --git a/lib/microservices/package.json b/lib/microservices/package.json new file mode 100644 index 00000000000..e373e4708d4 --- /dev/null +++ b/lib/microservices/package.json @@ -0,0 +1,22 @@ +{ + "name": "@nestjs/microservices", + "version": "4.3.10", + "description": "Nest - modern, fast, powerful node.js web framework (@microservices)", + "author": "Kamil Mysliwiec", + "license": "MIT", + "scripts": { + "compile": "tsc -p tsconfig.json" + }, + "dependencies": { + "iterare": "0.0.8", + "json-socket": "^0.2.1", + "optional": "0.1.4", + "redis": "^2.7.1" + }, + "peerDependencies": { + "@nestjs/common": "^4.*", + "@nestjs/core": "^4.*", + "reflect-metadata": "0.1.10", + "rxjs": "^5.4.2" + } +} diff --git a/lib/testing/package.json b/lib/testing/package.json new file mode 100644 index 00000000000..6555dd42b40 --- /dev/null +++ b/lib/testing/package.json @@ -0,0 +1,17 @@ +{ + "name": "@nestjs/testing", + "version": "4.3.10", + "description": "Nest - modern, fast, powerful node.js web framework (@testing)", + "author": "Kamil Mysliwiec", + "license": "MIT", + "scripts": { + "compile": "tsc -p tsconfig.json" + }, + "dependencies": { + "optional": "0.1.4" + }, + "peerDependencies": { + "@nestjs/common": "^4.*", + "@nestjs/core": "^4.*" + } +} diff --git a/lib/websockets/package.json b/lib/websockets/package.json new file mode 100644 index 00000000000..faf3a27fdf8 --- /dev/null +++ b/lib/websockets/package.json @@ -0,0 +1,20 @@ +{ + "name": "@nestjs/websockets", + "version": "4.3.10", + "description": "Nest - modern, fast, powerful node.js web framework (@websockets)", + "author": "Kamil Mysliwiec", + "license": "MIT", + "scripts": { + "compile": "tsc -p tsconfig.json" + }, + "dependencies": { + "iterare": "0.0.8", + "socket.io": "^2.0.3" + }, + "peerDependencies": { + "@nestjs/common": "^4.*", + "@nestjs/core": "^4.*", + "reflect-metadata": "0.1.10", + "rxjs": "^5.4.2" + } +} From b34b24e75c48f541987546086689f0bc42916c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Thu, 23 Nov 2017 21:21:26 +0100 Subject: [PATCH 32/34] chore(release) publish v4.4.0 --- lerna.json | 2 +- lib/common/package.json | 5 +---- lib/core/package.json | 5 +---- lib/microservices/package.json | 5 +---- lib/testing/package.json | 5 +---- lib/websockets/package.json | 5 +---- 6 files changed, 6 insertions(+), 21 deletions(-) diff --git a/lerna.json b/lerna.json index 8010ce4885d..fa806d7cee1 100644 --- a/lerna.json +++ b/lerna.json @@ -3,5 +3,5 @@ "packages": [ "lib/*" ], - "version": "4.3.10" + "version": "4.4.0" } diff --git a/lib/common/package.json b/lib/common/package.json index 5922bf10d70..fed0d9c1847 100644 --- a/lib/common/package.json +++ b/lib/common/package.json @@ -1,12 +1,9 @@ { "name": "@nestjs/common", - "version": "4.3.10", + "version": "4.4.0", "description": "Nest - modern, fast, powerful node.js web framework (@common)", "author": "Kamil Mysliwiec", "license": "MIT", - "scripts": { - "compile": "tsc -p tsconfig.json" - }, "dependencies": { "class-transformer": "0.1.8", "class-validator": "0.7.3", diff --git a/lib/core/package.json b/lib/core/package.json index 3c6055d0fbf..b6f67327946 100644 --- a/lib/core/package.json +++ b/lib/core/package.json @@ -1,12 +1,9 @@ { "name": "@nestjs/core", - "version": "4.3.10", + "version": "4.4.0", "description": "Nest - modern, fast, powerful node.js web framework (@core)", "author": "Kamil Mysliwiec", "license": "MIT", - "scripts": { - "compile": "tsc -p tsconfig.json" - }, "dependencies": { "body-parser": "1.17.2", "express": "4.16.2", diff --git a/lib/microservices/package.json b/lib/microservices/package.json index e373e4708d4..3d5fccd7927 100644 --- a/lib/microservices/package.json +++ b/lib/microservices/package.json @@ -1,12 +1,9 @@ { "name": "@nestjs/microservices", - "version": "4.3.10", + "version": "4.4.0", "description": "Nest - modern, fast, powerful node.js web framework (@microservices)", "author": "Kamil Mysliwiec", "license": "MIT", - "scripts": { - "compile": "tsc -p tsconfig.json" - }, "dependencies": { "iterare": "0.0.8", "json-socket": "^0.2.1", diff --git a/lib/testing/package.json b/lib/testing/package.json index 6555dd42b40..1c2ed35cefe 100644 --- a/lib/testing/package.json +++ b/lib/testing/package.json @@ -1,12 +1,9 @@ { "name": "@nestjs/testing", - "version": "4.3.10", + "version": "4.4.0", "description": "Nest - modern, fast, powerful node.js web framework (@testing)", "author": "Kamil Mysliwiec", "license": "MIT", - "scripts": { - "compile": "tsc -p tsconfig.json" - }, "dependencies": { "optional": "0.1.4" }, diff --git a/lib/websockets/package.json b/lib/websockets/package.json index faf3a27fdf8..b8796ffe0e9 100644 --- a/lib/websockets/package.json +++ b/lib/websockets/package.json @@ -1,12 +1,9 @@ { "name": "@nestjs/websockets", - "version": "4.3.10", + "version": "4.4.0", "description": "Nest - modern, fast, powerful node.js web framework (@websockets)", "author": "Kamil Mysliwiec", "license": "MIT", - "scripts": { - "compile": "tsc -p tsconfig.json" - }, "dependencies": { "iterare": "0.0.8", "socket.io": "^2.0.3" From a82180926cadb099de8fd2df25e708f18cd02fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Thu, 23 Nov 2017 21:26:11 +0100 Subject: [PATCH 33/34] update(@nestjs) configure lerna to use git tags --- lib/common/LICENSE | 22 ++ lib/common/Readme.md | 125 ++++++++++ lib/common/constants.d.ts | 20 ++ lib/common/constants.js | 22 ++ lib/common/enums/http-status.enum.d.ts | 45 ++++ lib/common/enums/http-status.enum.js | 48 ++++ lib/common/enums/index.d.ts | 2 + lib/common/enums/index.js | 7 + lib/common/enums/nest-environment.enum.d.ts | 4 + lib/common/enums/nest-environment.enum.js | 7 + lib/common/enums/request-method.enum.d.ts | 10 + lib/common/enums/request-method.enum.js | 13 + lib/common/enums/route-paramtypes.enum.d.ts | 10 + lib/common/enums/route-paramtypes.enum.js | 13 + lib/common/enums/transport.enum.d.ts | 4 + lib/common/enums/transport.enum.js | 7 + .../exceptions/bad-gateway.exception.d.ts | 4 + .../exceptions/bad-gateway.exception.js | 11 + .../exceptions/bad-request.exception.d.ts | 4 + .../exceptions/bad-request.exception.js | 11 + lib/common/exceptions/conflict.exception.d.ts | 4 + lib/common/exceptions/conflict.exception.js | 11 + lib/common/exceptions/constants.d.ts | 1 + lib/common/exceptions/constants.js | 3 + .../exceptions/forbidden.exception.d.ts | 4 + lib/common/exceptions/forbidden.exception.js | 11 + .../exceptions/gateway-timeout.exception.d.ts | 4 + .../exceptions/gateway-timeout.exception.js | 11 + lib/common/exceptions/gone.exception.d.ts | 4 + lib/common/exceptions/gone.exception.js | 11 + lib/common/exceptions/http.exception.d.ts | 21 ++ lib/common/exceptions/http.exception.js | 29 +++ lib/common/exceptions/index.d.ts | 18 ++ lib/common/exceptions/index.js | 23 ++ .../internal-server-error.exception.d.ts | 4 + .../internal-server-error.exception.js | 11 + .../invalid-module-config.exception.d.ts | 3 + .../invalid-module-config.exception.js | 9 + .../method-not-allowed.exception.d.ts | 4 + .../method-not-allowed.exception.js | 11 + .../exceptions/not-acceptable.exception.d.ts | 4 + .../exceptions/not-acceptable.exception.js | 11 + .../exceptions/not-found.exception.d.ts | 4 + lib/common/exceptions/not-found.exception.js | 11 + .../exceptions/not-implemented.exception.d.ts | 4 + .../exceptions/not-implemented.exception.js | 11 + .../payload-too-large.exception.d.ts | 4 + .../exceptions/payload-too-large.exception.js | 11 + .../exceptions/request-timeout.exception.d.ts | 4 + .../exceptions/request-timeout.exception.js | 11 + .../service-unavailable.exception.d.ts | 4 + .../service-unavailable.exception.js | 11 + .../exceptions/unauthorized.exception.d.ts | 4 + .../exceptions/unauthorized.exception.js | 11 + .../unprocessable-entity.exception.d.ts | 4 + .../unprocessable-entity.exception.js | 11 + .../unsupported-media-type.exception.d.ts | 4 + .../unsupported-media-type.exception.js | 11 + lib/common/index.d.ts | 6 + lib/common/index.js | 16 ++ .../interfaces/can-activate.interface.d.ts | 5 + .../interfaces/can-activate.interface.js | 2 + .../configuration-provider.interface.d.ts | 6 + .../configuration-provider.interface.js | 2 + .../controller-metadata.interface.d.ts | 3 + .../controller-metadata.interface.js | 2 + .../controllers/controller.interface.d.ts | 2 + .../controllers/controller.interface.js | 2 + lib/common/interfaces/controllers/index.d.ts | 2 + lib/common/interfaces/controllers/index.js | 2 + .../custom-route-param-factory.interface.d.ts | 1 + .../custom-route-param-factory.interface.js | 2 + .../exception-filter-metadata.interface.d.ts | 6 + .../exception-filter-metadata.interface.js | 2 + .../exception-filter.interface.d.ts | 3 + .../exceptions/exception-filter.interface.js | 2 + lib/common/interfaces/exceptions/index.d.ts | 5 + lib/common/interfaces/exceptions/index.js | 2 + ...c-exception-filter-metadata.interface.d.ts | 6 + ...rpc-exception-filter-metadata.interface.js | 2 + .../rpc-exception-filter.interface.d.ts | 4 + .../rpc-exception-filter.interface.js | 2 + .../ws-exception-filter.interface.d.ts | 3 + .../ws-exception-filter.interface.js | 2 + .../execution-context.interface.d.ts | 4 + .../interfaces/execution-context.interface.js | 2 + lib/common/interfaces/index.d.ts | 24 ++ lib/common/interfaces/index.js | 2 + .../interfaces/injectable.interface.d.ts | 2 + lib/common/interfaces/injectable.interface.js | 2 + lib/common/interfaces/metatype.interface.d.ts | 3 + lib/common/interfaces/metatype.interface.js | 2 + .../custom-transport-strategy.interface.d.ts | 4 + .../custom-transport-strategy.interface.js | 2 + .../microservice-configuration.interface.d.ts | 9 + .../microservice-configuration.interface.js | 2 + .../express-middleware.interface.d.ts | 3 + .../express-middleware.interface.js | 2 + .../express-midleware.interface.d.ts | 3 + .../express-midleware.interface.js | 2 + lib/common/interfaces/middlewares/index.d.ts | 5 + lib/common/interfaces/middlewares/index.js | 2 + .../middleware-config-proxy.interface.d.ts | 24 ++ .../middleware-config-proxy.interface.js | 2 + .../middleware-configuration.interface.d.ts | 9 + .../middleware-configuration.interface.js | 2 + .../middlewares-consumer.interface.d.ts | 11 + .../middlewares-consumer.interface.js | 2 + .../nest-middleware.interface.d.ts | 5 + .../middlewares/nest-middleware.interface.js | 2 + lib/common/interfaces/modules/index.d.ts | 4 + lib/common/interfaces/modules/index.js | 2 + .../modules/module-metadata.interface.d.ts | 8 + .../modules/module-metadata.interface.js | 2 + .../modules/module-metatype.interface.d.ts | 4 + .../modules/module-metatype.interface.js | 2 + .../modules/nest-module.interface.d.ts | 4 + .../modules/nest-module.interface.js | 2 + .../modules/on-destroy.interface.d.ts | 3 + .../modules/on-destroy.interface.js | 2 + .../interfaces/modules/on-init.interface.d.ts | 3 + .../interfaces/modules/on-init.interface.js | 2 + .../nest-application-context.interface.d.ts | 13 + .../nest-application-context.interface.js | 2 + .../nest-application.interface.d.ts | 110 +++++++++ .../interfaces/nest-application.interface.js | 2 + .../nest-interceptor.interface.d.ts | 5 + .../interfaces/nest-interceptor.interface.js | 2 + .../nest-microservice.interface.d.ts | 52 ++++ .../interfaces/nest-microservice.interface.js | 2 + .../interfaces/paramtype.interface.d.ts | 1 + lib/common/interfaces/paramtype.interface.js | 2 + .../interfaces/pipe-transform.interface.d.ts | 10 + .../interfaces/pipe-transform.interface.js | 2 + .../request-mapping-metadata.interface.d.ts | 5 + .../request-mapping-metadata.interface.js | 2 + .../web-socket-adapter.interface.d.ts | 10 + .../web-socket-adapter.interface.js | 2 + lib/common/pipes/index.d.ts | 2 + lib/common/pipes/index.js | 7 + lib/common/pipes/parse-int.pipe.d.ts | 5 + lib/common/pipes/parse-int.pipe.js | 33 +++ lib/common/pipes/validation.pipe.d.ts | 6 + lib/common/pipes/validation.pipe.js | 43 ++++ lib/common/services/logger.service.d.ts | 16 ++ lib/common/services/logger.service.js | 50 ++++ .../utils/bind-resolve-values.util.d.ts | 3 + lib/common/utils/bind-resolve-values.util.js | 16 ++ .../utils/decorators/bind.decorator.d.ts | 6 + lib/common/utils/decorators/bind.decorator.js | 14 ++ .../utils/decorators/catch.decorator.d.ts | 6 + .../utils/decorators/catch.decorator.js | 14 ++ .../utils/decorators/component.decorator.d.ts | 22 ++ .../utils/decorators/component.decorator.js | 45 ++++ .../decorators/controller.decorator.d.ts | 6 + .../utils/decorators/controller.decorator.js | 16 ++ ...create-route-param-metadata.decorator.d.ts | 7 + .../create-route-param-metadata.decorator.js | 20 ++ .../decorators/dependencies.decorator.d.ts | 2 + .../decorators/dependencies.decorator.js | 14 ++ .../exception-filters.decorator.d.ts | 13 + .../decorators/exception-filters.decorator.js | 25 ++ .../decorators/exceptions/constants.d.ts | 1 + .../utils/decorators/exceptions/constants.js | 3 + .../invalid-module-config.exception.d.ts | 3 + .../invalid-module-config.exception.js | 9 + .../utils/decorators/http-code.decorator.d.ts | 7 + .../utils/decorators/http-code.decorator.js | 16 ++ .../utils/decorators/inject.decorator.d.ts | 6 + .../utils/decorators/inject.decorator.js | 18 ++ .../utils/decorators/module.decorator.d.ts | 15 ++ .../utils/decorators/module.decorator.js | 40 +++ .../reflect-metadata.decorator.d.ts | 5 + .../decorators/reflect-metadata.decorator.js | 14 ++ .../decorators/request-mapping.decorator.d.ts | 35 +++ .../decorators/request-mapping.decorator.js | 56 +++++ .../decorators/route-params.decorator.d.ts | 25 ++ .../decorators/route-params.decorator.js | 43 ++++ .../utils/decorators/shared.decorator.d.ts | 7 + .../utils/decorators/shared.decorator.js | 25 ++ .../decorators/single-scope.decorator.d.ts | 6 + .../decorators/single-scope.decorator.js | 23 ++ .../decorators/use-guards.decorator.d.ts | 11 + .../utils/decorators/use-guards.decorator.js | 24 ++ .../use-interceptors.decorator.d.ts | 11 + .../decorators/use-interceptors.decorator.js | 24 ++ .../utils/decorators/use-pipes.decorator.d.ts | 12 + .../utils/decorators/use-pipes.decorator.js | 24 ++ lib/common/utils/forward-ref.util.d.ts | 3 + lib/common/utils/forward-ref.util.js | 6 + .../utils/http-exception-body.util.d.ts | 8 + lib/common/utils/http-exception-body.util.js | 5 + lib/common/utils/index.d.ts | 19 ++ lib/common/utils/index.js | 24 ++ lib/common/utils/merge-with-values.util.d.ts | 7 + lib/common/utils/merge-with-values.util.js | 16 ++ lib/common/utils/shared.utils.d.ts | 8 + lib/common/utils/shared.utils.js | 10 + lib/core/LICENSE | 22 ++ lib/core/Readme.md | 125 ++++++++++ lib/core/adapters/express-adapter.d.ts | 4 + lib/core/adapters/express-adapter.js | 12 + lib/core/application-config.d.ts | 23 ++ lib/core/application-config.js | 49 ++++ lib/core/constants.d.ts | 6 + lib/core/constants.js | 8 + lib/core/errors/exception-handler.d.ts | 5 + lib/core/errors/exception-handler.js | 15 ++ lib/core/errors/exceptions-zone.d.ts | 5 + lib/core/errors/exceptions-zone.js | 36 +++ .../invalid-exception-filter.exception.d.ts | 4 + .../invalid-exception-filter.exception.js | 10 + ...id-middleware-configuration.exception.d.ts | 4 + ...alid-middleware-configuration.exception.js | 10 + .../invalid-middleware.exception.d.ts | 4 + .../invalid-middleware.exception.js | 10 + .../exceptions/invalid-module.exception.d.ts | 4 + .../exceptions/invalid-module.exception.js | 11 + ...oservices-package-not-found.exception.d.ts | 4 + ...croservices-package-not-found.exception.js | 10 + .../errors/exceptions/runtime.exception.d.ts | 11 + .../errors/exceptions/runtime.exception.js | 12 + .../undefined-dependency.exception.d.ts | 4 + .../undefined-dependency.exception.js | 10 + .../unknown-dependencies.exception.d.ts | 4 + .../unknown-dependencies.exception.js | 10 + .../exceptions/unknown-export.exception.d.ts | 4 + .../exceptions/unknown-export.exception.js | 10 + .../exceptions/unknown-module.exception.d.ts | 4 + .../exceptions/unknown-module.exception.js | 9 + .../unknown-request-mapping.exception.d.ts | 4 + .../unknown-request-mapping.exception.js | 10 + lib/core/errors/messages.d.ts | 9 + lib/core/errors/messages.js | 19 ++ .../base-exception-filter-context.d.ts | 8 + .../base-exception-filter-context.js | 26 ++ lib/core/exceptions/exceptions-handler.d.ts | 9 + lib/core/exceptions/exceptions-handler.js | 51 ++++ lib/core/exceptions/http-exception.d.ts | 23 ++ lib/core/exceptions/http-exception.js | 33 +++ lib/core/guards/constants.d.ts | 1 + lib/core/guards/constants.js | 3 + lib/core/guards/guards-consumer.d.ts | 9 + lib/core/guards/guards-consumer.js | 49 ++++ lib/core/guards/guards-context-creator.d.ts | 19 ++ lib/core/guards/guards-context-creator.js | 52 ++++ lib/core/helpers/context-creator.d.ts | 9 + lib/core/helpers/context-creator.js | 23 ++ lib/core/helpers/messages.d.ts | 3 + lib/core/helpers/messages.js | 6 + lib/core/helpers/router-method-factory.d.ts | 4 + lib/core/helpers/router-method-factory.js | 20 ++ lib/core/index.d.ts | 7 + lib/core/index.js | 21 ++ lib/core/injector/container.d.ts | 32 +++ lib/core/injector/container.js | 72 ++++++ lib/core/injector/injector.d.ts | 53 ++++ lib/core/injector/injector.js | 228 ++++++++++++++++++ lib/core/injector/instance-loader.d.ts | 16 ++ lib/core/injector/instance-loader.js | 78 ++++++ lib/core/injector/module-ref.d.ts | 4 + lib/core/injector/module-ref.js | 5 + lib/core/injector/module-token-factory.d.ts | 7 + lib/core/injector/module-token-factory.js | 29 +++ lib/core/injector/module.d.ts | 63 +++++ lib/core/injector/module.js | 192 +++++++++++++++ .../interceptors/interceptors-consumer.d.ts | 11 + .../interceptors/interceptors-consumer.js | 40 +++ .../interceptors-context-creator.d.ts | 18 ++ .../interceptors-context-creator.js | 52 ++++ lib/core/metadata-scanner.d.ts | 4 + lib/core/metadata-scanner.js | 20 ++ lib/core/middlewares/builder.d.ts | 19 ++ lib/core/middlewares/builder.js | 65 +++++ lib/core/middlewares/container.d.ts | 16 ++ lib/core/middlewares/container.js | 42 ++++ lib/core/middlewares/middlewares-module.d.ts | 25 ++ lib/core/middlewares/middlewares-module.js | 108 +++++++++ lib/core/middlewares/resolver.d.ts | 9 + lib/core/middlewares/resolver.js | 29 +++ lib/core/middlewares/routes-mapper.d.ts | 11 + lib/core/middlewares/routes-mapper.js | 43 ++++ lib/core/middlewares/utils.d.ts | 5 + lib/core/middlewares/utils.js | 26 ++ lib/core/nest-application-context.d.ts | 14 ++ lib/core/nest-application-context.js | 38 +++ lib/core/nest-application.d.ts | 46 ++++ lib/core/nest-application.js | 187 ++++++++++++++ lib/core/nest-factory.d.ts | 36 +++ lib/core/nest-factory.js | 117 +++++++++ lib/core/pipes/params-token-factory.d.ts | 5 + lib/core/pipes/params-token-factory.js | 14 ++ lib/core/pipes/pipes-consumer.d.ts | 14 ++ lib/core/pipes/pipes-consumer.js | 35 +++ lib/core/pipes/pipes-context-creator.d.ts | 11 + lib/core/pipes/pipes-context-creator.js | 31 +++ .../exceptions-filter.interface.d.ts | 5 + .../interfaces/exceptions-filter.interface.js | 2 + .../router/interfaces/explorer.inteface.d.ts | 6 + .../router/interfaces/explorer.inteface.js | 2 + .../router/interfaces/resolver.interface.d.ts | 3 + .../router/interfaces/resolver.interface.js | 2 + .../route-params-factory.interface.d.ts | 8 + .../route-params-factory.interface.js | 2 + lib/core/router/route-params-factory.d.ts | 9 + lib/core/router/route-params-factory.js | 19 ++ lib/core/router/router-exception-filters.d.ts | 12 + lib/core/router/router-exception-filters.js | 26 ++ lib/core/router/router-execution-context.d.ts | 47 ++++ lib/core/router/router-execution-context.js | 113 +++++++++ lib/core/router/router-explorer.d.ts | 36 +++ lib/core/router/router-explorer.js | 82 +++++++ lib/core/router/router-proxy.d.ts | 6 + lib/core/router/router-proxy.js | 31 +++ .../router/router-response-controller.d.ts | 7 + lib/core/router/router-response-controller.js | 45 ++++ lib/core/router/routes-resolver.d.ts | 19 ++ lib/core/router/routes-resolver.js | 42 ++++ lib/core/scanner.d.ts | 32 +++ lib/core/scanner.js | 111 +++++++++ lib/core/services/reflector.service.d.ts | 3 + lib/core/services/reflector.service.js | 8 + lib/microservices/LICENSE | 22 ++ lib/microservices/Readme.md | 125 ++++++++++ .../client/client-proxy-factory.d.ts | 6 + .../client/client-proxy-factory.js | 15 ++ lib/microservices/client/client-proxy.d.ts | 7 + lib/microservices/client/client-proxy.js | 29 +++ lib/microservices/client/client-redis.d.ts | 17 ++ lib/microservices/client/client-redis.js | 59 +++++ lib/microservices/client/client-tcp.d.ts | 16 ++ lib/microservices/client/client-tcp.js | 81 +++++++ lib/microservices/client/index.d.ts | 2 + lib/microservices/client/index.js | 7 + lib/microservices/constants.d.ts | 5 + lib/microservices/constants.js | 7 + lib/microservices/container.d.ts | 9 + lib/microservices/container.js | 17 ++ .../context/exception-filters-context.d.ts | 12 + .../context/exception-filters-context.js | 26 ++ .../context/rpc-context-creator.d.ts | 24 ++ .../context/rpc-context-creator.js | 49 ++++ lib/microservices/context/rpc-proxy.d.ts | 5 + lib/microservices/context/rpc-proxy.js | 23 ++ lib/microservices/enums/index.d.ts | 1 + lib/microservices/enums/index.js | 6 + lib/microservices/enums/transport.enum.d.ts | 4 + lib/microservices/enums/transport.enum.js | 7 + lib/microservices/exceptions/index.d.ts | 1 + lib/microservices/exceptions/index.js | 6 + .../exceptions/invalid-message.exception.d.ts | 4 + .../exceptions/invalid-message.exception.js | 9 + .../exceptions/rpc-exception.d.ts | 5 + lib/microservices/exceptions/rpc-exception.js | 11 + .../exceptions/rpc-exceptions-handler.d.ts | 10 + .../exceptions/rpc-exceptions-handler.js | 43 ++++ lib/microservices/index.d.ts | 7 + lib/microservices/index.js | 17 ++ .../interfaces/client-metadata.interface.d.ts | 7 + .../interfaces/client-metadata.interface.js | 2 + .../interfaces/closeable.interface.d.ts | 3 + .../interfaces/closeable.interface.js | 2 + .../custom-transport-strategy.interface.d.ts | 4 + .../custom-transport-strategy.interface.js | 2 + lib/microservices/interfaces/index.d.ts | 7 + lib/microservices/interfaces/index.js | 2 + .../message-handlers.interface.d.ts | 4 + .../interfaces/message-handlers.interface.js | 2 + .../microservice-configuration.interface.d.ts | 10 + .../microservice-configuration.interface.js | 2 + .../microservice-response.interface.d.ts | 5 + .../microservice-response.interface.js | 2 + .../pattern-metadata.interface.d.ts | 3 + .../interfaces/pattern-metadata.interface.js | 2 + .../listener-metadata-explorer.d.ts | 19 ++ .../listener-metadata-explorer.js | 38 +++ lib/microservices/listeners-controller.d.ts | 14 ++ lib/microservices/listeners-controller.js | 28 +++ lib/microservices/microservices-module.d.ts | 14 ++ lib/microservices/microservices-module.js | 56 +++++ lib/microservices/nest-microservice.d.ts | 35 +++ lib/microservices/nest-microservice.js | 114 +++++++++ lib/microservices/server/index.d.ts | 1 + lib/microservices/server/index.js | 6 + lib/microservices/server/server-factory.d.ts | 5 + lib/microservices/server/server-factory.js | 15 ++ lib/microservices/server/server-redis.d.ts | 25 ++ lib/microservices/server/server-redis.js | 92 +++++++ lib/microservices/server/server-tcp.d.ts | 19 ++ lib/microservices/server/server-tcp.js | 58 +++++ lib/microservices/server/server.d.ts | 19 ++ lib/microservices/server/server.js | 42 ++++ lib/microservices/utils/client.decorator.d.ts | 13 + lib/microservices/utils/client.decorator.js | 21 ++ lib/microservices/utils/index.d.ts | 2 + lib/microservices/utils/index.js | 7 + .../utils/pattern.decorator.d.ts | 6 + lib/microservices/utils/pattern.decorator.js | 14 ++ lib/testing/LICENSE | 22 ++ lib/testing/Readme.md | 125 ++++++++++ .../errors/unknown-module.exception.d.ts | 4 + .../errors/unknown-module.exception.js | 9 + lib/testing/index.d.ts | 2 + lib/testing/index.js | 12 + lib/testing/interfaces/index.d.ts | 2 + lib/testing/interfaces/index.js | 2 + ...override-by-factory-options.interface.d.ts | 4 + .../override-by-factory-options.interface.js | 2 + .../interfaces/override-by.interface.d.ts | 7 + .../interfaces/override-by.interface.js | 2 + lib/testing/test.d.ts | 7 + lib/testing/test.js | 17 ++ lib/testing/testing-module.builder.d.ts | 19 ++ lib/testing/testing-module.builder.js | 66 +++++ lib/testing/testing-module.d.ts | 10 + lib/testing/testing-module.js | 21 ++ lib/websockets/LICENSE | 22 ++ lib/websockets/Readme.md | 125 ++++++++++ lib/websockets/adapters/io-adapter.d.ts | 21 ++ lib/websockets/adapters/io-adapter.js | 42 ++++ lib/websockets/constants.d.ts | 9 + lib/websockets/constants.js | 11 + lib/websockets/container.d.ts | 8 + lib/websockets/container.js | 20 ++ .../context/exception-filters-context.d.ts | 8 + .../context/exception-filters-context.js | 22 ++ .../context/ws-context-creator.d.ts | 23 ++ lib/websockets/context/ws-context-creator.js | 49 ++++ lib/websockets/context/ws-proxy.d.ts | 4 + lib/websockets/context/ws-proxy.js | 23 ++ .../invalid-socket-port.exception.d.ts | 4 + .../invalid-socket-port.exception.js | 9 + lib/websockets/exceptions/ws-exception.d.ts | 5 + lib/websockets/exceptions/ws-exception.js | 11 + .../exceptions/ws-exceptions-handler.d.ts | 8 + .../exceptions/ws-exceptions-handler.js | 43 ++++ lib/websockets/gateway-metadata-explorer.d.ts | 14 ++ lib/websockets/gateway-metadata-explorer.js | 37 +++ lib/websockets/index.d.ts | 5 + lib/websockets/index.js | 14 ++ .../gateway-metadata.interface.d.ts | 7 + .../interfaces/gateway-metadata.interface.js | 2 + .../gateway-middleware.interface.d.ts | 3 + .../gateway-middleware.interface.js | 2 + lib/websockets/interfaces/index.d.ts | 9 + lib/websockets/interfaces/index.js | 2 + .../interfaces/nest-gateway.interface.d.ts | 5 + .../interfaces/nest-gateway.interface.js | 2 + .../observable-socket-server.interface.d.ts | 8 + .../observable-socket-server.interface.js | 2 + .../on-gateway-connection.interface.d.ts | 3 + .../on-gateway-connection.interface.js | 2 + .../on-gateway-disconnect.interface.d.ts | 3 + .../on-gateway-disconnect.interface.js | 2 + .../interfaces/on-gateway-init.interface.d.ts | 3 + .../interfaces/on-gateway-init.interface.js | 2 + .../web-socket-server.interface.d.ts | 4 + .../interfaces/web-socket-server.interface.js | 2 + .../interfaces/ws-response.interface.d.ts | 4 + .../interfaces/ws-response.interface.js | 2 + lib/websockets/middlewares-injector.d.ts | 16 ++ lib/websockets/middlewares-injector.js | 51 ++++ lib/websockets/observable-socket.d.ts | 4 + lib/websockets/observable-socket.js | 15 ++ lib/websockets/socket-module.d.ts | 12 + lib/websockets/socket-module.js | 49 ++++ lib/websockets/socket-server-provider.d.ts | 12 + lib/websockets/socket-server-provider.js | 31 +++ .../utils/gateway-server.decorator.d.ts | 5 + .../utils/gateway-server.decorator.js | 13 + lib/websockets/utils/index.d.ts | 3 + lib/websockets/utils/index.js | 8 + .../utils/socket-gateway.decorator.d.ts | 7 + .../utils/socket-gateway.decorator.js | 20 ++ .../utils/subscribe-message.decorator.d.ts | 7 + .../utils/subscribe-message.decorator.js | 17 ++ lib/websockets/web-sockets-controller.d.ts | 37 +++ lib/websockets/web-sockets-controller.js | 113 +++++++++ package.json | 2 +- 479 files changed, 8366 insertions(+), 1 deletion(-) create mode 100644 lib/common/LICENSE create mode 100644 lib/common/Readme.md create mode 100644 lib/common/constants.d.ts create mode 100644 lib/common/constants.js create mode 100644 lib/common/enums/http-status.enum.d.ts create mode 100644 lib/common/enums/http-status.enum.js create mode 100644 lib/common/enums/index.d.ts create mode 100644 lib/common/enums/index.js create mode 100644 lib/common/enums/nest-environment.enum.d.ts create mode 100644 lib/common/enums/nest-environment.enum.js create mode 100644 lib/common/enums/request-method.enum.d.ts create mode 100644 lib/common/enums/request-method.enum.js create mode 100644 lib/common/enums/route-paramtypes.enum.d.ts create mode 100644 lib/common/enums/route-paramtypes.enum.js create mode 100644 lib/common/enums/transport.enum.d.ts create mode 100644 lib/common/enums/transport.enum.js create mode 100644 lib/common/exceptions/bad-gateway.exception.d.ts create mode 100644 lib/common/exceptions/bad-gateway.exception.js create mode 100644 lib/common/exceptions/bad-request.exception.d.ts create mode 100644 lib/common/exceptions/bad-request.exception.js create mode 100644 lib/common/exceptions/conflict.exception.d.ts create mode 100644 lib/common/exceptions/conflict.exception.js create mode 100644 lib/common/exceptions/constants.d.ts create mode 100644 lib/common/exceptions/constants.js create mode 100644 lib/common/exceptions/forbidden.exception.d.ts create mode 100644 lib/common/exceptions/forbidden.exception.js create mode 100644 lib/common/exceptions/gateway-timeout.exception.d.ts create mode 100644 lib/common/exceptions/gateway-timeout.exception.js create mode 100644 lib/common/exceptions/gone.exception.d.ts create mode 100644 lib/common/exceptions/gone.exception.js create mode 100644 lib/common/exceptions/http.exception.d.ts create mode 100644 lib/common/exceptions/http.exception.js create mode 100644 lib/common/exceptions/index.d.ts create mode 100644 lib/common/exceptions/index.js create mode 100644 lib/common/exceptions/internal-server-error.exception.d.ts create mode 100644 lib/common/exceptions/internal-server-error.exception.js create mode 100644 lib/common/exceptions/invalid-module-config.exception.d.ts create mode 100644 lib/common/exceptions/invalid-module-config.exception.js create mode 100644 lib/common/exceptions/method-not-allowed.exception.d.ts create mode 100644 lib/common/exceptions/method-not-allowed.exception.js create mode 100644 lib/common/exceptions/not-acceptable.exception.d.ts create mode 100644 lib/common/exceptions/not-acceptable.exception.js create mode 100644 lib/common/exceptions/not-found.exception.d.ts create mode 100644 lib/common/exceptions/not-found.exception.js create mode 100644 lib/common/exceptions/not-implemented.exception.d.ts create mode 100644 lib/common/exceptions/not-implemented.exception.js create mode 100644 lib/common/exceptions/payload-too-large.exception.d.ts create mode 100644 lib/common/exceptions/payload-too-large.exception.js create mode 100644 lib/common/exceptions/request-timeout.exception.d.ts create mode 100644 lib/common/exceptions/request-timeout.exception.js create mode 100644 lib/common/exceptions/service-unavailable.exception.d.ts create mode 100644 lib/common/exceptions/service-unavailable.exception.js create mode 100644 lib/common/exceptions/unauthorized.exception.d.ts create mode 100644 lib/common/exceptions/unauthorized.exception.js create mode 100644 lib/common/exceptions/unprocessable-entity.exception.d.ts create mode 100644 lib/common/exceptions/unprocessable-entity.exception.js create mode 100644 lib/common/exceptions/unsupported-media-type.exception.d.ts create mode 100644 lib/common/exceptions/unsupported-media-type.exception.js create mode 100644 lib/common/index.d.ts create mode 100644 lib/common/index.js create mode 100644 lib/common/interfaces/can-activate.interface.d.ts create mode 100644 lib/common/interfaces/can-activate.interface.js create mode 100644 lib/common/interfaces/configuration-provider.interface.d.ts create mode 100644 lib/common/interfaces/configuration-provider.interface.js create mode 100644 lib/common/interfaces/controllers/controller-metadata.interface.d.ts create mode 100644 lib/common/interfaces/controllers/controller-metadata.interface.js create mode 100644 lib/common/interfaces/controllers/controller.interface.d.ts create mode 100644 lib/common/interfaces/controllers/controller.interface.js create mode 100644 lib/common/interfaces/controllers/index.d.ts create mode 100644 lib/common/interfaces/controllers/index.js create mode 100644 lib/common/interfaces/custom-route-param-factory.interface.d.ts create mode 100644 lib/common/interfaces/custom-route-param-factory.interface.js create mode 100644 lib/common/interfaces/exceptions/exception-filter-metadata.interface.d.ts create mode 100644 lib/common/interfaces/exceptions/exception-filter-metadata.interface.js create mode 100644 lib/common/interfaces/exceptions/exception-filter.interface.d.ts create mode 100644 lib/common/interfaces/exceptions/exception-filter.interface.js create mode 100644 lib/common/interfaces/exceptions/index.d.ts create mode 100644 lib/common/interfaces/exceptions/index.js create mode 100644 lib/common/interfaces/exceptions/rpc-exception-filter-metadata.interface.d.ts create mode 100644 lib/common/interfaces/exceptions/rpc-exception-filter-metadata.interface.js create mode 100644 lib/common/interfaces/exceptions/rpc-exception-filter.interface.d.ts create mode 100644 lib/common/interfaces/exceptions/rpc-exception-filter.interface.js create mode 100644 lib/common/interfaces/exceptions/ws-exception-filter.interface.d.ts create mode 100644 lib/common/interfaces/exceptions/ws-exception-filter.interface.js create mode 100644 lib/common/interfaces/execution-context.interface.d.ts create mode 100644 lib/common/interfaces/execution-context.interface.js create mode 100644 lib/common/interfaces/index.d.ts create mode 100644 lib/common/interfaces/index.js create mode 100644 lib/common/interfaces/injectable.interface.d.ts create mode 100644 lib/common/interfaces/injectable.interface.js create mode 100644 lib/common/interfaces/metatype.interface.d.ts create mode 100644 lib/common/interfaces/metatype.interface.js create mode 100644 lib/common/interfaces/microservices/custom-transport-strategy.interface.d.ts create mode 100644 lib/common/interfaces/microservices/custom-transport-strategy.interface.js create mode 100644 lib/common/interfaces/microservices/microservice-configuration.interface.d.ts create mode 100644 lib/common/interfaces/microservices/microservice-configuration.interface.js create mode 100644 lib/common/interfaces/middlewares/express-middleware.interface.d.ts create mode 100644 lib/common/interfaces/middlewares/express-middleware.interface.js create mode 100644 lib/common/interfaces/middlewares/express-midleware.interface.d.ts create mode 100644 lib/common/interfaces/middlewares/express-midleware.interface.js create mode 100644 lib/common/interfaces/middlewares/index.d.ts create mode 100644 lib/common/interfaces/middlewares/index.js create mode 100644 lib/common/interfaces/middlewares/middleware-config-proxy.interface.d.ts create mode 100644 lib/common/interfaces/middlewares/middleware-config-proxy.interface.js create mode 100644 lib/common/interfaces/middlewares/middleware-configuration.interface.d.ts create mode 100644 lib/common/interfaces/middlewares/middleware-configuration.interface.js create mode 100644 lib/common/interfaces/middlewares/middlewares-consumer.interface.d.ts create mode 100644 lib/common/interfaces/middlewares/middlewares-consumer.interface.js create mode 100644 lib/common/interfaces/middlewares/nest-middleware.interface.d.ts create mode 100644 lib/common/interfaces/middlewares/nest-middleware.interface.js create mode 100644 lib/common/interfaces/modules/index.d.ts create mode 100644 lib/common/interfaces/modules/index.js create mode 100644 lib/common/interfaces/modules/module-metadata.interface.d.ts create mode 100644 lib/common/interfaces/modules/module-metadata.interface.js create mode 100644 lib/common/interfaces/modules/module-metatype.interface.d.ts create mode 100644 lib/common/interfaces/modules/module-metatype.interface.js create mode 100644 lib/common/interfaces/modules/nest-module.interface.d.ts create mode 100644 lib/common/interfaces/modules/nest-module.interface.js create mode 100644 lib/common/interfaces/modules/on-destroy.interface.d.ts create mode 100644 lib/common/interfaces/modules/on-destroy.interface.js create mode 100644 lib/common/interfaces/modules/on-init.interface.d.ts create mode 100644 lib/common/interfaces/modules/on-init.interface.js create mode 100644 lib/common/interfaces/nest-application-context.interface.d.ts create mode 100644 lib/common/interfaces/nest-application-context.interface.js create mode 100644 lib/common/interfaces/nest-application.interface.d.ts create mode 100644 lib/common/interfaces/nest-application.interface.js create mode 100644 lib/common/interfaces/nest-interceptor.interface.d.ts create mode 100644 lib/common/interfaces/nest-interceptor.interface.js create mode 100644 lib/common/interfaces/nest-microservice.interface.d.ts create mode 100644 lib/common/interfaces/nest-microservice.interface.js create mode 100644 lib/common/interfaces/paramtype.interface.d.ts create mode 100644 lib/common/interfaces/paramtype.interface.js create mode 100644 lib/common/interfaces/pipe-transform.interface.d.ts create mode 100644 lib/common/interfaces/pipe-transform.interface.js create mode 100644 lib/common/interfaces/request-mapping-metadata.interface.d.ts create mode 100644 lib/common/interfaces/request-mapping-metadata.interface.js create mode 100644 lib/common/interfaces/web-socket-adapter.interface.d.ts create mode 100644 lib/common/interfaces/web-socket-adapter.interface.js create mode 100644 lib/common/pipes/index.d.ts create mode 100644 lib/common/pipes/index.js create mode 100644 lib/common/pipes/parse-int.pipe.d.ts create mode 100644 lib/common/pipes/parse-int.pipe.js create mode 100644 lib/common/pipes/validation.pipe.d.ts create mode 100644 lib/common/pipes/validation.pipe.js create mode 100644 lib/common/services/logger.service.d.ts create mode 100644 lib/common/services/logger.service.js create mode 100644 lib/common/utils/bind-resolve-values.util.d.ts create mode 100644 lib/common/utils/bind-resolve-values.util.js create mode 100644 lib/common/utils/decorators/bind.decorator.d.ts create mode 100644 lib/common/utils/decorators/bind.decorator.js create mode 100644 lib/common/utils/decorators/catch.decorator.d.ts create mode 100644 lib/common/utils/decorators/catch.decorator.js create mode 100644 lib/common/utils/decorators/component.decorator.d.ts create mode 100644 lib/common/utils/decorators/component.decorator.js create mode 100644 lib/common/utils/decorators/controller.decorator.d.ts create mode 100644 lib/common/utils/decorators/controller.decorator.js create mode 100644 lib/common/utils/decorators/create-route-param-metadata.decorator.d.ts create mode 100644 lib/common/utils/decorators/create-route-param-metadata.decorator.js create mode 100644 lib/common/utils/decorators/dependencies.decorator.d.ts create mode 100644 lib/common/utils/decorators/dependencies.decorator.js create mode 100644 lib/common/utils/decorators/exception-filters.decorator.d.ts create mode 100644 lib/common/utils/decorators/exception-filters.decorator.js create mode 100644 lib/common/utils/decorators/exceptions/constants.d.ts create mode 100644 lib/common/utils/decorators/exceptions/constants.js create mode 100644 lib/common/utils/decorators/exceptions/invalid-module-config.exception.d.ts create mode 100644 lib/common/utils/decorators/exceptions/invalid-module-config.exception.js create mode 100644 lib/common/utils/decorators/http-code.decorator.d.ts create mode 100644 lib/common/utils/decorators/http-code.decorator.js create mode 100644 lib/common/utils/decorators/inject.decorator.d.ts create mode 100644 lib/common/utils/decorators/inject.decorator.js create mode 100644 lib/common/utils/decorators/module.decorator.d.ts create mode 100644 lib/common/utils/decorators/module.decorator.js create mode 100644 lib/common/utils/decorators/reflect-metadata.decorator.d.ts create mode 100644 lib/common/utils/decorators/reflect-metadata.decorator.js create mode 100644 lib/common/utils/decorators/request-mapping.decorator.d.ts create mode 100644 lib/common/utils/decorators/request-mapping.decorator.js create mode 100644 lib/common/utils/decorators/route-params.decorator.d.ts create mode 100644 lib/common/utils/decorators/route-params.decorator.js create mode 100644 lib/common/utils/decorators/shared.decorator.d.ts create mode 100644 lib/common/utils/decorators/shared.decorator.js create mode 100644 lib/common/utils/decorators/single-scope.decorator.d.ts create mode 100644 lib/common/utils/decorators/single-scope.decorator.js create mode 100644 lib/common/utils/decorators/use-guards.decorator.d.ts create mode 100644 lib/common/utils/decorators/use-guards.decorator.js create mode 100644 lib/common/utils/decorators/use-interceptors.decorator.d.ts create mode 100644 lib/common/utils/decorators/use-interceptors.decorator.js create mode 100644 lib/common/utils/decorators/use-pipes.decorator.d.ts create mode 100644 lib/common/utils/decorators/use-pipes.decorator.js create mode 100644 lib/common/utils/forward-ref.util.d.ts create mode 100644 lib/common/utils/forward-ref.util.js create mode 100644 lib/common/utils/http-exception-body.util.d.ts create mode 100644 lib/common/utils/http-exception-body.util.js create mode 100644 lib/common/utils/index.d.ts create mode 100644 lib/common/utils/index.js create mode 100644 lib/common/utils/merge-with-values.util.d.ts create mode 100644 lib/common/utils/merge-with-values.util.js create mode 100644 lib/common/utils/shared.utils.d.ts create mode 100644 lib/common/utils/shared.utils.js create mode 100644 lib/core/LICENSE create mode 100644 lib/core/Readme.md create mode 100644 lib/core/adapters/express-adapter.d.ts create mode 100644 lib/core/adapters/express-adapter.js create mode 100644 lib/core/application-config.d.ts create mode 100644 lib/core/application-config.js create mode 100644 lib/core/constants.d.ts create mode 100644 lib/core/constants.js create mode 100644 lib/core/errors/exception-handler.d.ts create mode 100644 lib/core/errors/exception-handler.js create mode 100644 lib/core/errors/exceptions-zone.d.ts create mode 100644 lib/core/errors/exceptions-zone.js create mode 100644 lib/core/errors/exceptions/invalid-exception-filter.exception.d.ts create mode 100644 lib/core/errors/exceptions/invalid-exception-filter.exception.js create mode 100644 lib/core/errors/exceptions/invalid-middleware-configuration.exception.d.ts create mode 100644 lib/core/errors/exceptions/invalid-middleware-configuration.exception.js create mode 100644 lib/core/errors/exceptions/invalid-middleware.exception.d.ts create mode 100644 lib/core/errors/exceptions/invalid-middleware.exception.js create mode 100644 lib/core/errors/exceptions/invalid-module.exception.d.ts create mode 100644 lib/core/errors/exceptions/invalid-module.exception.js create mode 100644 lib/core/errors/exceptions/microservices-package-not-found.exception.d.ts create mode 100644 lib/core/errors/exceptions/microservices-package-not-found.exception.js create mode 100644 lib/core/errors/exceptions/runtime.exception.d.ts create mode 100644 lib/core/errors/exceptions/runtime.exception.js create mode 100644 lib/core/errors/exceptions/undefined-dependency.exception.d.ts create mode 100644 lib/core/errors/exceptions/undefined-dependency.exception.js create mode 100644 lib/core/errors/exceptions/unknown-dependencies.exception.d.ts create mode 100644 lib/core/errors/exceptions/unknown-dependencies.exception.js create mode 100644 lib/core/errors/exceptions/unknown-export.exception.d.ts create mode 100644 lib/core/errors/exceptions/unknown-export.exception.js create mode 100644 lib/core/errors/exceptions/unknown-module.exception.d.ts create mode 100644 lib/core/errors/exceptions/unknown-module.exception.js create mode 100644 lib/core/errors/exceptions/unknown-request-mapping.exception.d.ts create mode 100644 lib/core/errors/exceptions/unknown-request-mapping.exception.js create mode 100644 lib/core/errors/messages.d.ts create mode 100644 lib/core/errors/messages.js create mode 100644 lib/core/exceptions/base-exception-filter-context.d.ts create mode 100644 lib/core/exceptions/base-exception-filter-context.js create mode 100644 lib/core/exceptions/exceptions-handler.d.ts create mode 100644 lib/core/exceptions/exceptions-handler.js create mode 100644 lib/core/exceptions/http-exception.d.ts create mode 100644 lib/core/exceptions/http-exception.js create mode 100644 lib/core/guards/constants.d.ts create mode 100644 lib/core/guards/constants.js create mode 100644 lib/core/guards/guards-consumer.d.ts create mode 100644 lib/core/guards/guards-consumer.js create mode 100644 lib/core/guards/guards-context-creator.d.ts create mode 100644 lib/core/guards/guards-context-creator.js create mode 100644 lib/core/helpers/context-creator.d.ts create mode 100644 lib/core/helpers/context-creator.js create mode 100644 lib/core/helpers/messages.d.ts create mode 100644 lib/core/helpers/messages.js create mode 100644 lib/core/helpers/router-method-factory.d.ts create mode 100644 lib/core/helpers/router-method-factory.js create mode 100644 lib/core/index.d.ts create mode 100644 lib/core/index.js create mode 100644 lib/core/injector/container.d.ts create mode 100644 lib/core/injector/container.js create mode 100644 lib/core/injector/injector.d.ts create mode 100644 lib/core/injector/injector.js create mode 100644 lib/core/injector/instance-loader.d.ts create mode 100644 lib/core/injector/instance-loader.js create mode 100644 lib/core/injector/module-ref.d.ts create mode 100644 lib/core/injector/module-ref.js create mode 100644 lib/core/injector/module-token-factory.d.ts create mode 100644 lib/core/injector/module-token-factory.js create mode 100644 lib/core/injector/module.d.ts create mode 100644 lib/core/injector/module.js create mode 100644 lib/core/interceptors/interceptors-consumer.d.ts create mode 100644 lib/core/interceptors/interceptors-consumer.js create mode 100644 lib/core/interceptors/interceptors-context-creator.d.ts create mode 100644 lib/core/interceptors/interceptors-context-creator.js create mode 100644 lib/core/metadata-scanner.d.ts create mode 100644 lib/core/metadata-scanner.js create mode 100644 lib/core/middlewares/builder.d.ts create mode 100644 lib/core/middlewares/builder.js create mode 100644 lib/core/middlewares/container.d.ts create mode 100644 lib/core/middlewares/container.js create mode 100644 lib/core/middlewares/middlewares-module.d.ts create mode 100644 lib/core/middlewares/middlewares-module.js create mode 100644 lib/core/middlewares/resolver.d.ts create mode 100644 lib/core/middlewares/resolver.js create mode 100644 lib/core/middlewares/routes-mapper.d.ts create mode 100644 lib/core/middlewares/routes-mapper.js create mode 100644 lib/core/middlewares/utils.d.ts create mode 100644 lib/core/middlewares/utils.js create mode 100644 lib/core/nest-application-context.d.ts create mode 100644 lib/core/nest-application-context.js create mode 100644 lib/core/nest-application.d.ts create mode 100644 lib/core/nest-application.js create mode 100644 lib/core/nest-factory.d.ts create mode 100644 lib/core/nest-factory.js create mode 100644 lib/core/pipes/params-token-factory.d.ts create mode 100644 lib/core/pipes/params-token-factory.js create mode 100644 lib/core/pipes/pipes-consumer.d.ts create mode 100644 lib/core/pipes/pipes-consumer.js create mode 100644 lib/core/pipes/pipes-context-creator.d.ts create mode 100644 lib/core/pipes/pipes-context-creator.js create mode 100644 lib/core/router/interfaces/exceptions-filter.interface.d.ts create mode 100644 lib/core/router/interfaces/exceptions-filter.interface.js create mode 100644 lib/core/router/interfaces/explorer.inteface.d.ts create mode 100644 lib/core/router/interfaces/explorer.inteface.js create mode 100644 lib/core/router/interfaces/resolver.interface.d.ts create mode 100644 lib/core/router/interfaces/resolver.interface.js create mode 100644 lib/core/router/interfaces/route-params-factory.interface.d.ts create mode 100644 lib/core/router/interfaces/route-params-factory.interface.js create mode 100644 lib/core/router/route-params-factory.d.ts create mode 100644 lib/core/router/route-params-factory.js create mode 100644 lib/core/router/router-exception-filters.d.ts create mode 100644 lib/core/router/router-exception-filters.js create mode 100644 lib/core/router/router-execution-context.d.ts create mode 100644 lib/core/router/router-execution-context.js create mode 100644 lib/core/router/router-explorer.d.ts create mode 100644 lib/core/router/router-explorer.js create mode 100644 lib/core/router/router-proxy.d.ts create mode 100644 lib/core/router/router-proxy.js create mode 100644 lib/core/router/router-response-controller.d.ts create mode 100644 lib/core/router/router-response-controller.js create mode 100644 lib/core/router/routes-resolver.d.ts create mode 100644 lib/core/router/routes-resolver.js create mode 100644 lib/core/scanner.d.ts create mode 100644 lib/core/scanner.js create mode 100644 lib/core/services/reflector.service.d.ts create mode 100644 lib/core/services/reflector.service.js create mode 100644 lib/microservices/LICENSE create mode 100644 lib/microservices/Readme.md create mode 100644 lib/microservices/client/client-proxy-factory.d.ts create mode 100644 lib/microservices/client/client-proxy-factory.js create mode 100644 lib/microservices/client/client-proxy.d.ts create mode 100644 lib/microservices/client/client-proxy.js create mode 100644 lib/microservices/client/client-redis.d.ts create mode 100644 lib/microservices/client/client-redis.js create mode 100644 lib/microservices/client/client-tcp.d.ts create mode 100644 lib/microservices/client/client-tcp.js create mode 100644 lib/microservices/client/index.d.ts create mode 100644 lib/microservices/client/index.js create mode 100644 lib/microservices/constants.d.ts create mode 100644 lib/microservices/constants.js create mode 100644 lib/microservices/container.d.ts create mode 100644 lib/microservices/container.js create mode 100644 lib/microservices/context/exception-filters-context.d.ts create mode 100644 lib/microservices/context/exception-filters-context.js create mode 100644 lib/microservices/context/rpc-context-creator.d.ts create mode 100644 lib/microservices/context/rpc-context-creator.js create mode 100644 lib/microservices/context/rpc-proxy.d.ts create mode 100644 lib/microservices/context/rpc-proxy.js create mode 100644 lib/microservices/enums/index.d.ts create mode 100644 lib/microservices/enums/index.js create mode 100644 lib/microservices/enums/transport.enum.d.ts create mode 100644 lib/microservices/enums/transport.enum.js create mode 100644 lib/microservices/exceptions/index.d.ts create mode 100644 lib/microservices/exceptions/index.js create mode 100644 lib/microservices/exceptions/invalid-message.exception.d.ts create mode 100644 lib/microservices/exceptions/invalid-message.exception.js create mode 100644 lib/microservices/exceptions/rpc-exception.d.ts create mode 100644 lib/microservices/exceptions/rpc-exception.js create mode 100644 lib/microservices/exceptions/rpc-exceptions-handler.d.ts create mode 100644 lib/microservices/exceptions/rpc-exceptions-handler.js create mode 100644 lib/microservices/index.d.ts create mode 100644 lib/microservices/index.js create mode 100644 lib/microservices/interfaces/client-metadata.interface.d.ts create mode 100644 lib/microservices/interfaces/client-metadata.interface.js create mode 100644 lib/microservices/interfaces/closeable.interface.d.ts create mode 100644 lib/microservices/interfaces/closeable.interface.js create mode 100644 lib/microservices/interfaces/custom-transport-strategy.interface.d.ts create mode 100644 lib/microservices/interfaces/custom-transport-strategy.interface.js create mode 100644 lib/microservices/interfaces/index.d.ts create mode 100644 lib/microservices/interfaces/index.js create mode 100644 lib/microservices/interfaces/message-handlers.interface.d.ts create mode 100644 lib/microservices/interfaces/message-handlers.interface.js create mode 100644 lib/microservices/interfaces/microservice-configuration.interface.d.ts create mode 100644 lib/microservices/interfaces/microservice-configuration.interface.js create mode 100644 lib/microservices/interfaces/microservice-response.interface.d.ts create mode 100644 lib/microservices/interfaces/microservice-response.interface.js create mode 100644 lib/microservices/interfaces/pattern-metadata.interface.d.ts create mode 100644 lib/microservices/interfaces/pattern-metadata.interface.js create mode 100644 lib/microservices/listener-metadata-explorer.d.ts create mode 100644 lib/microservices/listener-metadata-explorer.js create mode 100644 lib/microservices/listeners-controller.d.ts create mode 100644 lib/microservices/listeners-controller.js create mode 100644 lib/microservices/microservices-module.d.ts create mode 100644 lib/microservices/microservices-module.js create mode 100644 lib/microservices/nest-microservice.d.ts create mode 100644 lib/microservices/nest-microservice.js create mode 100644 lib/microservices/server/index.d.ts create mode 100644 lib/microservices/server/index.js create mode 100644 lib/microservices/server/server-factory.d.ts create mode 100644 lib/microservices/server/server-factory.js create mode 100644 lib/microservices/server/server-redis.d.ts create mode 100644 lib/microservices/server/server-redis.js create mode 100644 lib/microservices/server/server-tcp.d.ts create mode 100644 lib/microservices/server/server-tcp.js create mode 100644 lib/microservices/server/server.d.ts create mode 100644 lib/microservices/server/server.js create mode 100644 lib/microservices/utils/client.decorator.d.ts create mode 100644 lib/microservices/utils/client.decorator.js create mode 100644 lib/microservices/utils/index.d.ts create mode 100644 lib/microservices/utils/index.js create mode 100644 lib/microservices/utils/pattern.decorator.d.ts create mode 100644 lib/microservices/utils/pattern.decorator.js create mode 100644 lib/testing/LICENSE create mode 100644 lib/testing/Readme.md create mode 100644 lib/testing/errors/unknown-module.exception.d.ts create mode 100644 lib/testing/errors/unknown-module.exception.js create mode 100644 lib/testing/index.d.ts create mode 100644 lib/testing/index.js create mode 100644 lib/testing/interfaces/index.d.ts create mode 100644 lib/testing/interfaces/index.js create mode 100644 lib/testing/interfaces/override-by-factory-options.interface.d.ts create mode 100644 lib/testing/interfaces/override-by-factory-options.interface.js create mode 100644 lib/testing/interfaces/override-by.interface.d.ts create mode 100644 lib/testing/interfaces/override-by.interface.js create mode 100644 lib/testing/test.d.ts create mode 100644 lib/testing/test.js create mode 100644 lib/testing/testing-module.builder.d.ts create mode 100644 lib/testing/testing-module.builder.js create mode 100644 lib/testing/testing-module.d.ts create mode 100644 lib/testing/testing-module.js create mode 100644 lib/websockets/LICENSE create mode 100644 lib/websockets/Readme.md create mode 100644 lib/websockets/adapters/io-adapter.d.ts create mode 100644 lib/websockets/adapters/io-adapter.js create mode 100644 lib/websockets/constants.d.ts create mode 100644 lib/websockets/constants.js create mode 100644 lib/websockets/container.d.ts create mode 100644 lib/websockets/container.js create mode 100644 lib/websockets/context/exception-filters-context.d.ts create mode 100644 lib/websockets/context/exception-filters-context.js create mode 100644 lib/websockets/context/ws-context-creator.d.ts create mode 100644 lib/websockets/context/ws-context-creator.js create mode 100644 lib/websockets/context/ws-proxy.d.ts create mode 100644 lib/websockets/context/ws-proxy.js create mode 100644 lib/websockets/exceptions/invalid-socket-port.exception.d.ts create mode 100644 lib/websockets/exceptions/invalid-socket-port.exception.js create mode 100644 lib/websockets/exceptions/ws-exception.d.ts create mode 100644 lib/websockets/exceptions/ws-exception.js create mode 100644 lib/websockets/exceptions/ws-exceptions-handler.d.ts create mode 100644 lib/websockets/exceptions/ws-exceptions-handler.js create mode 100644 lib/websockets/gateway-metadata-explorer.d.ts create mode 100644 lib/websockets/gateway-metadata-explorer.js create mode 100644 lib/websockets/index.d.ts create mode 100644 lib/websockets/index.js create mode 100644 lib/websockets/interfaces/gateway-metadata.interface.d.ts create mode 100644 lib/websockets/interfaces/gateway-metadata.interface.js create mode 100644 lib/websockets/interfaces/gateway-middleware.interface.d.ts create mode 100644 lib/websockets/interfaces/gateway-middleware.interface.js create mode 100644 lib/websockets/interfaces/index.d.ts create mode 100644 lib/websockets/interfaces/index.js create mode 100644 lib/websockets/interfaces/nest-gateway.interface.d.ts create mode 100644 lib/websockets/interfaces/nest-gateway.interface.js create mode 100644 lib/websockets/interfaces/observable-socket-server.interface.d.ts create mode 100644 lib/websockets/interfaces/observable-socket-server.interface.js create mode 100644 lib/websockets/interfaces/on-gateway-connection.interface.d.ts create mode 100644 lib/websockets/interfaces/on-gateway-connection.interface.js create mode 100644 lib/websockets/interfaces/on-gateway-disconnect.interface.d.ts create mode 100644 lib/websockets/interfaces/on-gateway-disconnect.interface.js create mode 100644 lib/websockets/interfaces/on-gateway-init.interface.d.ts create mode 100644 lib/websockets/interfaces/on-gateway-init.interface.js create mode 100644 lib/websockets/interfaces/web-socket-server.interface.d.ts create mode 100644 lib/websockets/interfaces/web-socket-server.interface.js create mode 100644 lib/websockets/interfaces/ws-response.interface.d.ts create mode 100644 lib/websockets/interfaces/ws-response.interface.js create mode 100644 lib/websockets/middlewares-injector.d.ts create mode 100644 lib/websockets/middlewares-injector.js create mode 100644 lib/websockets/observable-socket.d.ts create mode 100644 lib/websockets/observable-socket.js create mode 100644 lib/websockets/socket-module.d.ts create mode 100644 lib/websockets/socket-module.js create mode 100644 lib/websockets/socket-server-provider.d.ts create mode 100644 lib/websockets/socket-server-provider.js create mode 100644 lib/websockets/utils/gateway-server.decorator.d.ts create mode 100644 lib/websockets/utils/gateway-server.decorator.js create mode 100644 lib/websockets/utils/index.d.ts create mode 100644 lib/websockets/utils/index.js create mode 100644 lib/websockets/utils/socket-gateway.decorator.d.ts create mode 100644 lib/websockets/utils/socket-gateway.decorator.js create mode 100644 lib/websockets/utils/subscribe-message.decorator.d.ts create mode 100644 lib/websockets/utils/subscribe-message.decorator.js create mode 100644 lib/websockets/web-sockets-controller.d.ts create mode 100644 lib/websockets/web-sockets-controller.js diff --git a/lib/common/LICENSE b/lib/common/LICENSE new file mode 100644 index 00000000000..be7581ff84f --- /dev/null +++ b/lib/common/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2017 Kamil Myƛliwiec + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/common/Readme.md b/lib/common/Readme.md new file mode 100644 index 00000000000..280bd354356 --- /dev/null +++ b/lib/common/Readme.md @@ -0,0 +1,125 @@ +

    + Nest Logo +

    + +[travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master +[travis-url]: https://travis-ci.org/nestjs/nest +[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux +[linux-url]: https://travis-ci.org/nestjs/nest + +

    A progressive Node.js framework for building efficient and scalable web applications. :cat:

    +

    +NPM Version +Package License +NPM Downloads +Travis +Linux +Coverage +Gitter +Backers on Open Collective +Sponsors on Open Collective +

    + + +## Description + +

    Nest is a framework for building efficient, scalable Node.js web applications. It uses modern JavaScript, is built with TypeScript (preserves compatibility with pure JavaScript) and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reactive Programming).

    +

    Under the hood, Nest makes use of Express, allowing for easy use of the myriad third-party plugins which are available.

    + +## Philosophy + +

    In recent years, thanks to Node.js, JavaScript has become the “lingua franca” of the web for both front and backend applications, giving rise to awesome projects like Angular, React and Vue which improve developer productivity and enable the construction of fast, testable, extensible frontend applications. However, on the server-side, while there are a lot of superb libraries, helpers and tools for Node, none of them effectively solve the main problem - the architecture.

    +

    Nest aims to provide an application architecture out of the box which allows for effortless creation of highly testable, scalable, loosely coupled and easily maintainable applications.

    + +## Features + +
      +
    • Built with TypeScript (compatible with pure JavaScript + Babel)
    • +
    • Easy to learn - syntax similar to Angular
    • +
    • Familiar - based on well-known libraries (Express / socket.io)
    • +
    • Dependency Injection - built-in asynchronous IoC container with a hierarchical injector
    • +
    • WebSockets module (based on socket.io, but you can bring your own library, by making use of WsAdapter)
    • +
    • Modular - defines an easy to follow module definition pattern so you can split your system into reusable modules
    • +
    • Reactive microservice support with message patterns (built-in transport via TCP / Redis, but other communication schemes can be implemented with CustomTransportStrategy)
    • +
    • Exception layer - throwable web exceptions with status codes, exception filters
    • +
    • Pipes - synchronous & asynchronous (e.g. validation purposes)
    • +
    • Guards - attach additional logic in a declarative manner (e.g. role-based access control)
    • +
    • Interceptors - built on top of RxJS
    • +
    • Testing utilities (both e2e & unit tests)
    • +
    + +## Installation + +**Install the TypeScript Starter Project with Git:** +```bash +$ git clone https://github.com/nestjs/typescript-starter.git project +$ cd project +$ npm install +$ npm run start +``` + +**Install the JavaScript (Babel) Starter Project with Git:** +```bash +$ git clone https://github.com/nestjs/javascript-starter.git project +$ cd project +$ npm install +$ npm run start +``` + +**Start a New Project from Scratch with NPM:** +```bash +$ npm i --save @nestjs/core @nestjs/common @nestjs/microservices @nestjs/websockets @nestjs/testing reflect-metadata rxjs +``` + +## Documentation & Quick Start + +:books: [Documentation & Tutorial](https://docs.nestjs.com) + +## Sponsors + + + +## Backers + +I am on a mission to provide an architecture to create truly flexible, scalable and loosely coupled systems using the Node.js platform. It takes a lot of time, so if you want to support me, please [become a backer / sponsor]((https://opencollective.com/nest#backer)). I appreciate your help. Thanks! :heart_eyes: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## People + +- Author - [Kamil Myƛliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) + +## License + + [MIT](LICENSE) diff --git a/lib/common/constants.d.ts b/lib/common/constants.d.ts new file mode 100644 index 00000000000..dd08c0bfc8e --- /dev/null +++ b/lib/common/constants.d.ts @@ -0,0 +1,20 @@ +export declare const metadata: { + MODULES: string; + COMPONENTS: string; + CONTROLLERS: string; + EXPORTS: string; +}; +export declare const SHARED_MODULE_METADATA = "__sharedModule__"; +export declare const PATH_METADATA = "path"; +export declare const PARAMTYPES_METADATA = "design:paramtypes"; +export declare const SELF_DECLARED_DEPS_METADATA = "self:paramtypes"; +export declare const METHOD_METADATA = "method"; +export declare const ROUTE_ARGS_METADATA = "__routeArguments__"; +export declare const CUSTOM_ROUTE_AGRS_METADATA = "__customRouteArgs__"; +export declare const EXCEPTION_FILTERS_METADATA = "__exceptionFilters__"; +export declare const FILTER_CATCH_EXCEPTIONS = "__filterCatchExceptions__"; +export declare const PIPES_METADATA = "__pipes__"; +export declare const GUARDS_METADATA = "__guards__"; +export declare const INTERCEPTORS_METADATA = "__interceptors__"; +export declare const HTTP_CODE_METADATA = "__httpCode__"; +export declare const GATEWAY_MIDDLEWARES = "__gatewayMiddlewares"; diff --git a/lib/common/constants.js b/lib/common/constants.js new file mode 100644 index 00000000000..430ff251310 --- /dev/null +++ b/lib/common/constants.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.metadata = { + MODULES: 'modules', + COMPONENTS: 'components', + CONTROLLERS: 'controllers', + EXPORTS: 'exports', +}; +exports.SHARED_MODULE_METADATA = '__sharedModule__'; +exports.PATH_METADATA = 'path'; +exports.PARAMTYPES_METADATA = 'design:paramtypes'; +exports.SELF_DECLARED_DEPS_METADATA = 'self:paramtypes'; +exports.METHOD_METADATA = 'method'; +exports.ROUTE_ARGS_METADATA = '__routeArguments__'; +exports.CUSTOM_ROUTE_AGRS_METADATA = '__customRouteArgs__'; +exports.EXCEPTION_FILTERS_METADATA = '__exceptionFilters__'; +exports.FILTER_CATCH_EXCEPTIONS = '__filterCatchExceptions__'; +exports.PIPES_METADATA = '__pipes__'; +exports.GUARDS_METADATA = '__guards__'; +exports.INTERCEPTORS_METADATA = '__interceptors__'; +exports.HTTP_CODE_METADATA = '__httpCode__'; +exports.GATEWAY_MIDDLEWARES = '__gatewayMiddlewares'; diff --git a/lib/common/enums/http-status.enum.d.ts b/lib/common/enums/http-status.enum.d.ts new file mode 100644 index 00000000000..fe4ac614a6f --- /dev/null +++ b/lib/common/enums/http-status.enum.d.ts @@ -0,0 +1,45 @@ +export declare enum HttpStatus { + CONTINUE = 100, + SWITCHING_PROTOCOLS = 101, + PROCESSING = 102, + OK = 200, + CREATED = 201, + ACCEPTED = 202, + NON_AUTHORITATIVE_INFORMATION = 203, + NO_CONTENT = 204, + RESET_CONTENT = 205, + PARTIAL_CONTENT = 206, + AMBIGUOUS = 300, + MOVED_PERMANENTLY = 301, + FOUND = 302, + SEE_OTHER = 303, + NOT_MODIFIED = 304, + TEMPORARY_REDIRECT = 307, + PERMANENT_REDIRECT = 308, + BAD_REQUEST = 400, + UNAUTHORIZED = 401, + PAYMENT_REQUIRED = 402, + FORBIDDEN = 403, + NOT_FOUND = 404, + METHOD_NOT_ALLOWED = 405, + NOT_ACCEPTABLE = 406, + PROXY_AUTHENTICATION_REQUIRED = 407, + REQUEST_TIMEOUT = 408, + CONFLICT = 409, + GONE = 410, + LENGTH_REQUIRED = 411, + PRECONDITION_FAILED = 412, + PAYLOAD_TOO_LARGE = 413, + URI_TOO_LONG = 414, + UNSUPPORTED_MEDIA_TYPE = 415, + REQUESTED_RANGE_NOT_SATISFIABLE = 416, + EXPECTATION_FAILED = 417, + UNPROCESSABLE_ENTITY = 422, + TOO_MANY_REQUESTS = 429, + INTERNAL_SERVER_ERROR = 500, + NOT_IMPLEMENTED = 501, + BAD_GATEWAY = 502, + SERVICE_UNAVAILABLE = 503, + GATEWAY_TIMEOUT = 504, + HTTP_VERSION_NOT_SUPPORTED = 505, +} diff --git a/lib/common/enums/http-status.enum.js b/lib/common/enums/http-status.enum.js new file mode 100644 index 00000000000..54e27037a39 --- /dev/null +++ b/lib/common/enums/http-status.enum.js @@ -0,0 +1,48 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var HttpStatus; +(function (HttpStatus) { + HttpStatus[HttpStatus["CONTINUE"] = 100] = "CONTINUE"; + HttpStatus[HttpStatus["SWITCHING_PROTOCOLS"] = 101] = "SWITCHING_PROTOCOLS"; + HttpStatus[HttpStatus["PROCESSING"] = 102] = "PROCESSING"; + HttpStatus[HttpStatus["OK"] = 200] = "OK"; + HttpStatus[HttpStatus["CREATED"] = 201] = "CREATED"; + HttpStatus[HttpStatus["ACCEPTED"] = 202] = "ACCEPTED"; + HttpStatus[HttpStatus["NON_AUTHORITATIVE_INFORMATION"] = 203] = "NON_AUTHORITATIVE_INFORMATION"; + HttpStatus[HttpStatus["NO_CONTENT"] = 204] = "NO_CONTENT"; + HttpStatus[HttpStatus["RESET_CONTENT"] = 205] = "RESET_CONTENT"; + HttpStatus[HttpStatus["PARTIAL_CONTENT"] = 206] = "PARTIAL_CONTENT"; + HttpStatus[HttpStatus["AMBIGUOUS"] = 300] = "AMBIGUOUS"; + HttpStatus[HttpStatus["MOVED_PERMANENTLY"] = 301] = "MOVED_PERMANENTLY"; + HttpStatus[HttpStatus["FOUND"] = 302] = "FOUND"; + HttpStatus[HttpStatus["SEE_OTHER"] = 303] = "SEE_OTHER"; + HttpStatus[HttpStatus["NOT_MODIFIED"] = 304] = "NOT_MODIFIED"; + HttpStatus[HttpStatus["TEMPORARY_REDIRECT"] = 307] = "TEMPORARY_REDIRECT"; + HttpStatus[HttpStatus["PERMANENT_REDIRECT"] = 308] = "PERMANENT_REDIRECT"; + HttpStatus[HttpStatus["BAD_REQUEST"] = 400] = "BAD_REQUEST"; + HttpStatus[HttpStatus["UNAUTHORIZED"] = 401] = "UNAUTHORIZED"; + HttpStatus[HttpStatus["PAYMENT_REQUIRED"] = 402] = "PAYMENT_REQUIRED"; + HttpStatus[HttpStatus["FORBIDDEN"] = 403] = "FORBIDDEN"; + HttpStatus[HttpStatus["NOT_FOUND"] = 404] = "NOT_FOUND"; + HttpStatus[HttpStatus["METHOD_NOT_ALLOWED"] = 405] = "METHOD_NOT_ALLOWED"; + HttpStatus[HttpStatus["NOT_ACCEPTABLE"] = 406] = "NOT_ACCEPTABLE"; + HttpStatus[HttpStatus["PROXY_AUTHENTICATION_REQUIRED"] = 407] = "PROXY_AUTHENTICATION_REQUIRED"; + HttpStatus[HttpStatus["REQUEST_TIMEOUT"] = 408] = "REQUEST_TIMEOUT"; + HttpStatus[HttpStatus["CONFLICT"] = 409] = "CONFLICT"; + HttpStatus[HttpStatus["GONE"] = 410] = "GONE"; + HttpStatus[HttpStatus["LENGTH_REQUIRED"] = 411] = "LENGTH_REQUIRED"; + HttpStatus[HttpStatus["PRECONDITION_FAILED"] = 412] = "PRECONDITION_FAILED"; + HttpStatus[HttpStatus["PAYLOAD_TOO_LARGE"] = 413] = "PAYLOAD_TOO_LARGE"; + HttpStatus[HttpStatus["URI_TOO_LONG"] = 414] = "URI_TOO_LONG"; + HttpStatus[HttpStatus["UNSUPPORTED_MEDIA_TYPE"] = 415] = "UNSUPPORTED_MEDIA_TYPE"; + HttpStatus[HttpStatus["REQUESTED_RANGE_NOT_SATISFIABLE"] = 416] = "REQUESTED_RANGE_NOT_SATISFIABLE"; + HttpStatus[HttpStatus["EXPECTATION_FAILED"] = 417] = "EXPECTATION_FAILED"; + HttpStatus[HttpStatus["UNPROCESSABLE_ENTITY"] = 422] = "UNPROCESSABLE_ENTITY"; + HttpStatus[HttpStatus["TOO_MANY_REQUESTS"] = 429] = "TOO_MANY_REQUESTS"; + HttpStatus[HttpStatus["INTERNAL_SERVER_ERROR"] = 500] = "INTERNAL_SERVER_ERROR"; + HttpStatus[HttpStatus["NOT_IMPLEMENTED"] = 501] = "NOT_IMPLEMENTED"; + HttpStatus[HttpStatus["BAD_GATEWAY"] = 502] = "BAD_GATEWAY"; + HttpStatus[HttpStatus["SERVICE_UNAVAILABLE"] = 503] = "SERVICE_UNAVAILABLE"; + HttpStatus[HttpStatus["GATEWAY_TIMEOUT"] = 504] = "GATEWAY_TIMEOUT"; + HttpStatus[HttpStatus["HTTP_VERSION_NOT_SUPPORTED"] = 505] = "HTTP_VERSION_NOT_SUPPORTED"; +})(HttpStatus = exports.HttpStatus || (exports.HttpStatus = {})); diff --git a/lib/common/enums/index.d.ts b/lib/common/enums/index.d.ts new file mode 100644 index 00000000000..c17d8692b12 --- /dev/null +++ b/lib/common/enums/index.d.ts @@ -0,0 +1,2 @@ +export * from './request-method.enum'; +export * from './http-status.enum'; diff --git a/lib/common/enums/index.js b/lib/common/enums/index.js new file mode 100644 index 00000000000..520eb070955 --- /dev/null +++ b/lib/common/enums/index.js @@ -0,0 +1,7 @@ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./request-method.enum")); +__export(require("./http-status.enum")); diff --git a/lib/common/enums/nest-environment.enum.d.ts b/lib/common/enums/nest-environment.enum.d.ts new file mode 100644 index 00000000000..8d006ea1a55 --- /dev/null +++ b/lib/common/enums/nest-environment.enum.d.ts @@ -0,0 +1,4 @@ +export declare enum NestEnvironment { + RUN = 0, + TEST = 1, +} diff --git a/lib/common/enums/nest-environment.enum.js b/lib/common/enums/nest-environment.enum.js new file mode 100644 index 00000000000..31cda50e0c5 --- /dev/null +++ b/lib/common/enums/nest-environment.enum.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var NestEnvironment; +(function (NestEnvironment) { + NestEnvironment[NestEnvironment["RUN"] = 0] = "RUN"; + NestEnvironment[NestEnvironment["TEST"] = 1] = "TEST"; +})(NestEnvironment = exports.NestEnvironment || (exports.NestEnvironment = {})); diff --git a/lib/common/enums/request-method.enum.d.ts b/lib/common/enums/request-method.enum.d.ts new file mode 100644 index 00000000000..476c9cb3f0a --- /dev/null +++ b/lib/common/enums/request-method.enum.d.ts @@ -0,0 +1,10 @@ +export declare enum RequestMethod { + GET = 0, + POST = 1, + PUT = 2, + DELETE = 3, + PATCH = 4, + ALL = 5, + OPTIONS = 6, + HEAD = 7, +} diff --git a/lib/common/enums/request-method.enum.js b/lib/common/enums/request-method.enum.js new file mode 100644 index 00000000000..e951585113c --- /dev/null +++ b/lib/common/enums/request-method.enum.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var RequestMethod; +(function (RequestMethod) { + RequestMethod[RequestMethod["GET"] = 0] = "GET"; + RequestMethod[RequestMethod["POST"] = 1] = "POST"; + RequestMethod[RequestMethod["PUT"] = 2] = "PUT"; + RequestMethod[RequestMethod["DELETE"] = 3] = "DELETE"; + RequestMethod[RequestMethod["PATCH"] = 4] = "PATCH"; + RequestMethod[RequestMethod["ALL"] = 5] = "ALL"; + RequestMethod[RequestMethod["OPTIONS"] = 6] = "OPTIONS"; + RequestMethod[RequestMethod["HEAD"] = 7] = "HEAD"; +})(RequestMethod = exports.RequestMethod || (exports.RequestMethod = {})); diff --git a/lib/common/enums/route-paramtypes.enum.d.ts b/lib/common/enums/route-paramtypes.enum.d.ts new file mode 100644 index 00000000000..d5451e82953 --- /dev/null +++ b/lib/common/enums/route-paramtypes.enum.d.ts @@ -0,0 +1,10 @@ +export declare enum RouteParamtypes { + REQUEST = 0, + RESPONSE = 1, + NEXT = 2, + BODY = 3, + QUERY = 4, + PARAM = 5, + HEADERS = 6, + SESSION = 7, +} diff --git a/lib/common/enums/route-paramtypes.enum.js b/lib/common/enums/route-paramtypes.enum.js new file mode 100644 index 00000000000..f705b1d794e --- /dev/null +++ b/lib/common/enums/route-paramtypes.enum.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var RouteParamtypes; +(function (RouteParamtypes) { + RouteParamtypes[RouteParamtypes["REQUEST"] = 0] = "REQUEST"; + RouteParamtypes[RouteParamtypes["RESPONSE"] = 1] = "RESPONSE"; + RouteParamtypes[RouteParamtypes["NEXT"] = 2] = "NEXT"; + RouteParamtypes[RouteParamtypes["BODY"] = 3] = "BODY"; + RouteParamtypes[RouteParamtypes["QUERY"] = 4] = "QUERY"; + RouteParamtypes[RouteParamtypes["PARAM"] = 5] = "PARAM"; + RouteParamtypes[RouteParamtypes["HEADERS"] = 6] = "HEADERS"; + RouteParamtypes[RouteParamtypes["SESSION"] = 7] = "SESSION"; +})(RouteParamtypes = exports.RouteParamtypes || (exports.RouteParamtypes = {})); diff --git a/lib/common/enums/transport.enum.d.ts b/lib/common/enums/transport.enum.d.ts new file mode 100644 index 00000000000..5f116ab7c12 --- /dev/null +++ b/lib/common/enums/transport.enum.d.ts @@ -0,0 +1,4 @@ +export declare enum Transport { + TCP = 0, + REDIS = 1, +} diff --git a/lib/common/enums/transport.enum.js b/lib/common/enums/transport.enum.js new file mode 100644 index 00000000000..059d1078e20 --- /dev/null +++ b/lib/common/enums/transport.enum.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Transport; +(function (Transport) { + Transport[Transport["TCP"] = 0] = "TCP"; + Transport[Transport["REDIS"] = 1] = "REDIS"; +})(Transport = exports.Transport || (exports.Transport = {})); diff --git a/lib/common/exceptions/bad-gateway.exception.d.ts b/lib/common/exceptions/bad-gateway.exception.d.ts new file mode 100644 index 00000000000..9acc902803a --- /dev/null +++ b/lib/common/exceptions/bad-gateway.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class BadGatewayException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/bad-gateway.exception.js b/lib/common/exceptions/bad-gateway.exception.js new file mode 100644 index 00000000000..a0f5dfe33d5 --- /dev/null +++ b/lib/common/exceptions/bad-gateway.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class BadGatewayException extends http_exception_1.HttpException { + constructor(message, error = 'Bad Gateway') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.BAD_GATEWAY), http_status_enum_1.HttpStatus.BAD_GATEWAY); + } +} +exports.BadGatewayException = BadGatewayException; diff --git a/lib/common/exceptions/bad-request.exception.d.ts b/lib/common/exceptions/bad-request.exception.d.ts new file mode 100644 index 00000000000..0359c2836c4 --- /dev/null +++ b/lib/common/exceptions/bad-request.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class BadRequestException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/bad-request.exception.js b/lib/common/exceptions/bad-request.exception.js new file mode 100644 index 00000000000..c00f736338a --- /dev/null +++ b/lib/common/exceptions/bad-request.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class BadRequestException extends http_exception_1.HttpException { + constructor(message, error = 'Bad Request') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.BAD_REQUEST), http_status_enum_1.HttpStatus.BAD_REQUEST); + } +} +exports.BadRequestException = BadRequestException; diff --git a/lib/common/exceptions/conflict.exception.d.ts b/lib/common/exceptions/conflict.exception.d.ts new file mode 100644 index 00000000000..c9cf4bc6adc --- /dev/null +++ b/lib/common/exceptions/conflict.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class ConflictException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/conflict.exception.js b/lib/common/exceptions/conflict.exception.js new file mode 100644 index 00000000000..607e02d9ffe --- /dev/null +++ b/lib/common/exceptions/conflict.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class ConflictException extends http_exception_1.HttpException { + constructor(message, error = 'Conflict') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.CONFLICT), http_status_enum_1.HttpStatus.CONFLICT); + } +} +exports.ConflictException = ConflictException; diff --git a/lib/common/exceptions/constants.d.ts b/lib/common/exceptions/constants.d.ts new file mode 100644 index 00000000000..3aff18f8ed8 --- /dev/null +++ b/lib/common/exceptions/constants.d.ts @@ -0,0 +1 @@ +export declare const InvalidModuleConfigMessage: (property: string) => string; diff --git a/lib/common/exceptions/constants.js b/lib/common/exceptions/constants.js new file mode 100644 index 00000000000..0f51c932ee3 --- /dev/null +++ b/lib/common/exceptions/constants.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.InvalidModuleConfigMessage = (property) => `Invalid property '${property}' in @Module() decorator.`; diff --git a/lib/common/exceptions/forbidden.exception.d.ts b/lib/common/exceptions/forbidden.exception.d.ts new file mode 100644 index 00000000000..88f6b75e958 --- /dev/null +++ b/lib/common/exceptions/forbidden.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class ForbiddenException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/forbidden.exception.js b/lib/common/exceptions/forbidden.exception.js new file mode 100644 index 00000000000..7e196b99f3e --- /dev/null +++ b/lib/common/exceptions/forbidden.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class ForbiddenException extends http_exception_1.HttpException { + constructor(message, error = 'Forbidden') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.FORBIDDEN), http_status_enum_1.HttpStatus.FORBIDDEN); + } +} +exports.ForbiddenException = ForbiddenException; diff --git a/lib/common/exceptions/gateway-timeout.exception.d.ts b/lib/common/exceptions/gateway-timeout.exception.d.ts new file mode 100644 index 00000000000..43bf13db9d3 --- /dev/null +++ b/lib/common/exceptions/gateway-timeout.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class GatewayTimeoutException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/gateway-timeout.exception.js b/lib/common/exceptions/gateway-timeout.exception.js new file mode 100644 index 00000000000..fb17331c88f --- /dev/null +++ b/lib/common/exceptions/gateway-timeout.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class GatewayTimeoutException extends http_exception_1.HttpException { + constructor(message, error = 'Gateway Timeout') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.GATEWAY_TIMEOUT), http_status_enum_1.HttpStatus.GATEWAY_TIMEOUT); + } +} +exports.GatewayTimeoutException = GatewayTimeoutException; diff --git a/lib/common/exceptions/gone.exception.d.ts b/lib/common/exceptions/gone.exception.d.ts new file mode 100644 index 00000000000..bf163313a92 --- /dev/null +++ b/lib/common/exceptions/gone.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class GoneException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/gone.exception.js b/lib/common/exceptions/gone.exception.js new file mode 100644 index 00000000000..a85a08c27c7 --- /dev/null +++ b/lib/common/exceptions/gone.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class GoneException extends http_exception_1.HttpException { + constructor(message, error = 'Gone') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.GONE), http_status_enum_1.HttpStatus.GONE); + } +} +exports.GoneException = GoneException; diff --git a/lib/common/exceptions/http.exception.d.ts b/lib/common/exceptions/http.exception.d.ts new file mode 100644 index 00000000000..314ebbabc2d --- /dev/null +++ b/lib/common/exceptions/http.exception.d.ts @@ -0,0 +1,21 @@ +export declare class HttpException { + private readonly response; + private readonly status; + /** + * The base Nest Application exception, which is handled by the default Exceptions Handler. + * If you throw an exception from your HTTP route handlers, Nest will map them to the appropriate HTTP response and send to the client. + * + * When `response` is an object: + * - object will be stringified and returned to the user as a JSON response, + * + * When `response` is a string: + * - Nest will create a response with two properties: + * ``` + * message: response, + * statusCode: X + * ``` + */ + constructor(response: string | object, status: number); + getResponse(): string | object; + getStatus(): number; +} diff --git a/lib/common/exceptions/http.exception.js b/lib/common/exceptions/http.exception.js new file mode 100644 index 00000000000..e3a4a481bf3 --- /dev/null +++ b/lib/common/exceptions/http.exception.js @@ -0,0 +1,29 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class HttpException { + /** + * The base Nest Application exception, which is handled by the default Exceptions Handler. + * If you throw an exception from your HTTP route handlers, Nest will map them to the appropriate HTTP response and send to the client. + * + * When `response` is an object: + * - object will be stringified and returned to the user as a JSON response, + * + * When `response` is a string: + * - Nest will create a response with two properties: + * ``` + * message: response, + * statusCode: X + * ``` + */ + constructor(response, status) { + this.response = response; + this.status = status; + } + getResponse() { + return this.response; + } + getStatus() { + return this.status; + } +} +exports.HttpException = HttpException; diff --git a/lib/common/exceptions/index.d.ts b/lib/common/exceptions/index.d.ts new file mode 100644 index 00000000000..23c69da657a --- /dev/null +++ b/lib/common/exceptions/index.d.ts @@ -0,0 +1,18 @@ +export * from './bad-request.exception'; +export * from './http.exception'; +export * from './unauthorized.exception'; +export * from './method-not-allowed.exception'; +export * from './not-found.exception'; +export * from './forbidden.exception'; +export * from './not-acceptable.exception'; +export * from './request-timeout.exception'; +export * from './conflict.exception'; +export * from './gone.exception'; +export * from './payload-too-large.exception'; +export * from './unsupported-media-type.exception'; +export * from './unprocessable-entity.exception'; +export * from './internal-server-error.exception'; +export * from './not-implemented.exception'; +export * from './bad-gateway.exception'; +export * from './service-unavailable.exception'; +export * from './gateway-timeout.exception'; diff --git a/lib/common/exceptions/index.js b/lib/common/exceptions/index.js new file mode 100644 index 00000000000..272a97955ca --- /dev/null +++ b/lib/common/exceptions/index.js @@ -0,0 +1,23 @@ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./bad-request.exception")); +__export(require("./http.exception")); +__export(require("./unauthorized.exception")); +__export(require("./method-not-allowed.exception")); +__export(require("./not-found.exception")); +__export(require("./forbidden.exception")); +__export(require("./not-acceptable.exception")); +__export(require("./request-timeout.exception")); +__export(require("./conflict.exception")); +__export(require("./gone.exception")); +__export(require("./payload-too-large.exception")); +__export(require("./unsupported-media-type.exception")); +__export(require("./unprocessable-entity.exception")); +__export(require("./internal-server-error.exception")); +__export(require("./not-implemented.exception")); +__export(require("./bad-gateway.exception")); +__export(require("./service-unavailable.exception")); +__export(require("./gateway-timeout.exception")); diff --git a/lib/common/exceptions/internal-server-error.exception.d.ts b/lib/common/exceptions/internal-server-error.exception.d.ts new file mode 100644 index 00000000000..af854728daf --- /dev/null +++ b/lib/common/exceptions/internal-server-error.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class InternalServerErrorException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/internal-server-error.exception.js b/lib/common/exceptions/internal-server-error.exception.js new file mode 100644 index 00000000000..661bd442333 --- /dev/null +++ b/lib/common/exceptions/internal-server-error.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class InternalServerErrorException extends http_exception_1.HttpException { + constructor(message, error = 'Internal Server Error') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.INTERNAL_SERVER_ERROR), http_status_enum_1.HttpStatus.INTERNAL_SERVER_ERROR); + } +} +exports.InternalServerErrorException = InternalServerErrorException; diff --git a/lib/common/exceptions/invalid-module-config.exception.d.ts b/lib/common/exceptions/invalid-module-config.exception.d.ts new file mode 100644 index 00000000000..8d2a089ebf6 --- /dev/null +++ b/lib/common/exceptions/invalid-module-config.exception.d.ts @@ -0,0 +1,3 @@ +export declare class InvalidModuleConfigException extends Error { + constructor(property: string); +} diff --git a/lib/common/exceptions/invalid-module-config.exception.js b/lib/common/exceptions/invalid-module-config.exception.js new file mode 100644 index 00000000000..21bdd384838 --- /dev/null +++ b/lib/common/exceptions/invalid-module-config.exception.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const constants_1 = require("./constants"); +class InvalidModuleConfigException extends Error { + constructor(property) { + super(constants_1.InvalidModuleConfigMessage(property)); + } +} +exports.InvalidModuleConfigException = InvalidModuleConfigException; diff --git a/lib/common/exceptions/method-not-allowed.exception.d.ts b/lib/common/exceptions/method-not-allowed.exception.d.ts new file mode 100644 index 00000000000..b53c4e3b7e5 --- /dev/null +++ b/lib/common/exceptions/method-not-allowed.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class MethodNotAllowedException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/method-not-allowed.exception.js b/lib/common/exceptions/method-not-allowed.exception.js new file mode 100644 index 00000000000..d5ed180ba1c --- /dev/null +++ b/lib/common/exceptions/method-not-allowed.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class MethodNotAllowedException extends http_exception_1.HttpException { + constructor(message, error = 'Method Not Allowed') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.METHOD_NOT_ALLOWED), http_status_enum_1.HttpStatus.METHOD_NOT_ALLOWED); + } +} +exports.MethodNotAllowedException = MethodNotAllowedException; diff --git a/lib/common/exceptions/not-acceptable.exception.d.ts b/lib/common/exceptions/not-acceptable.exception.d.ts new file mode 100644 index 00000000000..aedd756ea5c --- /dev/null +++ b/lib/common/exceptions/not-acceptable.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class NotAcceptableException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/not-acceptable.exception.js b/lib/common/exceptions/not-acceptable.exception.js new file mode 100644 index 00000000000..c93f208c590 --- /dev/null +++ b/lib/common/exceptions/not-acceptable.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class NotAcceptableException extends http_exception_1.HttpException { + constructor(message, error = 'Not Acceptable') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.NOT_ACCEPTABLE), http_status_enum_1.HttpStatus.NOT_ACCEPTABLE); + } +} +exports.NotAcceptableException = NotAcceptableException; diff --git a/lib/common/exceptions/not-found.exception.d.ts b/lib/common/exceptions/not-found.exception.d.ts new file mode 100644 index 00000000000..45847ad6911 --- /dev/null +++ b/lib/common/exceptions/not-found.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class NotFoundException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/not-found.exception.js b/lib/common/exceptions/not-found.exception.js new file mode 100644 index 00000000000..bfbd9b1d412 --- /dev/null +++ b/lib/common/exceptions/not-found.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class NotFoundException extends http_exception_1.HttpException { + constructor(message, error = 'Not Found') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.NOT_FOUND), http_status_enum_1.HttpStatus.NOT_FOUND); + } +} +exports.NotFoundException = NotFoundException; diff --git a/lib/common/exceptions/not-implemented.exception.d.ts b/lib/common/exceptions/not-implemented.exception.d.ts new file mode 100644 index 00000000000..8b1d49255b4 --- /dev/null +++ b/lib/common/exceptions/not-implemented.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class NotImplementedException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/not-implemented.exception.js b/lib/common/exceptions/not-implemented.exception.js new file mode 100644 index 00000000000..e552d24ad30 --- /dev/null +++ b/lib/common/exceptions/not-implemented.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class NotImplementedException extends http_exception_1.HttpException { + constructor(message, error = 'Not Implemented') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.NOT_IMPLEMENTED), http_status_enum_1.HttpStatus.NOT_IMPLEMENTED); + } +} +exports.NotImplementedException = NotImplementedException; diff --git a/lib/common/exceptions/payload-too-large.exception.d.ts b/lib/common/exceptions/payload-too-large.exception.d.ts new file mode 100644 index 00000000000..050c6776743 --- /dev/null +++ b/lib/common/exceptions/payload-too-large.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class PayloadTooLargeException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/payload-too-large.exception.js b/lib/common/exceptions/payload-too-large.exception.js new file mode 100644 index 00000000000..3e3da9835c7 --- /dev/null +++ b/lib/common/exceptions/payload-too-large.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class PayloadTooLargeException extends http_exception_1.HttpException { + constructor(message, error = 'Payload Too Large') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.PAYLOAD_TOO_LARGE), http_status_enum_1.HttpStatus.PAYLOAD_TOO_LARGE); + } +} +exports.PayloadTooLargeException = PayloadTooLargeException; diff --git a/lib/common/exceptions/request-timeout.exception.d.ts b/lib/common/exceptions/request-timeout.exception.d.ts new file mode 100644 index 00000000000..ae1bf4f1c79 --- /dev/null +++ b/lib/common/exceptions/request-timeout.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class RequestTimeoutException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/request-timeout.exception.js b/lib/common/exceptions/request-timeout.exception.js new file mode 100644 index 00000000000..3504f0c6d2b --- /dev/null +++ b/lib/common/exceptions/request-timeout.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class RequestTimeoutException extends http_exception_1.HttpException { + constructor(message, error = 'Request Timeout') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.REQUEST_TIMEOUT), http_status_enum_1.HttpStatus.REQUEST_TIMEOUT); + } +} +exports.RequestTimeoutException = RequestTimeoutException; diff --git a/lib/common/exceptions/service-unavailable.exception.d.ts b/lib/common/exceptions/service-unavailable.exception.d.ts new file mode 100644 index 00000000000..43cae5f5a12 --- /dev/null +++ b/lib/common/exceptions/service-unavailable.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class ServiceUnavailableException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/service-unavailable.exception.js b/lib/common/exceptions/service-unavailable.exception.js new file mode 100644 index 00000000000..9662bb8a4a7 --- /dev/null +++ b/lib/common/exceptions/service-unavailable.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class ServiceUnavailableException extends http_exception_1.HttpException { + constructor(message, error = 'Service Unavailable') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.SERVICE_UNAVAILABLE), http_status_enum_1.HttpStatus.SERVICE_UNAVAILABLE); + } +} +exports.ServiceUnavailableException = ServiceUnavailableException; diff --git a/lib/common/exceptions/unauthorized.exception.d.ts b/lib/common/exceptions/unauthorized.exception.d.ts new file mode 100644 index 00000000000..798da7f425b --- /dev/null +++ b/lib/common/exceptions/unauthorized.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class UnauthorizedException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/unauthorized.exception.js b/lib/common/exceptions/unauthorized.exception.js new file mode 100644 index 00000000000..38189ae9d80 --- /dev/null +++ b/lib/common/exceptions/unauthorized.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class UnauthorizedException extends http_exception_1.HttpException { + constructor(message, error = 'Unauthorized') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.UNAUTHORIZED), http_status_enum_1.HttpStatus.UNAUTHORIZED); + } +} +exports.UnauthorizedException = UnauthorizedException; diff --git a/lib/common/exceptions/unprocessable-entity.exception.d.ts b/lib/common/exceptions/unprocessable-entity.exception.d.ts new file mode 100644 index 00000000000..cf1a7d530c3 --- /dev/null +++ b/lib/common/exceptions/unprocessable-entity.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class UnprocessableEntityException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/unprocessable-entity.exception.js b/lib/common/exceptions/unprocessable-entity.exception.js new file mode 100644 index 00000000000..fde8e95fb5e --- /dev/null +++ b/lib/common/exceptions/unprocessable-entity.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class UnprocessableEntityException extends http_exception_1.HttpException { + constructor(message, error = 'Unprocessable Entity') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.UNPROCESSABLE_ENTITY), http_status_enum_1.HttpStatus.UNPROCESSABLE_ENTITY); + } +} +exports.UnprocessableEntityException = UnprocessableEntityException; diff --git a/lib/common/exceptions/unsupported-media-type.exception.d.ts b/lib/common/exceptions/unsupported-media-type.exception.d.ts new file mode 100644 index 00000000000..5f777fdb7d9 --- /dev/null +++ b/lib/common/exceptions/unsupported-media-type.exception.d.ts @@ -0,0 +1,4 @@ +import { HttpException } from './http.exception'; +export declare class UnsupportedMediaTypeException extends HttpException { + constructor(message?: string | object | any, error?: string); +} diff --git a/lib/common/exceptions/unsupported-media-type.exception.js b/lib/common/exceptions/unsupported-media-type.exception.js new file mode 100644 index 00000000000..2c501436f21 --- /dev/null +++ b/lib/common/exceptions/unsupported-media-type.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http.exception"); +const http_status_enum_1 = require("../enums/http-status.enum"); +const http_exception_body_util_1 = require("./../utils/http-exception-body.util"); +class UnsupportedMediaTypeException extends http_exception_1.HttpException { + constructor(message, error = 'Unsupported Media Type') { + super(http_exception_body_util_1.createHttpExceptionBody(message, error, http_status_enum_1.HttpStatus.UNSUPPORTED_MEDIA_TYPE), http_status_enum_1.HttpStatus.UNSUPPORTED_MEDIA_TYPE); + } +} +exports.UnsupportedMediaTypeException = UnsupportedMediaTypeException; diff --git a/lib/common/index.d.ts b/lib/common/index.d.ts new file mode 100644 index 00000000000..fd29a7a5826 --- /dev/null +++ b/lib/common/index.d.ts @@ -0,0 +1,6 @@ +export * from './utils'; +export * from './enums'; +export { NestModule, INestApplication, INestMicroservice, MiddlewareConfigProxy, MiddlewareConfiguration, NestMiddleware, ExpressMiddleware, MiddlewaresConsumer, OnModuleInit, ExceptionFilter, WebSocketAdapter, PipeTransform, Paramtype, ArgumentMetadata, OnModuleDestroy, ExecutionContext, CanActivate, RpcExceptionFilter, WsExceptionFilter, NestInterceptor, INestApplicationContext } from './interfaces'; +export * from './services/logger.service'; +export * from './pipes'; +export * from './exceptions'; diff --git a/lib/common/index.js b/lib/common/index.js new file mode 100644 index 00000000000..4ff913123a9 --- /dev/null +++ b/lib/common/index.js @@ -0,0 +1,16 @@ +"use strict"; +/* + * Nest @common + * Copyright(c) 2017-... Kamil Mysliwiec + * www.nestjs.com || www.kamilmysliwiec.com + * MIT Licensed + */ +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./utils")); +__export(require("./enums")); +__export(require("./services/logger.service")); +__export(require("./pipes")); +__export(require("./exceptions")); diff --git a/lib/common/interfaces/can-activate.interface.d.ts b/lib/common/interfaces/can-activate.interface.d.ts new file mode 100644 index 00000000000..bf4497a0ff3 --- /dev/null +++ b/lib/common/interfaces/can-activate.interface.d.ts @@ -0,0 +1,5 @@ +import { Observable } from 'rxjs/Observable'; +import { ExecutionContext } from './execution-context.interface'; +export interface CanActivate { + canActivate(request: any, context: ExecutionContext): boolean | Promise | Observable; +} diff --git a/lib/common/interfaces/can-activate.interface.js b/lib/common/interfaces/can-activate.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/can-activate.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/configuration-provider.interface.d.ts b/lib/common/interfaces/configuration-provider.interface.d.ts new file mode 100644 index 00000000000..effec1ee21a --- /dev/null +++ b/lib/common/interfaces/configuration-provider.interface.d.ts @@ -0,0 +1,6 @@ +import { NestInterceptor } from './nest-interceptor.interface'; +import { CanActivate } from './can-activate.interface'; +export interface ConfigurationProvider { + getGlobalInterceptors(): NestInterceptor[]; + getGlobalGuards(): CanActivate[]; +} diff --git a/lib/common/interfaces/configuration-provider.interface.js b/lib/common/interfaces/configuration-provider.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/configuration-provider.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/controllers/controller-metadata.interface.d.ts b/lib/common/interfaces/controllers/controller-metadata.interface.d.ts new file mode 100644 index 00000000000..b816bf9aafb --- /dev/null +++ b/lib/common/interfaces/controllers/controller-metadata.interface.d.ts @@ -0,0 +1,3 @@ +export interface ControllerMetadata { + path?: string; +} diff --git a/lib/common/interfaces/controllers/controller-metadata.interface.js b/lib/common/interfaces/controllers/controller-metadata.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/controllers/controller-metadata.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/controllers/controller.interface.d.ts b/lib/common/interfaces/controllers/controller.interface.d.ts new file mode 100644 index 00000000000..9089f280240 --- /dev/null +++ b/lib/common/interfaces/controllers/controller.interface.d.ts @@ -0,0 +1,2 @@ +export interface Controller { +} diff --git a/lib/common/interfaces/controllers/controller.interface.js b/lib/common/interfaces/controllers/controller.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/controllers/controller.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/controllers/index.d.ts b/lib/common/interfaces/controllers/index.d.ts new file mode 100644 index 00000000000..4bd60924b00 --- /dev/null +++ b/lib/common/interfaces/controllers/index.d.ts @@ -0,0 +1,2 @@ +export * from './controller-metadata.interface'; +export * from './controller.interface'; diff --git a/lib/common/interfaces/controllers/index.js b/lib/common/interfaces/controllers/index.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/controllers/index.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/custom-route-param-factory.interface.d.ts b/lib/common/interfaces/custom-route-param-factory.interface.d.ts new file mode 100644 index 00000000000..c5580392b52 --- /dev/null +++ b/lib/common/interfaces/custom-route-param-factory.interface.d.ts @@ -0,0 +1 @@ +export declare type CustomParamFactory = (data, req) => any; diff --git a/lib/common/interfaces/custom-route-param-factory.interface.js b/lib/common/interfaces/custom-route-param-factory.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/custom-route-param-factory.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/exceptions/exception-filter-metadata.interface.d.ts b/lib/common/interfaces/exceptions/exception-filter-metadata.interface.d.ts new file mode 100644 index 00000000000..664df291cae --- /dev/null +++ b/lib/common/interfaces/exceptions/exception-filter-metadata.interface.d.ts @@ -0,0 +1,6 @@ +import { ExceptionFilter } from './exception-filter.interface'; +import { Metatype } from '../metatype.interface'; +export interface ExceptionFilterMetadata { + func: ExceptionFilter['catch']; + exceptionMetatypes: Metatype[]; +} diff --git a/lib/common/interfaces/exceptions/exception-filter-metadata.interface.js b/lib/common/interfaces/exceptions/exception-filter-metadata.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/exceptions/exception-filter-metadata.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/exceptions/exception-filter.interface.d.ts b/lib/common/interfaces/exceptions/exception-filter.interface.d.ts new file mode 100644 index 00000000000..1c3df01069c --- /dev/null +++ b/lib/common/interfaces/exceptions/exception-filter.interface.d.ts @@ -0,0 +1,3 @@ +export interface ExceptionFilter { + catch(exception: any, response: any): any; +} diff --git a/lib/common/interfaces/exceptions/exception-filter.interface.js b/lib/common/interfaces/exceptions/exception-filter.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/exceptions/exception-filter.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/exceptions/index.d.ts b/lib/common/interfaces/exceptions/index.d.ts new file mode 100644 index 00000000000..f35002c2e21 --- /dev/null +++ b/lib/common/interfaces/exceptions/index.d.ts @@ -0,0 +1,5 @@ +export * from './exception-filter-metadata.interface'; +export * from './exception-filter.interface'; +export * from './rpc-exception-filter-metadata.interface'; +export * from './rpc-exception-filter.interface'; +export * from './ws-exception-filter.interface'; diff --git a/lib/common/interfaces/exceptions/index.js b/lib/common/interfaces/exceptions/index.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/exceptions/index.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/exceptions/rpc-exception-filter-metadata.interface.d.ts b/lib/common/interfaces/exceptions/rpc-exception-filter-metadata.interface.d.ts new file mode 100644 index 00000000000..85679224e67 --- /dev/null +++ b/lib/common/interfaces/exceptions/rpc-exception-filter-metadata.interface.d.ts @@ -0,0 +1,6 @@ +import { RpcExceptionFilter } from './rpc-exception-filter.interface'; +import { Metatype } from '../metatype.interface'; +export interface RpcExceptionFilterMetadata { + func: RpcExceptionFilter['catch']; + exceptionMetatypes: Metatype[]; +} diff --git a/lib/common/interfaces/exceptions/rpc-exception-filter-metadata.interface.js b/lib/common/interfaces/exceptions/rpc-exception-filter-metadata.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/exceptions/rpc-exception-filter-metadata.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/exceptions/rpc-exception-filter.interface.d.ts b/lib/common/interfaces/exceptions/rpc-exception-filter.interface.d.ts new file mode 100644 index 00000000000..e73474c1012 --- /dev/null +++ b/lib/common/interfaces/exceptions/rpc-exception-filter.interface.d.ts @@ -0,0 +1,4 @@ +import { Observable } from 'rxjs/Observable'; +export interface RpcExceptionFilter { + catch(exception: any): Observable; +} diff --git a/lib/common/interfaces/exceptions/rpc-exception-filter.interface.js b/lib/common/interfaces/exceptions/rpc-exception-filter.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/exceptions/rpc-exception-filter.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/exceptions/ws-exception-filter.interface.d.ts b/lib/common/interfaces/exceptions/ws-exception-filter.interface.d.ts new file mode 100644 index 00000000000..1d1994d342b --- /dev/null +++ b/lib/common/interfaces/exceptions/ws-exception-filter.interface.d.ts @@ -0,0 +1,3 @@ +export interface WsExceptionFilter { + catch(exception: any, client: any): any; +} diff --git a/lib/common/interfaces/exceptions/ws-exception-filter.interface.js b/lib/common/interfaces/exceptions/ws-exception-filter.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/exceptions/ws-exception-filter.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/execution-context.interface.d.ts b/lib/common/interfaces/execution-context.interface.d.ts new file mode 100644 index 00000000000..c174b8d0861 --- /dev/null +++ b/lib/common/interfaces/execution-context.interface.d.ts @@ -0,0 +1,4 @@ +export interface ExecutionContext { + parent: Function; + handler: (...args) => any; +} diff --git a/lib/common/interfaces/execution-context.interface.js b/lib/common/interfaces/execution-context.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/execution-context.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/index.d.ts b/lib/common/interfaces/index.d.ts new file mode 100644 index 00000000000..18c40f7f7c6 --- /dev/null +++ b/lib/common/interfaces/index.d.ts @@ -0,0 +1,24 @@ +export * from './request-mapping-metadata.interface'; +export * from './modules/nest-module.interface'; +export * from './modules/module-metadata.interface'; +export * from './controllers/controller.interface'; +export * from './injectable.interface'; +export * from './controllers/controller-metadata.interface'; +export * from './modules/module-metadata.interface'; +export * from './metatype.interface'; +export * from './nest-application.interface'; +export * from './nest-microservice.interface'; +export * from './nest-application-context.interface'; +export * from './modules/on-init.interface'; +export * from './modules/on-destroy.interface'; +export * from './exceptions/exception-filter.interface'; +export * from './middlewares'; +export * from './web-socket-adapter.interface'; +export * from './pipe-transform.interface'; +export * from './paramtype.interface'; +export * from './can-activate.interface'; +export * from './exceptions/rpc-exception-filter.interface'; +export * from './exceptions/ws-exception-filter.interface'; +export * from './execution-context.interface'; +export * from './nest-interceptor.interface'; +export * from './custom-route-param-factory.interface'; diff --git a/lib/common/interfaces/index.js b/lib/common/interfaces/index.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/index.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/injectable.interface.d.ts b/lib/common/interfaces/injectable.interface.d.ts new file mode 100644 index 00000000000..390800ab267 --- /dev/null +++ b/lib/common/interfaces/injectable.interface.d.ts @@ -0,0 +1,2 @@ +export interface Injectable { +} diff --git a/lib/common/interfaces/injectable.interface.js b/lib/common/interfaces/injectable.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/injectable.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/metatype.interface.d.ts b/lib/common/interfaces/metatype.interface.d.ts new file mode 100644 index 00000000000..957b2991608 --- /dev/null +++ b/lib/common/interfaces/metatype.interface.d.ts @@ -0,0 +1,3 @@ +export interface Metatype { + new (...args: any[]): T; +} diff --git a/lib/common/interfaces/metatype.interface.js b/lib/common/interfaces/metatype.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/metatype.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/microservices/custom-transport-strategy.interface.d.ts b/lib/common/interfaces/microservices/custom-transport-strategy.interface.d.ts new file mode 100644 index 00000000000..b743506b902 --- /dev/null +++ b/lib/common/interfaces/microservices/custom-transport-strategy.interface.d.ts @@ -0,0 +1,4 @@ +export interface CustomTransportStrategy { + listen(callback: () => void): any; + close(): any; +} diff --git a/lib/common/interfaces/microservices/custom-transport-strategy.interface.js b/lib/common/interfaces/microservices/custom-transport-strategy.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/microservices/custom-transport-strategy.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/microservices/microservice-configuration.interface.d.ts b/lib/common/interfaces/microservices/microservice-configuration.interface.d.ts new file mode 100644 index 00000000000..831a3208d78 --- /dev/null +++ b/lib/common/interfaces/microservices/microservice-configuration.interface.d.ts @@ -0,0 +1,9 @@ +import { CustomTransportStrategy } from './custom-transport-strategy.interface'; +import { Transport } from './../../enums/transport.enum'; +export interface MicroserviceConfiguration { + transport?: Transport; + url?: string; + port?: number; + host?: string; + strategy?: CustomTransportStrategy; +} diff --git a/lib/common/interfaces/microservices/microservice-configuration.interface.js b/lib/common/interfaces/microservices/microservice-configuration.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/microservices/microservice-configuration.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/middlewares/express-middleware.interface.d.ts b/lib/common/interfaces/middlewares/express-middleware.interface.d.ts new file mode 100644 index 00000000000..e79f9ccec25 --- /dev/null +++ b/lib/common/interfaces/middlewares/express-middleware.interface.d.ts @@ -0,0 +1,3 @@ +export interface ExpressMiddleware { + (req?: any, res?: any, next?: any): void; +} diff --git a/lib/common/interfaces/middlewares/express-middleware.interface.js b/lib/common/interfaces/middlewares/express-middleware.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/middlewares/express-middleware.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/middlewares/express-midleware.interface.d.ts b/lib/common/interfaces/middlewares/express-midleware.interface.d.ts new file mode 100644 index 00000000000..e79f9ccec25 --- /dev/null +++ b/lib/common/interfaces/middlewares/express-midleware.interface.d.ts @@ -0,0 +1,3 @@ +export interface ExpressMiddleware { + (req?: any, res?: any, next?: any): void; +} diff --git a/lib/common/interfaces/middlewares/express-midleware.interface.js b/lib/common/interfaces/middlewares/express-midleware.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/middlewares/express-midleware.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/middlewares/index.d.ts b/lib/common/interfaces/middlewares/index.d.ts new file mode 100644 index 00000000000..20b9b371492 --- /dev/null +++ b/lib/common/interfaces/middlewares/index.d.ts @@ -0,0 +1,5 @@ +export * from './middleware-config-proxy.interface'; +export * from './middlewares-consumer.interface'; +export * from './middleware-configuration.interface'; +export * from './nest-middleware.interface'; +export * from './express-middleware.interface'; diff --git a/lib/common/interfaces/middlewares/index.js b/lib/common/interfaces/middlewares/index.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/middlewares/index.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/middlewares/middleware-config-proxy.interface.d.ts b/lib/common/interfaces/middlewares/middleware-config-proxy.interface.d.ts new file mode 100644 index 00000000000..71a0338caa9 --- /dev/null +++ b/lib/common/interfaces/middlewares/middleware-config-proxy.interface.d.ts @@ -0,0 +1,24 @@ +import { MiddlewaresConsumer } from './middlewares-consumer.interface'; +export interface MiddlewareConfigProxy { + /** + * Passes custom arguments to `resolve()` method of the middleware + * + * @param {} ...data + * @returns MiddlewareConfigProxy + */ + with(...data: any[]): MiddlewareConfigProxy; + /** + * Attaches passed routes / controllers to the processed middleware(s). + * Single route can be defined as a literal object: + * ``` + * path: string; + * method: RequestMethod; + * ``` + * + * When you passed Controller class, Nest will attach middleware to every HTTP route handler inside this controller. + * + * @param {} ...routes + * @returns MiddlewaresConsumer + */ + forRoutes(...routes: any[]): MiddlewaresConsumer; +} diff --git a/lib/common/interfaces/middlewares/middleware-config-proxy.interface.js b/lib/common/interfaces/middlewares/middleware-config-proxy.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/middlewares/middleware-config-proxy.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/middlewares/middleware-configuration.interface.d.ts b/lib/common/interfaces/middlewares/middleware-configuration.interface.d.ts new file mode 100644 index 00000000000..fd0be7e0223 --- /dev/null +++ b/lib/common/interfaces/middlewares/middleware-configuration.interface.d.ts @@ -0,0 +1,9 @@ +import { ControllerMetadata } from '../controllers/controller-metadata.interface'; +import { Controller } from '../controllers/controller.interface'; +import { RequestMethod } from '../../enums/request-method.enum'; +export interface MiddlewareConfiguration { + middlewares: any; + forRoutes: (Controller | ControllerMetadata & { + method?: RequestMethod; + })[]; +} diff --git a/lib/common/interfaces/middlewares/middleware-configuration.interface.js b/lib/common/interfaces/middlewares/middleware-configuration.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/middlewares/middleware-configuration.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/middlewares/middlewares-consumer.interface.d.ts b/lib/common/interfaces/middlewares/middlewares-consumer.interface.d.ts new file mode 100644 index 00000000000..149efde4e53 --- /dev/null +++ b/lib/common/interfaces/middlewares/middlewares-consumer.interface.d.ts @@ -0,0 +1,11 @@ +import { MiddlewareConfigProxy } from './middleware-config-proxy.interface'; +export interface MiddlewaresConsumer { + /** + * Takes single middleware class or array of classes, + * which subsequently can be attached to the passed routes / controllers. + * + * @param {any|any[]} middlewares + * @returns MiddlewareConfigProxy + */ + apply(middlewares: any | any[]): MiddlewareConfigProxy; +} diff --git a/lib/common/interfaces/middlewares/middlewares-consumer.interface.js b/lib/common/interfaces/middlewares/middlewares-consumer.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/middlewares/middlewares-consumer.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/middlewares/nest-middleware.interface.d.ts b/lib/common/interfaces/middlewares/nest-middleware.interface.d.ts new file mode 100644 index 00000000000..4656c6b5ea5 --- /dev/null +++ b/lib/common/interfaces/middlewares/nest-middleware.interface.d.ts @@ -0,0 +1,5 @@ +import { ExpressMiddleware } from './express-middleware.interface'; +export declare type AsyncExpressMiddleware = Promise; +export interface NestMiddleware { + resolve(...args: any[]): ExpressMiddleware | AsyncExpressMiddleware | Promise; +} diff --git a/lib/common/interfaces/middlewares/nest-middleware.interface.js b/lib/common/interfaces/middlewares/nest-middleware.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/middlewares/nest-middleware.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/modules/index.d.ts b/lib/common/interfaces/modules/index.d.ts new file mode 100644 index 00000000000..e10c22d6487 --- /dev/null +++ b/lib/common/interfaces/modules/index.d.ts @@ -0,0 +1,4 @@ +export * from './module-metadata.interface'; +export * from './module-metatype.interface'; +export * from './nest-module.interface'; +export * from './on-init.interface'; diff --git a/lib/common/interfaces/modules/index.js b/lib/common/interfaces/modules/index.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/modules/index.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/modules/module-metadata.interface.d.ts b/lib/common/interfaces/modules/module-metadata.interface.d.ts new file mode 100644 index 00000000000..b3c8d1ae2d1 --- /dev/null +++ b/lib/common/interfaces/modules/module-metadata.interface.d.ts @@ -0,0 +1,8 @@ +import { NestModule } from './nest-module.interface'; +import { Controller } from '../controllers/controller.interface'; +export interface ModuleMetadata { + modules?: NestModule[] | any[]; + components?: any[]; + controllers?: Controller[] | any[]; + exports?: any[]; +} diff --git a/lib/common/interfaces/modules/module-metadata.interface.js b/lib/common/interfaces/modules/module-metadata.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/modules/module-metadata.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/modules/module-metatype.interface.d.ts b/lib/common/interfaces/modules/module-metatype.interface.d.ts new file mode 100644 index 00000000000..4ecb8cd0333 --- /dev/null +++ b/lib/common/interfaces/modules/module-metatype.interface.d.ts @@ -0,0 +1,4 @@ +import { NestModule } from './nest-module.interface'; +import { Metatype } from '../metatype.interface'; +export interface NestModuleMetatype extends Metatype { +} diff --git a/lib/common/interfaces/modules/module-metatype.interface.js b/lib/common/interfaces/modules/module-metatype.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/modules/module-metatype.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/modules/nest-module.interface.d.ts b/lib/common/interfaces/modules/nest-module.interface.d.ts new file mode 100644 index 00000000000..a18f1212b13 --- /dev/null +++ b/lib/common/interfaces/modules/nest-module.interface.d.ts @@ -0,0 +1,4 @@ +import { MiddlewaresConsumer } from '../middlewares/middlewares-consumer.interface'; +export interface NestModule { + configure(consumer: MiddlewaresConsumer): MiddlewaresConsumer | void; +} diff --git a/lib/common/interfaces/modules/nest-module.interface.js b/lib/common/interfaces/modules/nest-module.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/modules/nest-module.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/modules/on-destroy.interface.d.ts b/lib/common/interfaces/modules/on-destroy.interface.d.ts new file mode 100644 index 00000000000..1ac3e2cf665 --- /dev/null +++ b/lib/common/interfaces/modules/on-destroy.interface.d.ts @@ -0,0 +1,3 @@ +export interface OnModuleDestroy { + onModuleDestroy(): any; +} diff --git a/lib/common/interfaces/modules/on-destroy.interface.js b/lib/common/interfaces/modules/on-destroy.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/modules/on-destroy.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/modules/on-init.interface.d.ts b/lib/common/interfaces/modules/on-init.interface.d.ts new file mode 100644 index 00000000000..2647a33334b --- /dev/null +++ b/lib/common/interfaces/modules/on-init.interface.d.ts @@ -0,0 +1,3 @@ +export interface OnModuleInit { + onModuleInit(): any; +} diff --git a/lib/common/interfaces/modules/on-init.interface.js b/lib/common/interfaces/modules/on-init.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/modules/on-init.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/nest-application-context.interface.d.ts b/lib/common/interfaces/nest-application-context.interface.d.ts new file mode 100644 index 00000000000..b4700c08b2a --- /dev/null +++ b/lib/common/interfaces/nest-application-context.interface.d.ts @@ -0,0 +1,13 @@ +import { Metatype } from './metatype.interface'; +export interface INestApplicationContext { + /** + * Allows you to navigate through the modules tree, for example, to pull out a specific instance from the selected module. + * @returns INestApplicationContext + */ + select(module: Metatype): INestApplicationContext; + /** + * Makes possible to retrieve the instance of the component or controller available inside the processed module. + * @returns T + */ + get(metatypeOrToken: Metatype | string): T; +} diff --git a/lib/common/interfaces/nest-application-context.interface.js b/lib/common/interfaces/nest-application-context.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/nest-application-context.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/nest-application.interface.d.ts b/lib/common/interfaces/nest-application.interface.d.ts new file mode 100644 index 00000000000..cc3ce1297a3 --- /dev/null +++ b/lib/common/interfaces/nest-application.interface.d.ts @@ -0,0 +1,110 @@ +import { MicroserviceConfiguration } from '@nestjs/microservices'; +import { INestMicroservice, ExceptionFilter, PipeTransform } from './index'; +import { WebSocketAdapter } from './web-socket-adapter.interface'; +import { CanActivate } from './can-activate.interface'; +import { NestInterceptor } from './nest-interceptor.interface'; +export interface INestApplication { + /** + * Initializes application. It is not necessary to call this method directly. + * + * @returns Promise + */ + init(): Promise; + /** + * The wrapper function around native `express.use()` method. + * Example `app.use(bodyParser.json())` + * + * @param {} requestHandler Express Request Handler + * @returns void + */ + use(requestHandler: any): void; + /** + * Starts the application. + * + * @param {number} port + * @param {string} hostname + * @param {Function} callback Optional callback + * @returns Promise + */ + listen(port: number, callback?: () => void): Promise; + listen(port: number, hostname: string, callback?: () => void): Promise; + /** + * Starts the application and can be awaited. + * + * @param {number} port + * @param {string} hostname (optional) + * @returns Promise + */ + listenAsync(port: number, hostname?: string): Promise; + /** + * Setups the prefix for the every HTTP route path + * + * @param {string} prefix The prefix for the every HTTP route path (for example `/v1/api`) + * @returns void + */ + setGlobalPrefix(prefix: string): void; + /** + * Setup Web Sockets Adapter, which will be used inside Gateways. + * Use, when you want to override default `socket.io` library. + * + * @param {WebSocketAdapter} adapter + * @returns void + */ + useWebSocketAdapter(adapter: WebSocketAdapter): void; + /** + * Connects microservice to the NestApplication instance. It transforms application to the hybrid instance. + * + * @param {MicroserviceConfiguration} config Microservice configuration objet + * @returns INestMicroservice + */ + connectMicroservice(config: MicroserviceConfiguration): INestMicroservice; + /** + * Returns array of the connected microservices to the NestApplication. + * + * @returns INestMicroservice[] + */ + getMicroservices(): INestMicroservice[]; + /** + * Starts all the connected microservices asynchronously + * + * @param {Function} callback Optional callback function + * @returns void + */ + startAllMicroservices(callback?: () => void): void; + /** + * Starts all the connected microservices and can be awaited + * + * @returns Promise + */ + startAllMicroservicesAsync(): Promise; + /** + * Setups exception filters as a global filters (will be used within every HTTP route handler) + * + * @param {ExceptionFilter[]} ...filters + */ + useGlobalFilters(...filters: ExceptionFilter[]): any; + /** + * Setups pipes as a global pipes (will be used within every HTTP route handler) + * + * @param {PipeTransform[]} ...pipes + */ + useGlobalPipes(...pipes: PipeTransform[]): any; + /** + * Setups interceptors as a global interceptors (will be used within every HTTP route handler) + * + * @param {NestInterceptor[]} ...interceptors + */ + useGlobalInterceptors(...interceptors: NestInterceptor[]): any; + /** + * Setups guards as a global guards (will be used within every HTTP route handler) + * + * @param {CanActivate[]} ...guards + */ + useGlobalGuards(...guards: CanActivate[]): any; + /** + * Terminates the application (both NestApplication, Web Socket Gateways and every connected microservice) + * + * @returns void + */ + close(): void; +} diff --git a/lib/common/interfaces/nest-application.interface.js b/lib/common/interfaces/nest-application.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/nest-application.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/nest-interceptor.interface.d.ts b/lib/common/interfaces/nest-interceptor.interface.d.ts new file mode 100644 index 00000000000..dc3cc95f815 --- /dev/null +++ b/lib/common/interfaces/nest-interceptor.interface.d.ts @@ -0,0 +1,5 @@ +import { Observable } from 'rxjs/Observable'; +import { ExecutionContext } from './execution-context.interface'; +export interface NestInterceptor { + intercept(dataOrRequest: any, context: ExecutionContext, stream$: Observable): Observable | Promise>; +} diff --git a/lib/common/interfaces/nest-interceptor.interface.js b/lib/common/interfaces/nest-interceptor.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/nest-interceptor.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/nest-microservice.interface.d.ts b/lib/common/interfaces/nest-microservice.interface.d.ts new file mode 100644 index 00000000000..e9cf7001905 --- /dev/null +++ b/lib/common/interfaces/nest-microservice.interface.d.ts @@ -0,0 +1,52 @@ +import { WebSocketAdapter } from './web-socket-adapter.interface'; +import { ExceptionFilter } from './exceptions/exception-filter.interface'; +import { PipeTransform } from './pipe-transform.interface'; +import { NestInterceptor } from './nest-interceptor.interface'; +import { CanActivate } from './can-activate.interface'; +export interface INestMicroservice { + /** + * Starts the microservice. + * + * @param {Function} callback Callback called after instant + * @returns Promise + */ + listen(callback: () => void): any; + /** + * Setup Web Sockets Adapter, which will be used inside Gateways. + * Use, when you want to override default `socket.io` library. + * + * @param {WebSocketAdapter} adapter + * @returns void + */ + useWebSocketAdapter(adapter: WebSocketAdapter): void; + /** + * Setups exception filters as a global filters (will be used within every message pattern handler) + * + * @param {ExceptionFilter[]} ...filters + */ + useGlobalFilters(...filters: ExceptionFilter[]): any; + /** + * Setups pipes as a global pipes (will be used within every message pattern handler) + * + * @param {PipeTransform[]} ...pipes + */ + useGlobalPipes(...pipes: PipeTransform[]): any; + /** + * Setups interceptors as a global interceptors (will be used within every message pattern handler) + * + * @param {NestInterceptor[]} ...interceptors + */ + useGlobalInterceptors(...interceptors: NestInterceptor[]): any; + /** + * Setups guards as a global guards (will be used within every message pattern handler) + * + * @param {CanActivate[]} ...guards + */ + useGlobalGuards(...guards: CanActivate[]): any; + /** + * Terminates the application (both NestMicroservice and every Web Socket Gateway) + * + * @returns void + */ + close(): void; +} diff --git a/lib/common/interfaces/nest-microservice.interface.js b/lib/common/interfaces/nest-microservice.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/nest-microservice.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/paramtype.interface.d.ts b/lib/common/interfaces/paramtype.interface.d.ts new file mode 100644 index 00000000000..cdaed174bdd --- /dev/null +++ b/lib/common/interfaces/paramtype.interface.d.ts @@ -0,0 +1 @@ +export declare type Paramtype = 'body' | 'query' | 'param'; diff --git a/lib/common/interfaces/paramtype.interface.js b/lib/common/interfaces/paramtype.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/paramtype.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/pipe-transform.interface.d.ts b/lib/common/interfaces/pipe-transform.interface.d.ts new file mode 100644 index 00000000000..dcd5d1141f6 --- /dev/null +++ b/lib/common/interfaces/pipe-transform.interface.d.ts @@ -0,0 +1,10 @@ +import { Paramtype } from './paramtype.interface'; +export declare type Transform = (value: T, metadata: ArgumentMetadata) => any; +export interface ArgumentMetadata { + type: Paramtype; + metatype?: new (...args) => any; + data?: string; +} +export interface PipeTransform { + transform(value: T, metadata: ArgumentMetadata): any; +} diff --git a/lib/common/interfaces/pipe-transform.interface.js b/lib/common/interfaces/pipe-transform.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/pipe-transform.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/request-mapping-metadata.interface.d.ts b/lib/common/interfaces/request-mapping-metadata.interface.d.ts new file mode 100644 index 00000000000..36a1950eaf8 --- /dev/null +++ b/lib/common/interfaces/request-mapping-metadata.interface.d.ts @@ -0,0 +1,5 @@ +import { RequestMethod } from '../enums/request-method.enum'; +export interface RequestMappingMetadata { + path?: string; + method?: RequestMethod; +} diff --git a/lib/common/interfaces/request-mapping-metadata.interface.js b/lib/common/interfaces/request-mapping-metadata.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/request-mapping-metadata.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/interfaces/web-socket-adapter.interface.d.ts b/lib/common/interfaces/web-socket-adapter.interface.d.ts new file mode 100644 index 00000000000..3e7515a3564 --- /dev/null +++ b/lib/common/interfaces/web-socket-adapter.interface.d.ts @@ -0,0 +1,10 @@ +import { MessageMappingProperties } from '@nestjs/websockets/gateway-metadata-explorer'; +import { Observable } from 'rxjs/Observable'; +export interface WebSocketAdapter { + create(port: number): any; + createWithNamespace?(port: number, namespace: string): any; + bindClientConnect(server: any, callback: (...args) => void): any; + bindClientDisconnect?(client: any, callback: (...args) => void): any; + bindMessageHandlers(client: any, handler: MessageMappingProperties[], process: (data) => Observable): any; + bindMiddleware?(server: any, middleware: (socket, next) => void): any; +} diff --git a/lib/common/interfaces/web-socket-adapter.interface.js b/lib/common/interfaces/web-socket-adapter.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/common/interfaces/web-socket-adapter.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/common/pipes/index.d.ts b/lib/common/pipes/index.d.ts new file mode 100644 index 00000000000..001a3fc7f75 --- /dev/null +++ b/lib/common/pipes/index.d.ts @@ -0,0 +1,2 @@ +export * from './validation.pipe'; +export * from './parse-int.pipe'; diff --git a/lib/common/pipes/index.js b/lib/common/pipes/index.js new file mode 100644 index 00000000000..c56b080c23a --- /dev/null +++ b/lib/common/pipes/index.js @@ -0,0 +1,7 @@ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./validation.pipe")); +__export(require("./parse-int.pipe")); diff --git a/lib/common/pipes/parse-int.pipe.d.ts b/lib/common/pipes/parse-int.pipe.d.ts new file mode 100644 index 00000000000..c6bb2904048 --- /dev/null +++ b/lib/common/pipes/parse-int.pipe.d.ts @@ -0,0 +1,5 @@ +import { PipeTransform } from '../interfaces/pipe-transform.interface'; +import { ArgumentMetadata } from '../index'; +export declare class ParseIntPipe implements PipeTransform { + transform(value: string, metadata: ArgumentMetadata): Promise; +} diff --git a/lib/common/pipes/parse-int.pipe.js b/lib/common/pipes/parse-int.pipe.js new file mode 100644 index 00000000000..84dc4b31709 --- /dev/null +++ b/lib/common/pipes/parse-int.pipe.js @@ -0,0 +1,33 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + 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; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const bad_request_exception_1 = require("../exceptions/bad-request.exception"); +const index_1 = require("../index"); +let ParseIntPipe = class ParseIntPipe { + transform(value, metadata) { + return __awaiter(this, void 0, void 0, function* () { + const val = parseInt(value, 10); + if (isNaN(val)) { + throw new bad_request_exception_1.BadRequestException('Validation failed'); + } + return val; + }); + } +}; +ParseIntPipe = __decorate([ + index_1.Pipe() +], ParseIntPipe); +exports.ParseIntPipe = ParseIntPipe; diff --git a/lib/common/pipes/validation.pipe.d.ts b/lib/common/pipes/validation.pipe.d.ts new file mode 100644 index 00000000000..813b7b00c57 --- /dev/null +++ b/lib/common/pipes/validation.pipe.d.ts @@ -0,0 +1,6 @@ +import { PipeTransform } from '../interfaces/pipe-transform.interface'; +import { ArgumentMetadata } from '../index'; +export declare class ValidationPipe implements PipeTransform { + transform(value: any, metadata: ArgumentMetadata): Promise; + private toValidate(metatype); +} diff --git a/lib/common/pipes/validation.pipe.js b/lib/common/pipes/validation.pipe.js new file mode 100644 index 00000000000..1f462ad27e2 --- /dev/null +++ b/lib/common/pipes/validation.pipe.js @@ -0,0 +1,43 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + 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; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const class_validator_1 = require("class-validator"); +const class_transformer_1 = require("class-transformer"); +const index_1 = require("../index"); +let ValidationPipe = class ValidationPipe { + transform(value, metadata) { + return __awaiter(this, void 0, void 0, function* () { + const { metatype } = metadata; + if (!metatype || !this.toValidate(metatype)) { + return value; + } + const entity = class_transformer_1.plainToClass(metatype, value); + const errors = yield class_validator_1.validate(entity); + if (errors.length > 0) { + throw new index_1.BadRequestException(errors); + } + return value; + }); + } + toValidate(metatype) { + const types = [String, Boolean, Number, Array, Object]; + return !types.find(type => metatype === type); + } +}; +ValidationPipe = __decorate([ + index_1.Pipe() +], ValidationPipe); +exports.ValidationPipe = ValidationPipe; diff --git a/lib/common/services/logger.service.d.ts b/lib/common/services/logger.service.d.ts new file mode 100644 index 00000000000..41131ae9d1e --- /dev/null +++ b/lib/common/services/logger.service.d.ts @@ -0,0 +1,16 @@ +import { NestEnvironment } from '../enums/nest-environment.enum'; +export declare class Logger { + private readonly context; + private readonly printTimestamps; + private static lastTimestamp; + private static contextEnv; + private readonly yellow; + constructor(context: string, printTimestamps?: boolean); + static setMode(mode: NestEnvironment): void; + log(message: string): void; + error(message: string, trace?: string): void; + warn(message: string): void; + private printMessage(message, color); + private printTimestamp(); + private printStackTrace(trace); +} diff --git a/lib/common/services/logger.service.js b/lib/common/services/logger.service.js new file mode 100644 index 00000000000..80265b56786 --- /dev/null +++ b/lib/common/services/logger.service.js @@ -0,0 +1,50 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const clc = require("cli-color"); +const nest_environment_enum_1 = require("../enums/nest-environment.enum"); +class Logger { + constructor(context, printTimestamps = false) { + this.context = context; + this.printTimestamps = printTimestamps; + this.yellow = clc.xterm(3); + } + static setMode(mode) { + this.contextEnv = mode; + } + log(message) { + this.printMessage(message, clc.green); + } + error(message, trace = '') { + this.printMessage(message, clc.red); + this.printStackTrace(trace); + } + warn(message) { + this.printMessage(message, clc.yellow); + } + printMessage(message, color) { + if (Logger.contextEnv === nest_environment_enum_1.NestEnvironment.TEST) + return; + process.stdout.write(color(`[Nest] ${process.pid} - `)); + process.stdout.write(`${new Date(Date.now()).toLocaleString()} `); + process.stdout.write(this.yellow(`[${this.context}] `)); + process.stdout.write(color(message)); + this.printTimestamp(); + process.stdout.write(`\n`); + } + printTimestamp() { + const includeTimestamp = Logger.lastTimestamp && this.printTimestamps; + if (includeTimestamp) { + process.stdout.write(this.yellow(` +${Date.now() - Logger.lastTimestamp}ms`)); + } + Logger.lastTimestamp = Date.now(); + } + printStackTrace(trace) { + if (Logger.contextEnv === nest_environment_enum_1.NestEnvironment.TEST || !trace) + return; + process.stdout.write(trace); + process.stdout.write(`\n`); + } +} +Logger.lastTimestamp = null; +Logger.contextEnv = nest_environment_enum_1.NestEnvironment.RUN; +exports.Logger = Logger; diff --git a/lib/common/utils/bind-resolve-values.util.d.ts b/lib/common/utils/bind-resolve-values.util.d.ts new file mode 100644 index 00000000000..0a42d3550ff --- /dev/null +++ b/lib/common/utils/bind-resolve-values.util.d.ts @@ -0,0 +1,3 @@ +import { Constructor } from './merge-with-values.util'; +import { NestMiddleware } from '../interfaces/middlewares/nest-middleware.interface'; +export declare const BindResolveMiddlewareValues: >(data: any[]) => (Metatype: T) => any; diff --git a/lib/common/utils/bind-resolve-values.util.js b/lib/common/utils/bind-resolve-values.util.js new file mode 100644 index 00000000000..d8d97e66567 --- /dev/null +++ b/lib/common/utils/bind-resolve-values.util.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const component_decorator_1 = require("./decorators/component.decorator"); +exports.BindResolveMiddlewareValues = (data) => { + return (Metatype) => { + const type = class extends Metatype { + resolve() { + return super.resolve(...data); + } + }; + const token = Metatype.name + JSON.stringify(data); + Object.defineProperty(type, 'name', { value: token }); + component_decorator_1.Component()(type); + return type; + }; +}; diff --git a/lib/common/utils/decorators/bind.decorator.d.ts b/lib/common/utils/decorators/bind.decorator.d.ts new file mode 100644 index 00000000000..0ef166a8ddb --- /dev/null +++ b/lib/common/utils/decorators/bind.decorator.d.ts @@ -0,0 +1,6 @@ +/** + * Binds parameters decorators to the method + * Useful when the language doesn't provide a 'Parameter Decorators' feature + * @param {} ...decorators + */ +export declare function Bind(...decorators: any[]): (target: object, key: any, descriptor: any) => any; diff --git a/lib/common/utils/decorators/bind.decorator.js b/lib/common/utils/decorators/bind.decorator.js new file mode 100644 index 00000000000..1ec9f4e64d0 --- /dev/null +++ b/lib/common/utils/decorators/bind.decorator.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Binds parameters decorators to the method + * Useful when the language doesn't provide a 'Parameter Decorators' feature + * @param {} ...decorators + */ +function Bind(...decorators) { + return (target, key, descriptor) => { + decorators.forEach((fn, index) => fn(target, key, index)); + return descriptor; + }; +} +exports.Bind = Bind; diff --git a/lib/common/utils/decorators/catch.decorator.d.ts b/lib/common/utils/decorators/catch.decorator.d.ts new file mode 100644 index 00000000000..6061cb902a9 --- /dev/null +++ b/lib/common/utils/decorators/catch.decorator.d.ts @@ -0,0 +1,6 @@ +import 'reflect-metadata'; +/** + * Defines the Exceptions Filter. Takes set of exception types as an argument, which has to be catched by this Filter. + * The class should implements the `ExceptionFilter` interface. + */ +export declare function Catch(...exceptions: any[]): ClassDecorator; diff --git a/lib/common/utils/decorators/catch.decorator.js b/lib/common/utils/decorators/catch.decorator.js new file mode 100644 index 00000000000..6bd8fdb3553 --- /dev/null +++ b/lib/common/utils/decorators/catch.decorator.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("../../constants"); +/** + * Defines the Exceptions Filter. Takes set of exception types as an argument, which has to be catched by this Filter. + * The class should implements the `ExceptionFilter` interface. + */ +function Catch(...exceptions) { + return (target) => { + Reflect.defineMetadata(constants_1.FILTER_CATCH_EXCEPTIONS, exceptions, target); + }; +} +exports.Catch = Catch; diff --git a/lib/common/utils/decorators/component.decorator.d.ts b/lib/common/utils/decorators/component.decorator.d.ts new file mode 100644 index 00000000000..e290f030884 --- /dev/null +++ b/lib/common/utils/decorators/component.decorator.d.ts @@ -0,0 +1,22 @@ +/** + * Defines the Component. The component can inject dependencies through constructor. + * Those dependencies should belongs to the same module. + */ +export declare function Component(): ClassDecorator; +/** + * Defines the Pipe. The Pipe should implements the `PipeTransform` interface. + */ +export declare function Pipe(): ClassDecorator; +/** + * Defines the Guard. The Guard should implement the `CanActivate` interface. + */ +export declare function Guard(): ClassDecorator; +/** + * Defines the Middleware. The Middleware should implement the `NestMiddleware` interface. + */ +export declare function Middleware(): ClassDecorator; +/** + * Defines the Interceptor. The Interceptor should implement `HttpInterceptor`, `RpcInterceptor` or `WsInterceptor` interface. + */ +export declare function Interceptor(): ClassDecorator; +export declare function mixin(mixinClass: any): any; diff --git a/lib/common/utils/decorators/component.decorator.js b/lib/common/utils/decorators/component.decorator.js new file mode 100644 index 00000000000..72e5628df43 --- /dev/null +++ b/lib/common/utils/decorators/component.decorator.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Defines the Component. The component can inject dependencies through constructor. + * Those dependencies should belongs to the same module. + */ +function Component() { + return (target) => { }; +} +exports.Component = Component; +/** + * Defines the Pipe. The Pipe should implements the `PipeTransform` interface. + */ +function Pipe() { + return (target) => { }; +} +exports.Pipe = Pipe; +/** + * Defines the Guard. The Guard should implement the `CanActivate` interface. + */ +function Guard() { + return (target) => { }; +} +exports.Guard = Guard; +/** + * Defines the Middleware. The Middleware should implement the `NestMiddleware` interface. + */ +function Middleware() { + return (target) => { }; +} +exports.Middleware = Middleware; +/** + * Defines the Interceptor. The Interceptor should implement `HttpInterceptor`, `RpcInterceptor` or `WsInterceptor` interface. + */ +function Interceptor() { + return (target) => { }; +} +exports.Interceptor = Interceptor; +function mixin(mixinClass) { + this.offset = this.offset ? ++this.offset : (Math.random() * 100); + Object.defineProperty(mixinClass, 'name', { value: JSON.stringify(this.offset) }); + Component()(mixinClass); + return mixinClass; +} +exports.mixin = mixin; diff --git a/lib/common/utils/decorators/controller.decorator.d.ts b/lib/common/utils/decorators/controller.decorator.d.ts new file mode 100644 index 00000000000..72aeebc5756 --- /dev/null +++ b/lib/common/utils/decorators/controller.decorator.d.ts @@ -0,0 +1,6 @@ +import 'reflect-metadata'; +/** + * Defines the Controller. The controller can inject dependencies through constructor. + * Those dependencies should belongs to the same module. + */ +export declare function Controller(prefix?: string): ClassDecorator; diff --git a/lib/common/utils/decorators/controller.decorator.js b/lib/common/utils/decorators/controller.decorator.js new file mode 100644 index 00000000000..200bc4fbca0 --- /dev/null +++ b/lib/common/utils/decorators/controller.decorator.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const shared_utils_1 = require("../shared.utils"); +const constants_1 = require("../../constants"); +/** + * Defines the Controller. The controller can inject dependencies through constructor. + * Those dependencies should belongs to the same module. + */ +function Controller(prefix) { + const path = shared_utils_1.isUndefined(prefix) ? '/' : prefix; + return (target) => { + Reflect.defineMetadata(constants_1.PATH_METADATA, path, target); + }; +} +exports.Controller = Controller; diff --git a/lib/common/utils/decorators/create-route-param-metadata.decorator.d.ts b/lib/common/utils/decorators/create-route-param-metadata.decorator.d.ts new file mode 100644 index 00000000000..88065650f5a --- /dev/null +++ b/lib/common/utils/decorators/create-route-param-metadata.decorator.d.ts @@ -0,0 +1,7 @@ +import { CustomParamFactory } from '../../interfaces/custom-route-param-factory.interface'; +import { ParamData } from './route-params.decorator'; +/** + * Create route params custom decorator + * @param factory + */ +export declare const createRouteParamDecorator: (factory: CustomParamFactory) => (data?: ParamData) => ParameterDecorator; diff --git a/lib/common/utils/decorators/create-route-param-metadata.decorator.js b/lib/common/utils/decorators/create-route-param-metadata.decorator.js new file mode 100644 index 00000000000..3b4b96f7455 --- /dev/null +++ b/lib/common/utils/decorators/create-route-param-metadata.decorator.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const constants_1 = require("../../constants"); +const assignCustomMetadata = (args, paramtype, index, factory, data) => (Object.assign({}, args, { [`${index}:${paramtype}${constants_1.CUSTOM_ROUTE_AGRS_METADATA}:${index}`]: { + index, + factory, + data, + } })); +const randomString = () => Math.random().toString(36).substring(2, 15); +/** + * Create route params custom decorator + * @param factory + */ +exports.createRouteParamDecorator = (factory) => { + const paramtype = randomString() + randomString(); + return (data) => (target, key, index) => { + const args = Reflect.getMetadata(constants_1.ROUTE_ARGS_METADATA, target, key) || {}; + Reflect.defineMetadata(constants_1.ROUTE_ARGS_METADATA, assignCustomMetadata(args, paramtype, index, factory, data), target, key); + }; +}; diff --git a/lib/common/utils/decorators/dependencies.decorator.d.ts b/lib/common/utils/decorators/dependencies.decorator.d.ts new file mode 100644 index 00000000000..b5e8863499b --- /dev/null +++ b/lib/common/utils/decorators/dependencies.decorator.d.ts @@ -0,0 +1,2 @@ +import 'reflect-metadata'; +export declare const Dependencies: (...dependencies: any[]) => ClassDecorator; diff --git a/lib/common/utils/decorators/dependencies.decorator.js b/lib/common/utils/decorators/dependencies.decorator.js new file mode 100644 index 00000000000..aae76eec67f --- /dev/null +++ b/lib/common/utils/decorators/dependencies.decorator.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("../../constants"); +const flatten = arr => { + const flat = [].concat(...arr); + return flat.some(Array.isArray) ? flatten(flat) : flat; +}; +exports.Dependencies = (...dependencies) => { + const flattenDeps = flatten(dependencies); + return (target) => { + Reflect.defineMetadata(constants_1.PARAMTYPES_METADATA, flattenDeps, target); + }; +}; diff --git a/lib/common/utils/decorators/exception-filters.decorator.d.ts b/lib/common/utils/decorators/exception-filters.decorator.d.ts new file mode 100644 index 00000000000..68f0c250bc1 --- /dev/null +++ b/lib/common/utils/decorators/exception-filters.decorator.d.ts @@ -0,0 +1,13 @@ +import 'reflect-metadata'; +import { ExceptionFilter } from '../../index'; +/** + * Setups exception filters to the chosen context. + * When the `@UseFilters()` is used on the controller level: + * - Exception Filter will be set up to every handler (every method) + * + * When the `@UseFilters()` is used on the handle level: + * - Exception Filter will be set up only to specified method + * + * @param {ExceptionFilter[]} ...filters (instances) + */ +export declare const UseFilters: (...filters: ExceptionFilter[]) => (target: object, key?: any, descriptor?: any) => any; diff --git a/lib/common/utils/decorators/exception-filters.decorator.js b/lib/common/utils/decorators/exception-filters.decorator.js new file mode 100644 index 00000000000..4bd19ea0c30 --- /dev/null +++ b/lib/common/utils/decorators/exception-filters.decorator.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("../../constants"); +const defineFiltersMetadata = (...filters) => { + return (target, key, descriptor) => { + if (descriptor) { + Reflect.defineMetadata(constants_1.EXCEPTION_FILTERS_METADATA, filters, descriptor.value); + return descriptor; + } + Reflect.defineMetadata(constants_1.EXCEPTION_FILTERS_METADATA, filters, target); + return target; + }; +}; +/** + * Setups exception filters to the chosen context. + * When the `@UseFilters()` is used on the controller level: + * - Exception Filter will be set up to every handler (every method) + * + * When the `@UseFilters()` is used on the handle level: + * - Exception Filter will be set up only to specified method + * + * @param {ExceptionFilter[]} ...filters (instances) + */ +exports.UseFilters = (...filters) => defineFiltersMetadata(...filters); diff --git a/lib/common/utils/decorators/exceptions/constants.d.ts b/lib/common/utils/decorators/exceptions/constants.d.ts new file mode 100644 index 00000000000..3aff18f8ed8 --- /dev/null +++ b/lib/common/utils/decorators/exceptions/constants.d.ts @@ -0,0 +1 @@ +export declare const InvalidModuleConfigMessage: (property: string) => string; diff --git a/lib/common/utils/decorators/exceptions/constants.js b/lib/common/utils/decorators/exceptions/constants.js new file mode 100644 index 00000000000..0f51c932ee3 --- /dev/null +++ b/lib/common/utils/decorators/exceptions/constants.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.InvalidModuleConfigMessage = (property) => `Invalid property '${property}' in @Module() decorator.`; diff --git a/lib/common/utils/decorators/exceptions/invalid-module-config.exception.d.ts b/lib/common/utils/decorators/exceptions/invalid-module-config.exception.d.ts new file mode 100644 index 00000000000..8d2a089ebf6 --- /dev/null +++ b/lib/common/utils/decorators/exceptions/invalid-module-config.exception.d.ts @@ -0,0 +1,3 @@ +export declare class InvalidModuleConfigException extends Error { + constructor(property: string); +} diff --git a/lib/common/utils/decorators/exceptions/invalid-module-config.exception.js b/lib/common/utils/decorators/exceptions/invalid-module-config.exception.js new file mode 100644 index 00000000000..21bdd384838 --- /dev/null +++ b/lib/common/utils/decorators/exceptions/invalid-module-config.exception.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const constants_1 = require("./constants"); +class InvalidModuleConfigException extends Error { + constructor(property) { + super(constants_1.InvalidModuleConfigMessage(property)); + } +} +exports.InvalidModuleConfigException = InvalidModuleConfigException; diff --git a/lib/common/utils/decorators/http-code.decorator.d.ts b/lib/common/utils/decorators/http-code.decorator.d.ts new file mode 100644 index 00000000000..fad38886aaf --- /dev/null +++ b/lib/common/utils/decorators/http-code.decorator.d.ts @@ -0,0 +1,7 @@ +/** + * Defines the HTTP status code, which should be sent with response. + * It overrides default status code for the given request method. + * + * @param {number} statusCode + */ +export declare function HttpCode(statusCode: number): MethodDecorator; diff --git a/lib/common/utils/decorators/http-code.decorator.js b/lib/common/utils/decorators/http-code.decorator.js new file mode 100644 index 00000000000..27e4fb79519 --- /dev/null +++ b/lib/common/utils/decorators/http-code.decorator.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const constants_1 = require("../../constants"); +/** + * Defines the HTTP status code, which should be sent with response. + * It overrides default status code for the given request method. + * + * @param {number} statusCode + */ +function HttpCode(statusCode) { + return (target, key, descriptor) => { + Reflect.defineMetadata(constants_1.HTTP_CODE_METADATA, statusCode, descriptor.value); + return descriptor; + }; +} +exports.HttpCode = HttpCode; diff --git a/lib/common/utils/decorators/inject.decorator.d.ts b/lib/common/utils/decorators/inject.decorator.d.ts new file mode 100644 index 00000000000..a7c1c8927b0 --- /dev/null +++ b/lib/common/utils/decorators/inject.decorator.d.ts @@ -0,0 +1,6 @@ +import 'reflect-metadata'; +/** + * Injects component, which has to be available in the current injector (module) scope. + * Components are recognized by types / or tokens. + */ +export declare function Inject(token: any): ParameterDecorator; diff --git a/lib/common/utils/decorators/inject.decorator.js b/lib/common/utils/decorators/inject.decorator.js new file mode 100644 index 00000000000..06d196e3837 --- /dev/null +++ b/lib/common/utils/decorators/inject.decorator.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("../../constants"); +const shared_utils_1 = require("../shared.utils"); +/** + * Injects component, which has to be available in the current injector (module) scope. + * Components are recognized by types / or tokens. + */ +function Inject(token) { + return (target, key, index) => { + const args = Reflect.getMetadata(constants_1.SELF_DECLARED_DEPS_METADATA, target) || []; + const type = shared_utils_1.isFunction(token) ? token.name : token; + args.push({ index, param: type }); + Reflect.defineMetadata(constants_1.SELF_DECLARED_DEPS_METADATA, args, target); + }; +} +exports.Inject = Inject; diff --git a/lib/common/utils/decorators/module.decorator.d.ts b/lib/common/utils/decorators/module.decorator.d.ts new file mode 100644 index 00000000000..259210018d7 --- /dev/null +++ b/lib/common/utils/decorators/module.decorator.d.ts @@ -0,0 +1,15 @@ +import 'reflect-metadata'; +/** + * Defines the module + * - `modules` - the set of the 'imported' modules + * - `controllers` - the list of controllers (e.g. HTTP controllers) + * - `components` - the list of components that belong to this module. They can be injected between themselves. + * - `exports` - the set of components, which should be available for modules, which imports this module + * @param obj {ModuleMetadata} Module metadata + */ +export declare function Module(obj: { + modules?: any[]; + controllers?: any[]; + components?: any[]; + exports?: any[]; +}): ClassDecorator; diff --git a/lib/common/utils/decorators/module.decorator.js b/lib/common/utils/decorators/module.decorator.js new file mode 100644 index 00000000000..43e0f20c14b --- /dev/null +++ b/lib/common/utils/decorators/module.decorator.js @@ -0,0 +1,40 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const invalid_module_config_exception_1 = require("./exceptions/invalid-module-config.exception"); +const constants_1 = require("../../constants"); +const metadataKeys = [ + constants_1.metadata.MODULES, + constants_1.metadata.EXPORTS, + constants_1.metadata.COMPONENTS, + constants_1.metadata.CONTROLLERS, +]; +const validateKeys = (keys) => { + const isKeyValid = (key) => metadataKeys.findIndex(k => k === key) < 0; + const validateKey = (key) => { + if (isKeyValid(key)) { + throw new invalid_module_config_exception_1.InvalidModuleConfigException(key); + } + }; + keys.forEach(validateKey); +}; +/** + * Defines the module + * - `modules` - the set of the 'imported' modules + * - `controllers` - the list of controllers (e.g. HTTP controllers) + * - `components` - the list of components that belong to this module. They can be injected between themselves. + * - `exports` - the set of components, which should be available for modules, which imports this module + * @param obj {ModuleMetadata} Module metadata + */ +function Module(obj) { + const propsKeys = Object.keys(obj); + validateKeys(propsKeys); + return (target) => { + for (const property in obj) { + if (obj.hasOwnProperty(property)) { + Reflect.defineMetadata(property, obj[property], target); + } + } + }; +} +exports.Module = Module; diff --git a/lib/common/utils/decorators/reflect-metadata.decorator.d.ts b/lib/common/utils/decorators/reflect-metadata.decorator.d.ts new file mode 100644 index 00000000000..bd43ca76128 --- /dev/null +++ b/lib/common/utils/decorators/reflect-metadata.decorator.d.ts @@ -0,0 +1,5 @@ +/** + * Assigns the metadata to the class / function under specified `key`. + * This metadata can be reflected using `Reflector` class. + */ +export declare const ReflectMetadata: (metadataKey: any, metadataValue: any) => (target: object, key?: any, descriptor?: any) => any; diff --git a/lib/common/utils/decorators/reflect-metadata.decorator.js b/lib/common/utils/decorators/reflect-metadata.decorator.js new file mode 100644 index 00000000000..d952cd70bac --- /dev/null +++ b/lib/common/utils/decorators/reflect-metadata.decorator.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Assigns the metadata to the class / function under specified `key`. + * This metadata can be reflected using `Reflector` class. + */ +exports.ReflectMetadata = (metadataKey, metadataValue) => (target, key, descriptor) => { + if (descriptor) { + Reflect.defineMetadata(metadataKey, metadataValue, descriptor.value); + return descriptor; + } + Reflect.defineMetadata(metadataKey, metadataValue, target); + return target; +}; diff --git a/lib/common/utils/decorators/request-mapping.decorator.d.ts b/lib/common/utils/decorators/request-mapping.decorator.d.ts new file mode 100644 index 00000000000..988e1e34310 --- /dev/null +++ b/lib/common/utils/decorators/request-mapping.decorator.d.ts @@ -0,0 +1,35 @@ +import 'reflect-metadata'; +import { RequestMappingMetadata } from '../../interfaces/request-mapping-metadata.interface'; +export declare const RequestMapping: (metadata?: RequestMappingMetadata) => MethodDecorator; +/** + * Routes HTTP POST requests to the specified path. + */ +export declare const Post: (path?: string) => MethodDecorator; +/** + * Routes HTTP GET requests to the specified path. + */ +export declare const Get: (path?: string) => MethodDecorator; +/** + * Routes HTTP DELETE requests to the specified path. + */ +export declare const Delete: (path?: string) => MethodDecorator; +/** + * Routes HTTP PUT requests to the specified path. + */ +export declare const Put: (path?: string) => MethodDecorator; +/** + * Routes HTTP PATCH requests to the specified path. + */ +export declare const Patch: (path?: string) => MethodDecorator; +/** + * Routes HTTP OPTIONS requests to the specified path. + */ +export declare const Options: (path?: string) => MethodDecorator; +/** + * Routes HTTP HEAD requests to the specified path. + */ +export declare const Head: (path?: string) => MethodDecorator; +/** + * Routes all HTTP requests to the specified path. + */ +export declare const All: (path?: string) => MethodDecorator; diff --git a/lib/common/utils/decorators/request-mapping.decorator.js b/lib/common/utils/decorators/request-mapping.decorator.js new file mode 100644 index 00000000000..45a9eedee1e --- /dev/null +++ b/lib/common/utils/decorators/request-mapping.decorator.js @@ -0,0 +1,56 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const request_method_enum_1 = require("../../enums/request-method.enum"); +const constants_1 = require("../../constants"); +const defaultMetadata = { + [constants_1.PATH_METADATA]: '/', + [constants_1.METHOD_METADATA]: request_method_enum_1.RequestMethod.GET, +}; +exports.RequestMapping = (metadata = defaultMetadata) => { + const path = metadata[constants_1.PATH_METADATA] || '/'; + const requestMethod = metadata[constants_1.METHOD_METADATA] || request_method_enum_1.RequestMethod.GET; + return (target, key, descriptor) => { + Reflect.defineMetadata(constants_1.PATH_METADATA, path, descriptor.value); + Reflect.defineMetadata(constants_1.METHOD_METADATA, requestMethod, descriptor.value); + return descriptor; + }; +}; +const createMappingDecorator = (method) => (path) => { + return exports.RequestMapping({ + [constants_1.PATH_METADATA]: path, + [constants_1.METHOD_METADATA]: method, + }); +}; +/** + * Routes HTTP POST requests to the specified path. + */ +exports.Post = createMappingDecorator(request_method_enum_1.RequestMethod.POST); +/** + * Routes HTTP GET requests to the specified path. + */ +exports.Get = createMappingDecorator(request_method_enum_1.RequestMethod.GET); +/** + * Routes HTTP DELETE requests to the specified path. + */ +exports.Delete = createMappingDecorator(request_method_enum_1.RequestMethod.DELETE); +/** + * Routes HTTP PUT requests to the specified path. + */ +exports.Put = createMappingDecorator(request_method_enum_1.RequestMethod.PUT); +/** + * Routes HTTP PATCH requests to the specified path. + */ +exports.Patch = createMappingDecorator(request_method_enum_1.RequestMethod.PATCH); +/** + * Routes HTTP OPTIONS requests to the specified path. + */ +exports.Options = createMappingDecorator(request_method_enum_1.RequestMethod.OPTIONS); +/** + * Routes HTTP HEAD requests to the specified path. + */ +exports.Head = createMappingDecorator(request_method_enum_1.RequestMethod.HEAD); +/** + * Routes all HTTP requests to the specified path. + */ +exports.All = createMappingDecorator(request_method_enum_1.RequestMethod.ALL); diff --git a/lib/common/utils/decorators/route-params.decorator.d.ts b/lib/common/utils/decorators/route-params.decorator.d.ts new file mode 100644 index 00000000000..087e01390e8 --- /dev/null +++ b/lib/common/utils/decorators/route-params.decorator.d.ts @@ -0,0 +1,25 @@ +import 'reflect-metadata'; +import { PipeTransform } from '../../index'; +export declare type ParamData = object | string | number; +export interface RouteParamsMetadata { + [prop: number]: { + index: number; + data?: ParamData; + }; +} +export declare const Request: () => ParameterDecorator; +export declare const Response: () => ParameterDecorator; +export declare const Next: () => ParameterDecorator; +export declare const Session: () => ParameterDecorator; +export declare const Headers: (property?: string) => ParameterDecorator; +export declare function Query(): any; +export declare function Query(...pipes: PipeTransform[]): any; +export declare function Query(property: string, ...pipes: PipeTransform[]): any; +export declare function Body(): any; +export declare function Body(...pipes: PipeTransform[]): any; +export declare function Body(property: string, ...pipes: PipeTransform[]): any; +export declare function Param(): any; +export declare function Param(...pipes: PipeTransform[]): any; +export declare function Param(property: string, ...pipes: PipeTransform[]): any; +export declare const Req: () => ParameterDecorator; +export declare const Res: () => ParameterDecorator; diff --git a/lib/common/utils/decorators/route-params.decorator.js b/lib/common/utils/decorators/route-params.decorator.js new file mode 100644 index 00000000000..c1ef52134f9 --- /dev/null +++ b/lib/common/utils/decorators/route-params.decorator.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("../../constants"); +const route_paramtypes_enum_1 = require("../../enums/route-paramtypes.enum"); +const shared_utils_1 = require("../shared.utils"); +const assignMetadata = (args, paramtype, index, data, ...pipes) => (Object.assign({}, args, { [`${paramtype}:${index}`]: { + index, + data, + pipes, + } })); +const createRouteParamDecorator = (paramtype) => { + return (data) => (target, key, index) => { + const args = Reflect.getMetadata(constants_1.ROUTE_ARGS_METADATA, target, key) || {}; + Reflect.defineMetadata(constants_1.ROUTE_ARGS_METADATA, assignMetadata(args, paramtype, index, data), target, key); + }; +}; +const createPipesRouteParamDecorator = (paramtype) => (data, ...pipes) => (target, key, index) => { + const args = Reflect.getMetadata(constants_1.ROUTE_ARGS_METADATA, target, key) || {}; + const hasParamData = shared_utils_1.isNil(data) || shared_utils_1.isString(data); + const paramData = hasParamData ? data : undefined; + const paramPipes = hasParamData ? pipes : [data, ...pipes]; + Reflect.defineMetadata(constants_1.ROUTE_ARGS_METADATA, assignMetadata(args, paramtype, index, paramData, ...paramPipes), target, key); +}; +exports.Request = createRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.REQUEST); +exports.Response = createRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.RESPONSE); +exports.Next = createRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.NEXT); +exports.Session = createRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.SESSION); +exports.Headers = createRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.HEADERS); +function Query(property, ...pipes) { + return createPipesRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.QUERY)(property, ...pipes); +} +exports.Query = Query; +function Body(property, ...pipes) { + return createPipesRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.BODY)(property, ...pipes); +} +exports.Body = Body; +function Param(property, ...pipes) { + return createPipesRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.PARAM)(property, ...pipes); +} +exports.Param = Param; +exports.Req = exports.Request; +exports.Res = exports.Response; diff --git a/lib/common/utils/decorators/shared.decorator.d.ts b/lib/common/utils/decorators/shared.decorator.d.ts new file mode 100644 index 00000000000..578f73e930a --- /dev/null +++ b/lib/common/utils/decorators/shared.decorator.d.ts @@ -0,0 +1,7 @@ +import 'reflect-metadata'; +/** + * Specifies scope of this module. When module is `@Shared()`, Nest will create only one instance of this + * module and share them between all of the modules. + * @deprecated + */ +export declare const Shared: (scope?: string) => (target: any) => any; diff --git a/lib/common/utils/decorators/shared.decorator.js b/lib/common/utils/decorators/shared.decorator.js new file mode 100644 index 00000000000..952d406fb97 --- /dev/null +++ b/lib/common/utils/decorators/shared.decorator.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("../../constants"); +const index_1 = require("../../index"); +/** + * Specifies scope of this module. When module is `@Shared()`, Nest will create only one instance of this + * module and share them between all of the modules. + * @deprecated + */ +exports.Shared = (scope = 'global') => { + const logger = new index_1.Logger('Shared'); + logger.warn('DEPRECATED! Since version 4.0.0 `@Shared()` decorator is deprecated. All modules are singletons now.'); + return (target) => { + const Metatype = target; + const Type = class extends Metatype { + constructor(...args) { + super(...args); + } + }; + Reflect.defineMetadata(constants_1.SHARED_MODULE_METADATA, scope, Type); + Object.defineProperty(Type, 'name', { value: target.name }); + return Type; + }; +}; diff --git a/lib/common/utils/decorators/single-scope.decorator.d.ts b/lib/common/utils/decorators/single-scope.decorator.d.ts new file mode 100644 index 00000000000..9da25bbaac1 --- /dev/null +++ b/lib/common/utils/decorators/single-scope.decorator.d.ts @@ -0,0 +1,6 @@ +import 'reflect-metadata'; +/** + * Makes the module single-scoped (not singleton). + * Nest will always create the new instance of the module, when it's imported by another one. + */ +export declare function SingleScope(): ClassDecorator; diff --git a/lib/common/utils/decorators/single-scope.decorator.js b/lib/common/utils/decorators/single-scope.decorator.js new file mode 100644 index 00000000000..b511fda70a5 --- /dev/null +++ b/lib/common/utils/decorators/single-scope.decorator.js @@ -0,0 +1,23 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("../../constants"); +/** + * Makes the module single-scoped (not singleton). + * Nest will always create the new instance of the module, when it's imported by another one. + */ +function SingleScope() { + return (target) => { + const Metatype = target; + const Type = class extends Metatype { + constructor(...args) { + super(...args); + } + }; + Reflect.defineMetadata(constants_1.SHARED_MODULE_METADATA, true, Type); + Object.defineProperty(Type, 'name', { value: target.name }); + return Type; + }; +} +exports.SingleScope = SingleScope; +; diff --git a/lib/common/utils/decorators/use-guards.decorator.d.ts b/lib/common/utils/decorators/use-guards.decorator.d.ts new file mode 100644 index 00000000000..027fc210be4 --- /dev/null +++ b/lib/common/utils/decorators/use-guards.decorator.d.ts @@ -0,0 +1,11 @@ +/** + * Setups guards to the chosen context. + * When the `@UseGuards()` is used on the controller level: + * - Guard will be set up to every handler (every method) + * + * When the `@UseGuards()` is used on the handle level: + * - Guard will be set up only to specified method + * + * @param {} ...guards (types) + */ +export declare function UseGuards(...guards: any[]): (target: object, key?: any, descriptor?: any) => any; diff --git a/lib/common/utils/decorators/use-guards.decorator.js b/lib/common/utils/decorators/use-guards.decorator.js new file mode 100644 index 00000000000..26f5a4844f6 --- /dev/null +++ b/lib/common/utils/decorators/use-guards.decorator.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const constants_1 = require("../../constants"); +/** + * Setups guards to the chosen context. + * When the `@UseGuards()` is used on the controller level: + * - Guard will be set up to every handler (every method) + * + * When the `@UseGuards()` is used on the handle level: + * - Guard will be set up only to specified method + * + * @param {} ...guards (types) + */ +function UseGuards(...guards) { + return (target, key, descriptor) => { + if (descriptor) { + Reflect.defineMetadata(constants_1.GUARDS_METADATA, guards, descriptor.value); + return descriptor; + } + Reflect.defineMetadata(constants_1.GUARDS_METADATA, guards, target); + return target; + }; +} +exports.UseGuards = UseGuards; diff --git a/lib/common/utils/decorators/use-interceptors.decorator.d.ts b/lib/common/utils/decorators/use-interceptors.decorator.d.ts new file mode 100644 index 00000000000..e9ced6e0de3 --- /dev/null +++ b/lib/common/utils/decorators/use-interceptors.decorator.d.ts @@ -0,0 +1,11 @@ +/** + * Setups interceptors to the chosen context. + * When the `@UseInterceptors()` is used on the controller level: + * - Interceptor will be set up to every handler (every method) + * + * When the `@UseInterceptors()` is used on the handle level: + * - Interceptor will be set up only to specified method + * + * @param {} ...interceptors (types) + */ +export declare function UseInterceptors(...interceptors: any[]): (target: object, key?: any, descriptor?: any) => any; diff --git a/lib/common/utils/decorators/use-interceptors.decorator.js b/lib/common/utils/decorators/use-interceptors.decorator.js new file mode 100644 index 00000000000..bb4f6250452 --- /dev/null +++ b/lib/common/utils/decorators/use-interceptors.decorator.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const constants_1 = require("../../constants"); +/** + * Setups interceptors to the chosen context. + * When the `@UseInterceptors()` is used on the controller level: + * - Interceptor will be set up to every handler (every method) + * + * When the `@UseInterceptors()` is used on the handle level: + * - Interceptor will be set up only to specified method + * + * @param {} ...interceptors (types) + */ +function UseInterceptors(...interceptors) { + return (target, key, descriptor) => { + if (descriptor) { + Reflect.defineMetadata(constants_1.INTERCEPTORS_METADATA, interceptors, descriptor.value); + return descriptor; + } + Reflect.defineMetadata(constants_1.INTERCEPTORS_METADATA, interceptors, target); + return target; + }; +} +exports.UseInterceptors = UseInterceptors; diff --git a/lib/common/utils/decorators/use-pipes.decorator.d.ts b/lib/common/utils/decorators/use-pipes.decorator.d.ts new file mode 100644 index 00000000000..f1d08216c45 --- /dev/null +++ b/lib/common/utils/decorators/use-pipes.decorator.d.ts @@ -0,0 +1,12 @@ +import { PipeTransform } from '../../interfaces/index'; +/** + * Setups pipes to the chosen context. + * When the `@UsePipes()` is used on the controller level: + * - Pipe will be set up to every handler (every method) + * + * When the `@UsePipes()` is used on the handle level: + * - Pipe will be set up only to specified method + * + * @param {PipeTransform[]} ...pipes (instances) + */ +export declare function UsePipes(...pipes: PipeTransform[]): (target: object, key?: any, descriptor?: any) => any; diff --git a/lib/common/utils/decorators/use-pipes.decorator.js b/lib/common/utils/decorators/use-pipes.decorator.js new file mode 100644 index 00000000000..dd3b0fe6b24 --- /dev/null +++ b/lib/common/utils/decorators/use-pipes.decorator.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const constants_1 = require("../../constants"); +/** + * Setups pipes to the chosen context. + * When the `@UsePipes()` is used on the controller level: + * - Pipe will be set up to every handler (every method) + * + * When the `@UsePipes()` is used on the handle level: + * - Pipe will be set up only to specified method + * + * @param {PipeTransform[]} ...pipes (instances) + */ +function UsePipes(...pipes) { + return (target, key, descriptor) => { + if (descriptor) { + Reflect.defineMetadata(constants_1.PIPES_METADATA, pipes, descriptor.value); + return descriptor; + } + Reflect.defineMetadata(constants_1.PIPES_METADATA, pipes, target); + return target; + }; +} +exports.UsePipes = UsePipes; diff --git a/lib/common/utils/forward-ref.util.d.ts b/lib/common/utils/forward-ref.util.d.ts new file mode 100644 index 00000000000..33bde634545 --- /dev/null +++ b/lib/common/utils/forward-ref.util.d.ts @@ -0,0 +1,3 @@ +export declare function forwardRef(fn: () => any): { + forwardRef: () => any; +}; diff --git a/lib/common/utils/forward-ref.util.js b/lib/common/utils/forward-ref.util.js new file mode 100644 index 00000000000..217606e5b54 --- /dev/null +++ b/lib/common/utils/forward-ref.util.js @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function forwardRef(fn) { + return { forwardRef: fn }; +} +exports.forwardRef = forwardRef; diff --git a/lib/common/utils/http-exception-body.util.d.ts b/lib/common/utils/http-exception-body.util.d.ts new file mode 100644 index 00000000000..32944fa29c8 --- /dev/null +++ b/lib/common/utils/http-exception-body.util.d.ts @@ -0,0 +1,8 @@ +export declare const createHttpExceptionBody: (message: any, error: string, status: number) => { + statusCode: number; + error: string; + message: any; +} | { + statusCode: number; + error: string; +}; diff --git a/lib/common/utils/http-exception-body.util.js b/lib/common/utils/http-exception-body.util.js new file mode 100644 index 00000000000..fe6bc14a4e6 --- /dev/null +++ b/lib/common/utils/http-exception-body.util.js @@ -0,0 +1,5 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createHttpExceptionBody = (message, error, status) => message + ? { statusCode: status, error, message } + : { statusCode: status, error }; diff --git a/lib/common/utils/index.d.ts b/lib/common/utils/index.d.ts new file mode 100644 index 00000000000..6f2edce40dd --- /dev/null +++ b/lib/common/utils/index.d.ts @@ -0,0 +1,19 @@ +export * from './decorators/request-mapping.decorator'; +export * from './decorators/controller.decorator'; +export * from './decorators/component.decorator'; +export * from './decorators/module.decorator'; +export * from './decorators/dependencies.decorator'; +export * from './decorators/inject.decorator'; +export * from './decorators/route-params.decorator'; +export * from './decorators/catch.decorator'; +export * from './decorators/exception-filters.decorator'; +export * from './decorators/shared.decorator'; +export * from './decorators/single-scope.decorator'; +export * from './decorators/use-pipes.decorator'; +export * from './decorators/use-guards.decorator'; +export * from './decorators/reflect-metadata.decorator'; +export * from './decorators/use-interceptors.decorator'; +export * from './decorators/http-code.decorator'; +export * from './decorators/bind.decorator'; +export * from './forward-ref.util'; +export * from './decorators/create-route-param-metadata.decorator'; diff --git a/lib/common/utils/index.js b/lib/common/utils/index.js new file mode 100644 index 00000000000..6de5d6cf99f --- /dev/null +++ b/lib/common/utils/index.js @@ -0,0 +1,24 @@ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./decorators/request-mapping.decorator")); +__export(require("./decorators/controller.decorator")); +__export(require("./decorators/component.decorator")); +__export(require("./decorators/module.decorator")); +__export(require("./decorators/dependencies.decorator")); +__export(require("./decorators/inject.decorator")); +__export(require("./decorators/route-params.decorator")); +__export(require("./decorators/catch.decorator")); +__export(require("./decorators/exception-filters.decorator")); +__export(require("./decorators/shared.decorator")); +__export(require("./decorators/single-scope.decorator")); +__export(require("./decorators/use-pipes.decorator")); +__export(require("./decorators/use-guards.decorator")); +__export(require("./decorators/reflect-metadata.decorator")); +__export(require("./decorators/use-interceptors.decorator")); +__export(require("./decorators/http-code.decorator")); +__export(require("./decorators/bind.decorator")); +__export(require("./forward-ref.util")); +__export(require("./decorators/create-route-param-metadata.decorator")); diff --git a/lib/common/utils/merge-with-values.util.d.ts b/lib/common/utils/merge-with-values.util.d.ts new file mode 100644 index 00000000000..49a2ea3e6e3 --- /dev/null +++ b/lib/common/utils/merge-with-values.util.d.ts @@ -0,0 +1,7 @@ +import 'reflect-metadata'; +export interface Constructor { + new (...args: any[]): T; +} +export declare const MergeWithValues: >(data: { + [param: string]: any; +}) => (Metatype: T) => any; diff --git a/lib/common/utils/merge-with-values.util.js b/lib/common/utils/merge-with-values.util.js new file mode 100644 index 00000000000..55f3132d505 --- /dev/null +++ b/lib/common/utils/merge-with-values.util.js @@ -0,0 +1,16 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +exports.MergeWithValues = (data) => { + return (Metatype) => { + const Type = class extends Metatype { + constructor(...args) { + super(...args); + } + }; + const token = Metatype.name + JSON.stringify(data); + Object.defineProperty(Type, 'name', { value: token }); + Object.assign(Type.prototype, data); + return Type; + }; +}; diff --git a/lib/common/utils/shared.utils.d.ts b/lib/common/utils/shared.utils.d.ts new file mode 100644 index 00000000000..54d38406298 --- /dev/null +++ b/lib/common/utils/shared.utils.d.ts @@ -0,0 +1,8 @@ +export declare const isUndefined: (obj: any) => obj is undefined; +export declare const isFunction: (fn: any) => boolean; +export declare const isObject: (fn: any) => fn is object; +export declare const isString: (fn: any) => fn is string; +export declare const isConstructor: (fn: any) => boolean; +export declare const validatePath: (path: any) => string; +export declare const isNil: (obj: any) => boolean; +export declare const isEmpty: (array: any) => boolean; diff --git a/lib/common/utils/shared.utils.js b/lib/common/utils/shared.utils.js new file mode 100644 index 00000000000..00fe51122ee --- /dev/null +++ b/lib/common/utils/shared.utils.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.isUndefined = (obj) => typeof obj === 'undefined'; +exports.isFunction = (fn) => typeof fn === 'function'; +exports.isObject = (fn) => typeof fn === 'object'; +exports.isString = (fn) => typeof fn === 'string'; +exports.isConstructor = (fn) => fn === 'constructor'; +exports.validatePath = (path) => (path.charAt(0) !== '/') ? '/' + path : path; +exports.isNil = (obj) => exports.isUndefined(obj) || obj === null; +exports.isEmpty = (array) => !(array && array.length > 0); diff --git a/lib/core/LICENSE b/lib/core/LICENSE new file mode 100644 index 00000000000..be7581ff84f --- /dev/null +++ b/lib/core/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2017 Kamil Myƛliwiec + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/core/Readme.md b/lib/core/Readme.md new file mode 100644 index 00000000000..280bd354356 --- /dev/null +++ b/lib/core/Readme.md @@ -0,0 +1,125 @@ +

    + Nest Logo +

    + +[travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master +[travis-url]: https://travis-ci.org/nestjs/nest +[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux +[linux-url]: https://travis-ci.org/nestjs/nest + +

    A progressive Node.js framework for building efficient and scalable web applications. :cat:

    +

    +NPM Version +Package License +NPM Downloads +Travis +Linux +Coverage +Gitter +Backers on Open Collective +Sponsors on Open Collective +

    + + +## Description + +

    Nest is a framework for building efficient, scalable Node.js web applications. It uses modern JavaScript, is built with TypeScript (preserves compatibility with pure JavaScript) and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reactive Programming).

    +

    Under the hood, Nest makes use of Express, allowing for easy use of the myriad third-party plugins which are available.

    + +## Philosophy + +

    In recent years, thanks to Node.js, JavaScript has become the “lingua franca” of the web for both front and backend applications, giving rise to awesome projects like Angular, React and Vue which improve developer productivity and enable the construction of fast, testable, extensible frontend applications. However, on the server-side, while there are a lot of superb libraries, helpers and tools for Node, none of them effectively solve the main problem - the architecture.

    +

    Nest aims to provide an application architecture out of the box which allows for effortless creation of highly testable, scalable, loosely coupled and easily maintainable applications.

    + +## Features + +
      +
    • Built with TypeScript (compatible with pure JavaScript + Babel)
    • +
    • Easy to learn - syntax similar to Angular
    • +
    • Familiar - based on well-known libraries (Express / socket.io)
    • +
    • Dependency Injection - built-in asynchronous IoC container with a hierarchical injector
    • +
    • WebSockets module (based on socket.io, but you can bring your own library, by making use of WsAdapter)
    • +
    • Modular - defines an easy to follow module definition pattern so you can split your system into reusable modules
    • +
    • Reactive microservice support with message patterns (built-in transport via TCP / Redis, but other communication schemes can be implemented with CustomTransportStrategy)
    • +
    • Exception layer - throwable web exceptions with status codes, exception filters
    • +
    • Pipes - synchronous & asynchronous (e.g. validation purposes)
    • +
    • Guards - attach additional logic in a declarative manner (e.g. role-based access control)
    • +
    • Interceptors - built on top of RxJS
    • +
    • Testing utilities (both e2e & unit tests)
    • +
    + +## Installation + +**Install the TypeScript Starter Project with Git:** +```bash +$ git clone https://github.com/nestjs/typescript-starter.git project +$ cd project +$ npm install +$ npm run start +``` + +**Install the JavaScript (Babel) Starter Project with Git:** +```bash +$ git clone https://github.com/nestjs/javascript-starter.git project +$ cd project +$ npm install +$ npm run start +``` + +**Start a New Project from Scratch with NPM:** +```bash +$ npm i --save @nestjs/core @nestjs/common @nestjs/microservices @nestjs/websockets @nestjs/testing reflect-metadata rxjs +``` + +## Documentation & Quick Start + +:books: [Documentation & Tutorial](https://docs.nestjs.com) + +## Sponsors + + + +## Backers + +I am on a mission to provide an architecture to create truly flexible, scalable and loosely coupled systems using the Node.js platform. It takes a lot of time, so if you want to support me, please [become a backer / sponsor]((https://opencollective.com/nest#backer)). I appreciate your help. Thanks! :heart_eyes: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## People + +- Author - [Kamil Myƛliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) + +## License + + [MIT](LICENSE) diff --git a/lib/core/adapters/express-adapter.d.ts b/lib/core/adapters/express-adapter.d.ts new file mode 100644 index 00000000000..72b914eba11 --- /dev/null +++ b/lib/core/adapters/express-adapter.d.ts @@ -0,0 +1,4 @@ +export declare class ExpressAdapter { + static create(): any; + static createRouter(): any; +} diff --git a/lib/core/adapters/express-adapter.js b/lib/core/adapters/express-adapter.js new file mode 100644 index 00000000000..60b329fc453 --- /dev/null +++ b/lib/core/adapters/express-adapter.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const express = require("express"); +class ExpressAdapter { + static create() { + return express(); + } + static createRouter() { + return express.Router({ mergeParams: true }); + } +} +exports.ExpressAdapter = ExpressAdapter; diff --git a/lib/core/application-config.d.ts b/lib/core/application-config.d.ts new file mode 100644 index 00000000000..0454f6337a1 --- /dev/null +++ b/lib/core/application-config.d.ts @@ -0,0 +1,23 @@ +import { PipeTransform, WebSocketAdapter, ExceptionFilter, NestInterceptor, CanActivate } from '@nestjs/common'; +import { ConfigurationProvider } from '@nestjs/common/interfaces/configuration-provider.interface'; +export declare class ApplicationConfig implements ConfigurationProvider { + private ioAdapter; + private globalPipes; + private globalFilters; + private globalInterceptors; + private globalGuards; + private globalPrefix; + constructor(ioAdapter?: WebSocketAdapter | null); + setGlobalPrefix(prefix: string): void; + getGlobalPrefix(): string; + setIoAdapter(ioAdapter: WebSocketAdapter): void; + getIoAdapter(): WebSocketAdapter; + useGlobalPipes(...pipes: PipeTransform[]): void; + getGlobalFilters(): ExceptionFilter[]; + useGlobalFilters(...filters: ExceptionFilter[]): void; + getGlobalPipes(): PipeTransform[]; + getGlobalInterceptors(): NestInterceptor[]; + useGlobalInterceptors(...interceptors: NestInterceptor[]): void; + getGlobalGuards(): CanActivate[]; + useGlobalGuards(...guards: CanActivate[]): void; +} diff --git a/lib/core/application-config.js b/lib/core/application-config.js new file mode 100644 index 00000000000..d8986d9d5cc --- /dev/null +++ b/lib/core/application-config.js @@ -0,0 +1,49 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class ApplicationConfig { + constructor(ioAdapter = null) { + this.ioAdapter = ioAdapter; + this.globalPipes = []; + this.globalFilters = []; + this.globalInterceptors = []; + this.globalGuards = []; + this.globalPrefix = ''; + } + setGlobalPrefix(prefix) { + this.globalPrefix = prefix; + } + getGlobalPrefix() { + return this.globalPrefix; + } + setIoAdapter(ioAdapter) { + this.ioAdapter = ioAdapter; + } + getIoAdapter() { + return this.ioAdapter; + } + useGlobalPipes(...pipes) { + this.globalPipes = pipes; + } + getGlobalFilters() { + return this.globalFilters; + } + useGlobalFilters(...filters) { + this.globalFilters = filters; + } + getGlobalPipes() { + return this.globalPipes; + } + getGlobalInterceptors() { + return this.globalInterceptors; + } + useGlobalInterceptors(...interceptors) { + this.globalInterceptors = interceptors; + } + getGlobalGuards() { + return this.globalGuards; + } + useGlobalGuards(...guards) { + this.globalGuards = guards; + } +} +exports.ApplicationConfig = ApplicationConfig; diff --git a/lib/core/constants.d.ts b/lib/core/constants.d.ts new file mode 100644 index 00000000000..56bf39c8193 --- /dev/null +++ b/lib/core/constants.d.ts @@ -0,0 +1,6 @@ +export declare const messages: { + APPLICATION_START: string; + APPLICATION_READY: string; + MICROSERVICE_READY: string; + UNKNOWN_EXCEPTION_MESSAGE: string; +}; diff --git a/lib/core/constants.js b/lib/core/constants.js new file mode 100644 index 00000000000..a2954c21847 --- /dev/null +++ b/lib/core/constants.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.messages = { + APPLICATION_START: `Starting Nest application...`, + APPLICATION_READY: `Nest application successfully started`, + MICROSERVICE_READY: `Nest microservice successfully started`, + UNKNOWN_EXCEPTION_MESSAGE: 'Internal server error', +}; diff --git a/lib/core/errors/exception-handler.d.ts b/lib/core/errors/exception-handler.d.ts new file mode 100644 index 00000000000..25d8ab523a8 --- /dev/null +++ b/lib/core/errors/exception-handler.d.ts @@ -0,0 +1,5 @@ +import { RuntimeException } from './exceptions/runtime.exception'; +export declare class ExceptionHandler { + private static readonly logger; + handle(exception: RuntimeException | Error): void; +} diff --git a/lib/core/errors/exception-handler.js b/lib/core/errors/exception-handler.js new file mode 100644 index 00000000000..2ba6f363bd0 --- /dev/null +++ b/lib/core/errors/exception-handler.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("./exceptions/runtime.exception"); +const logger_service_1 = require("@nestjs/common/services/logger.service"); +class ExceptionHandler { + handle(exception) { + if (!(exception instanceof runtime_exception_1.RuntimeException)) { + ExceptionHandler.logger.error(exception.message, exception.stack); + return; + } + ExceptionHandler.logger.error(exception.what(), exception.stack); + } +} +ExceptionHandler.logger = new logger_service_1.Logger(ExceptionHandler.name); +exports.ExceptionHandler = ExceptionHandler; diff --git a/lib/core/errors/exceptions-zone.d.ts b/lib/core/errors/exceptions-zone.d.ts new file mode 100644 index 00000000000..06d4efeccee --- /dev/null +++ b/lib/core/errors/exceptions-zone.d.ts @@ -0,0 +1,5 @@ +export declare class ExceptionsZone { + private static readonly exceptionHandler; + static run(fn: () => void): void; + static asyncRun(fn: () => Promise): Promise; +} diff --git a/lib/core/errors/exceptions-zone.js b/lib/core/errors/exceptions-zone.js new file mode 100644 index 00000000000..6efb525786a --- /dev/null +++ b/lib/core/errors/exceptions-zone.js @@ -0,0 +1,36 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const exception_handler_1 = require("./exception-handler"); +const messages_1 = require("./messages"); +class ExceptionsZone { + static run(fn) { + try { + fn(); + } + catch (e) { + this.exceptionHandler.handle(e); + throw messages_1.UNHANDLED_RUNTIME_EXCEPTION; + } + } + static asyncRun(fn) { + return __awaiter(this, void 0, void 0, function* () { + try { + yield fn(); + } + catch (e) { + this.exceptionHandler.handle(e); + throw messages_1.UNHANDLED_RUNTIME_EXCEPTION; + } + }); + } +} +ExceptionsZone.exceptionHandler = new exception_handler_1.ExceptionHandler(); +exports.ExceptionsZone = ExceptionsZone; diff --git a/lib/core/errors/exceptions/invalid-exception-filter.exception.d.ts b/lib/core/errors/exceptions/invalid-exception-filter.exception.d.ts new file mode 100644 index 00000000000..a2ed936da89 --- /dev/null +++ b/lib/core/errors/exceptions/invalid-exception-filter.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from './runtime.exception'; +export declare class InvalidExceptionFilterException extends RuntimeException { + constructor(); +} diff --git a/lib/core/errors/exceptions/invalid-exception-filter.exception.js b/lib/core/errors/exceptions/invalid-exception-filter.exception.js new file mode 100644 index 00000000000..28c87bd78b9 --- /dev/null +++ b/lib/core/errors/exceptions/invalid-exception-filter.exception.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("./runtime.exception"); +const messages_1 = require("../messages"); +class InvalidExceptionFilterException extends runtime_exception_1.RuntimeException { + constructor() { + super(messages_1.INVALID_EXCEPTION_FILTER); + } +} +exports.InvalidExceptionFilterException = InvalidExceptionFilterException; diff --git a/lib/core/errors/exceptions/invalid-middleware-configuration.exception.d.ts b/lib/core/errors/exceptions/invalid-middleware-configuration.exception.d.ts new file mode 100644 index 00000000000..a4bbaaa03ea --- /dev/null +++ b/lib/core/errors/exceptions/invalid-middleware-configuration.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from './runtime.exception'; +export declare class InvalidMiddlewareConfigurationException extends RuntimeException { + constructor(); +} diff --git a/lib/core/errors/exceptions/invalid-middleware-configuration.exception.js b/lib/core/errors/exceptions/invalid-middleware-configuration.exception.js new file mode 100644 index 00000000000..107eb3c0062 --- /dev/null +++ b/lib/core/errors/exceptions/invalid-middleware-configuration.exception.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("./runtime.exception"); +const messages_1 = require("../messages"); +class InvalidMiddlewareConfigurationException extends runtime_exception_1.RuntimeException { + constructor() { + super(messages_1.INVALID_MIDDLEWARE_CONFIGURATION); + } +} +exports.InvalidMiddlewareConfigurationException = InvalidMiddlewareConfigurationException; diff --git a/lib/core/errors/exceptions/invalid-middleware.exception.d.ts b/lib/core/errors/exceptions/invalid-middleware.exception.d.ts new file mode 100644 index 00000000000..acb777c38ac --- /dev/null +++ b/lib/core/errors/exceptions/invalid-middleware.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from './runtime.exception'; +export declare class InvalidMiddlewareException extends RuntimeException { + constructor(name: string); +} diff --git a/lib/core/errors/exceptions/invalid-middleware.exception.js b/lib/core/errors/exceptions/invalid-middleware.exception.js new file mode 100644 index 00000000000..dacc3558564 --- /dev/null +++ b/lib/core/errors/exceptions/invalid-middleware.exception.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("./runtime.exception"); +const messages_1 = require("../messages"); +class InvalidMiddlewareException extends runtime_exception_1.RuntimeException { + constructor(name) { + super(messages_1.InvalidMiddlewareMessage(name)); + } +} +exports.InvalidMiddlewareException = InvalidMiddlewareException; diff --git a/lib/core/errors/exceptions/invalid-module.exception.d.ts b/lib/core/errors/exceptions/invalid-module.exception.d.ts new file mode 100644 index 00000000000..3cd8c0093f8 --- /dev/null +++ b/lib/core/errors/exceptions/invalid-module.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from './runtime.exception'; +export declare class InvalidModuleException extends RuntimeException { + constructor(trace: any[]); +} diff --git a/lib/core/errors/exceptions/invalid-module.exception.js b/lib/core/errors/exceptions/invalid-module.exception.js new file mode 100644 index 00000000000..8f0ecca1cfd --- /dev/null +++ b/lib/core/errors/exceptions/invalid-module.exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("./runtime.exception"); +const messages_1 = require("../messages"); +class InvalidModuleException extends runtime_exception_1.RuntimeException { + constructor(trace) { + const scope = (trace || []).map((module) => module.name).join(' -> '); + super(messages_1.InvalidModuleMessage(scope)); + } +} +exports.InvalidModuleException = InvalidModuleException; diff --git a/lib/core/errors/exceptions/microservices-package-not-found.exception.d.ts b/lib/core/errors/exceptions/microservices-package-not-found.exception.d.ts new file mode 100644 index 00000000000..97c847a0c18 --- /dev/null +++ b/lib/core/errors/exceptions/microservices-package-not-found.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from './runtime.exception'; +export declare class MicroservicesPackageNotFoundException extends RuntimeException { + constructor(); +} diff --git a/lib/core/errors/exceptions/microservices-package-not-found.exception.js b/lib/core/errors/exceptions/microservices-package-not-found.exception.js new file mode 100644 index 00000000000..188f9b32679 --- /dev/null +++ b/lib/core/errors/exceptions/microservices-package-not-found.exception.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("./runtime.exception"); +const messages_1 = require("../messages"); +class MicroservicesPackageNotFoundException extends runtime_exception_1.RuntimeException { + constructor() { + super(messages_1.MICROSERVICES_PACKAGE_NOT_FOUND_EXCEPTION); + } +} +exports.MicroservicesPackageNotFoundException = MicroservicesPackageNotFoundException; diff --git a/lib/core/errors/exceptions/runtime.exception.d.ts b/lib/core/errors/exceptions/runtime.exception.d.ts new file mode 100644 index 00000000000..2e5b6489f54 --- /dev/null +++ b/lib/core/errors/exceptions/runtime.exception.d.ts @@ -0,0 +1,11 @@ +export declare class Error { + name: string; + message: string; + stack: string; + constructor(message?: string); +} +export declare class RuntimeException extends Error { + private msg; + constructor(msg?: string); + what(): string; +} diff --git a/lib/core/errors/exceptions/runtime.exception.js b/lib/core/errors/exceptions/runtime.exception.js new file mode 100644 index 00000000000..95b4d1658fb --- /dev/null +++ b/lib/core/errors/exceptions/runtime.exception.js @@ -0,0 +1,12 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class RuntimeException extends Error { + constructor(msg = ``) { + super(msg); + this.msg = msg; + } + what() { + return this.msg; + } +} +exports.RuntimeException = RuntimeException; diff --git a/lib/core/errors/exceptions/undefined-dependency.exception.d.ts b/lib/core/errors/exceptions/undefined-dependency.exception.d.ts new file mode 100644 index 00000000000..70e2ef7641e --- /dev/null +++ b/lib/core/errors/exceptions/undefined-dependency.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from './runtime.exception'; +export declare class UndefinedDependencyException extends RuntimeException { + constructor(type: string, index: number, length: number); +} diff --git a/lib/core/errors/exceptions/undefined-dependency.exception.js b/lib/core/errors/exceptions/undefined-dependency.exception.js new file mode 100644 index 00000000000..35f9c7bb55d --- /dev/null +++ b/lib/core/errors/exceptions/undefined-dependency.exception.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("./runtime.exception"); +const messages_1 = require("../messages"); +class UndefinedDependencyException extends runtime_exception_1.RuntimeException { + constructor(type, index, length) { + super(messages_1.UnknownDependenciesMessage(type, index, length)); + } +} +exports.UndefinedDependencyException = UndefinedDependencyException; diff --git a/lib/core/errors/exceptions/unknown-dependencies.exception.d.ts b/lib/core/errors/exceptions/unknown-dependencies.exception.d.ts new file mode 100644 index 00000000000..f1627c9ba3c --- /dev/null +++ b/lib/core/errors/exceptions/unknown-dependencies.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from './runtime.exception'; +export declare class UnknownDependenciesException extends RuntimeException { + constructor(type: string, index: number, length: number); +} diff --git a/lib/core/errors/exceptions/unknown-dependencies.exception.js b/lib/core/errors/exceptions/unknown-dependencies.exception.js new file mode 100644 index 00000000000..f41e227144f --- /dev/null +++ b/lib/core/errors/exceptions/unknown-dependencies.exception.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("./runtime.exception"); +const messages_1 = require("../messages"); +class UnknownDependenciesException extends runtime_exception_1.RuntimeException { + constructor(type, index, length) { + super(messages_1.UnknownDependenciesMessage(type, index, length)); + } +} +exports.UnknownDependenciesException = UnknownDependenciesException; diff --git a/lib/core/errors/exceptions/unknown-export.exception.d.ts b/lib/core/errors/exceptions/unknown-export.exception.d.ts new file mode 100644 index 00000000000..5246b262f5d --- /dev/null +++ b/lib/core/errors/exceptions/unknown-export.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from './runtime.exception'; +export declare class UnknownExportException extends RuntimeException { + constructor(name: string); +} diff --git a/lib/core/errors/exceptions/unknown-export.exception.js b/lib/core/errors/exceptions/unknown-export.exception.js new file mode 100644 index 00000000000..033f9dbd026 --- /dev/null +++ b/lib/core/errors/exceptions/unknown-export.exception.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("./runtime.exception"); +const messages_1 = require("../messages"); +class UnknownExportException extends runtime_exception_1.RuntimeException { + constructor(name) { + super(messages_1.UnknownExportMessage(name)); + } +} +exports.UnknownExportException = UnknownExportException; diff --git a/lib/core/errors/exceptions/unknown-module.exception.d.ts b/lib/core/errors/exceptions/unknown-module.exception.d.ts new file mode 100644 index 00000000000..effb1a0e67f --- /dev/null +++ b/lib/core/errors/exceptions/unknown-module.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from './runtime.exception'; +export declare class UnknownModuleException extends RuntimeException { + constructor(); +} diff --git a/lib/core/errors/exceptions/unknown-module.exception.js b/lib/core/errors/exceptions/unknown-module.exception.js new file mode 100644 index 00000000000..84e1209e858 --- /dev/null +++ b/lib/core/errors/exceptions/unknown-module.exception.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("./runtime.exception"); +class UnknownModuleException extends runtime_exception_1.RuntimeException { + constructor() { + super(); + } +} +exports.UnknownModuleException = UnknownModuleException; diff --git a/lib/core/errors/exceptions/unknown-request-mapping.exception.d.ts b/lib/core/errors/exceptions/unknown-request-mapping.exception.d.ts new file mode 100644 index 00000000000..283340c2bde --- /dev/null +++ b/lib/core/errors/exceptions/unknown-request-mapping.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from './runtime.exception'; +export declare class UnknownRequestMappingException extends RuntimeException { + constructor(); +} diff --git a/lib/core/errors/exceptions/unknown-request-mapping.exception.js b/lib/core/errors/exceptions/unknown-request-mapping.exception.js new file mode 100644 index 00000000000..f03fa61a8f0 --- /dev/null +++ b/lib/core/errors/exceptions/unknown-request-mapping.exception.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("./runtime.exception"); +const messages_1 = require("../messages"); +class UnknownRequestMappingException extends runtime_exception_1.RuntimeException { + constructor() { + super(messages_1.UNKNOWN_REQUEST_MAPPING); + } +} +exports.UnknownRequestMappingException = UnknownRequestMappingException; diff --git a/lib/core/errors/messages.d.ts b/lib/core/errors/messages.d.ts new file mode 100644 index 00000000000..ea0d35215d2 --- /dev/null +++ b/lib/core/errors/messages.d.ts @@ -0,0 +1,9 @@ +export declare const UnknownDependenciesMessage: (type: string, index: number, length: number) => string; +export declare const InvalidMiddlewareMessage: (name: string) => string; +export declare const InvalidModuleMessage: (scope: string) => string; +export declare const UnknownExportMessage: (name: string) => string; +export declare const INVALID_MIDDLEWARE_CONFIGURATION: string; +export declare const UNKNOWN_REQUEST_MAPPING: string; +export declare const UNHANDLED_RUNTIME_EXCEPTION: string; +export declare const INVALID_EXCEPTION_FILTER: string; +export declare const MICROSERVICES_PACKAGE_NOT_FOUND_EXCEPTION: string; diff --git a/lib/core/errors/messages.js b/lib/core/errors/messages.js new file mode 100644 index 00000000000..cb34c9fce8b --- /dev/null +++ b/lib/core/errors/messages.js @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UnknownDependenciesMessage = (type, index, length) => { + let message = `Nest can't resolve dependencies of the ${type}`; + message += ` (`; + const args = new Array(length).fill('+'); + args[index] = '?'; + message += args.join(', '); + message += `). Please verify whether [${index}] argument is available in the current context.`; + return message; +}; +exports.InvalidMiddlewareMessage = (name) => `The middleware doesn't provide the 'resolve' method (${name})`; +exports.InvalidModuleMessage = (scope) => `Nest can't create the module instance. The frequent reason of this exception is the circular dependency between modules. Use forwardRef() to avoid it (read more https://docs.nestjs.com/advanced/circular-dependency). Scope [${scope}]`; +exports.UnknownExportMessage = (name) => `You are trying to export unknown component (${name}). Remember - your component should be listed both in exports and components arrays!`; +exports.INVALID_MIDDLEWARE_CONFIGURATION = `Invalid middleware configuration passed inside the module 'configure()' method.`; +exports.UNKNOWN_REQUEST_MAPPING = `Request mapping properties not defined in the @RequestMapping() annotation!`; +exports.UNHANDLED_RUNTIME_EXCEPTION = `Unhandled Runtime Exception.`; +exports.INVALID_EXCEPTION_FILTER = `Invalid exception filters (@UseFilters()).`; +exports.MICROSERVICES_PACKAGE_NOT_FOUND_EXCEPTION = `Unable to load @nestjs/microservices packages (please, make sure whether it's installed already).`; diff --git a/lib/core/exceptions/base-exception-filter-context.d.ts b/lib/core/exceptions/base-exception-filter-context.d.ts new file mode 100644 index 00000000000..9bf124e6835 --- /dev/null +++ b/lib/core/exceptions/base-exception-filter-context.d.ts @@ -0,0 +1,8 @@ +import 'reflect-metadata'; +import { Metatype } from '@nestjs/common/interfaces/index'; +import { ExceptionFilter } from '@nestjs/common/interfaces/exceptions/exception-filter.interface'; +import { ContextCreator } from './../helpers/context-creator'; +export declare class BaseExceptionFilterContext extends ContextCreator { + createConcreteContext(metadata: T): R; + reflectCatchExceptions(instance: ExceptionFilter): Metatype[]; +} diff --git a/lib/core/exceptions/base-exception-filter-context.js b/lib/core/exceptions/base-exception-filter-context.js new file mode 100644 index 00000000000..17b057afdb1 --- /dev/null +++ b/lib/core/exceptions/base-exception-filter-context.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const iterare_1 = require("iterare"); +const constants_1 = require("@nestjs/common/constants"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const context_creator_1 = require("./../helpers/context-creator"); +class BaseExceptionFilterContext extends context_creator_1.ContextCreator { + createConcreteContext(metadata) { + if (shared_utils_1.isUndefined(metadata) || shared_utils_1.isEmpty(metadata)) { + return []; + } + return iterare_1.default(metadata) + .filter((instance) => instance.catch && shared_utils_1.isFunction(instance.catch)) + .map((instance) => ({ + func: instance.catch.bind(instance), + exceptionMetatypes: this.reflectCatchExceptions(instance), + })) + .toArray(); + } + reflectCatchExceptions(instance) { + const prototype = Object.getPrototypeOf(instance); + return Reflect.getMetadata(constants_1.FILTER_CATCH_EXCEPTIONS, prototype.constructor) || []; + } +} +exports.BaseExceptionFilterContext = BaseExceptionFilterContext; diff --git a/lib/core/exceptions/exceptions-handler.d.ts b/lib/core/exceptions/exceptions-handler.d.ts new file mode 100644 index 00000000000..477dbe85fbb --- /dev/null +++ b/lib/core/exceptions/exceptions-handler.d.ts @@ -0,0 +1,9 @@ +import { ExceptionFilterMetadata } from '@nestjs/common/interfaces/exceptions/exception-filter-metadata.interface'; +import { HttpException } from '@nestjs/common'; +export declare class ExceptionsHandler { + private static readonly logger; + private filters; + next(exception: Error | HttpException | any, response: any): void; + setCustomFilters(filters: ExceptionFilterMetadata[]): void; + invokeCustomFilters(exception: any, response: any): boolean; +} diff --git a/lib/core/exceptions/exceptions-handler.js b/lib/core/exceptions/exceptions-handler.js new file mode 100644 index 00000000000..4b3a935a5d6 --- /dev/null +++ b/lib/core/exceptions/exceptions-handler.js @@ -0,0 +1,51 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http_exception_1 = require("./http-exception"); +const constants_1 = require("../constants"); +const common_1 = require("@nestjs/common"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const invalid_exception_filter_exception_1 = require("../errors/exceptions/invalid-exception-filter.exception"); +const common_2 = require("@nestjs/common"); +class ExceptionsHandler { + constructor() { + this.filters = []; + } + next(exception, response) { + if (this.invokeCustomFilters(exception, response)) + return; + if (!(exception instanceof common_2.HttpException || exception instanceof http_exception_1.HttpException)) { + response.status(500).json({ + statusCode: 500, + message: constants_1.messages.UNKNOWN_EXCEPTION_MESSAGE, + }); + if (shared_utils_1.isObject(exception) && exception.message) { + return ExceptionsHandler.logger.error(exception.message, exception.stack); + } + return ExceptionsHandler.logger.error(exception); + } + const res = exception.getResponse(); + const message = shared_utils_1.isObject(res) ? res : ({ + statusCode: exception.getStatus(), + message: res, + }); + response.status(exception.getStatus()).json(message); + } + setCustomFilters(filters) { + if (!Array.isArray(filters)) { + throw new invalid_exception_filter_exception_1.InvalidExceptionFilterException(); + } + this.filters = filters; + } + invokeCustomFilters(exception, response) { + if (shared_utils_1.isEmpty(this.filters)) + return false; + const filter = this.filters.find(({ exceptionMetatypes, func }) => { + const hasMetatype = !!exceptionMetatypes.find(ExceptionMetatype => exception instanceof ExceptionMetatype); + return hasMetatype; + }); + filter && filter.func(exception, response); + return !!filter; + } +} +ExceptionsHandler.logger = new common_1.Logger(ExceptionsHandler.name); +exports.ExceptionsHandler = ExceptionsHandler; diff --git a/lib/core/exceptions/http-exception.d.ts b/lib/core/exceptions/http-exception.d.ts new file mode 100644 index 00000000000..99c459e6476 --- /dev/null +++ b/lib/core/exceptions/http-exception.d.ts @@ -0,0 +1,23 @@ +export declare class HttpException { + private readonly response; + private readonly status; + private readonly logger; + /** + * The base Nest Application exception, which is handled by the default Exceptions Handler. + * If you throw an exception from your HTTP route handlers, Nest will map them to the appropriate HTTP response and send to the client. + * + * When `response` is an object: + * - object will be stringified and returned to the user as a JSON response, + * + * When `response` is a string: + * - Nest will create a response with two properties: + * ``` + * message: response, + * statusCode: X + * ``` + * @deprecated + */ + constructor(response: string | object, status: number); + getResponse(): string | object; + getStatus(): number; +} diff --git a/lib/core/exceptions/http-exception.js b/lib/core/exceptions/http-exception.js new file mode 100644 index 00000000000..2b4126f8417 --- /dev/null +++ b/lib/core/exceptions/http-exception.js @@ -0,0 +1,33 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const common_1 = require("@nestjs/common"); +class HttpException { + /** + * The base Nest Application exception, which is handled by the default Exceptions Handler. + * If you throw an exception from your HTTP route handlers, Nest will map them to the appropriate HTTP response and send to the client. + * + * When `response` is an object: + * - object will be stringified and returned to the user as a JSON response, + * + * When `response` is a string: + * - Nest will create a response with two properties: + * ``` + * message: response, + * statusCode: X + * ``` + * @deprecated + */ + constructor(response, status) { + this.response = response; + this.status = status; + this.logger = new common_1.Logger(HttpException.name); + this.logger.warn('DEPRECATED! Since version [4.3.2] HttpException class was moved to the @nestjs/common package!'); + } + getResponse() { + return this.response; + } + getStatus() { + return this.status; + } +} +exports.HttpException = HttpException; diff --git a/lib/core/guards/constants.d.ts b/lib/core/guards/constants.d.ts new file mode 100644 index 00000000000..f4c98c0f485 --- /dev/null +++ b/lib/core/guards/constants.d.ts @@ -0,0 +1 @@ +export declare const FORBIDDEN_MESSAGE = "Forbidden resource"; diff --git a/lib/core/guards/constants.js b/lib/core/guards/constants.js new file mode 100644 index 00000000000..3f2a9b02dba --- /dev/null +++ b/lib/core/guards/constants.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FORBIDDEN_MESSAGE = 'Forbidden resource'; diff --git a/lib/core/guards/guards-consumer.d.ts b/lib/core/guards/guards-consumer.d.ts new file mode 100644 index 00000000000..a165b68b249 --- /dev/null +++ b/lib/core/guards/guards-consumer.d.ts @@ -0,0 +1,9 @@ +import { Controller } from '@nestjs/common/interfaces'; +import { CanActivate, ExecutionContext } from '@nestjs/common'; +import { Observable } from 'rxjs/Observable'; +import 'rxjs/add/operator/toPromise'; +export declare class GuardsConsumer { + tryActivate(guards: CanActivate[], data: any, instance: Controller, callback: (...args) => any): Promise; + createContext(instance: Controller, callback: (...args) => any): ExecutionContext; + pickResult(result: boolean | Promise | Observable): Promise; +} diff --git a/lib/core/guards/guards-consumer.js b/lib/core/guards/guards-consumer.js new file mode 100644 index 00000000000..d38d19cff7a --- /dev/null +++ b/lib/core/guards/guards-consumer.js @@ -0,0 +1,49 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const Observable_1 = require("rxjs/Observable"); +require("rxjs/add/operator/toPromise"); +class GuardsConsumer { + tryActivate(guards, data, instance, callback) { + return __awaiter(this, void 0, void 0, function* () { + if (!guards || shared_utils_1.isEmpty(guards)) { + return true; + } + const context = this.createContext(instance, callback); + for (const guard of guards) { + const result = guard.canActivate(data, context); + if (yield this.pickResult(result)) { + continue; + } + return false; + } + return true; + }); + } + createContext(instance, callback) { + return { + parent: instance.constructor, + handler: callback, + }; + } + pickResult(result) { + return __awaiter(this, void 0, void 0, function* () { + if (result instanceof Observable_1.Observable) { + return yield result.toPromise(); + } + if (result instanceof Promise) { + return yield result; + } + return result; + }); + } +} +exports.GuardsConsumer = GuardsConsumer; diff --git a/lib/core/guards/guards-context-creator.d.ts b/lib/core/guards/guards-context-creator.d.ts new file mode 100644 index 00000000000..c8e643e8ccb --- /dev/null +++ b/lib/core/guards/guards-context-creator.d.ts @@ -0,0 +1,19 @@ +import 'reflect-metadata'; +import { Controller } from '@nestjs/common/interfaces'; +import { ContextCreator } from './../helpers/context-creator'; +import { NestContainer } from '../injector/container'; +import { CanActivate } from '@nestjs/common'; +import { ConfigurationProvider } from '@nestjs/common/interfaces/configuration-provider.interface'; +export declare class GuardsContextCreator extends ContextCreator { + private readonly container; + private readonly config; + private moduleContext; + constructor(container: NestContainer, config?: ConfigurationProvider); + create(instance: Controller, callback: (...args) => any, module: string): CanActivate[]; + createConcreteContext(metadata: T): R; + createGlobalMetadataContext(metadata: T): R; + getInstanceByMetatype(metatype: any): { + instance: any; + } | undefined; + getGlobalMetadata(): T; +} diff --git a/lib/core/guards/guards-context-creator.js b/lib/core/guards/guards-context-creator.js new file mode 100644 index 00000000000..19bd5a3f63c --- /dev/null +++ b/lib/core/guards/guards-context-creator.js @@ -0,0 +1,52 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const iterare_1 = require("iterare"); +const constants_1 = require("@nestjs/common/constants"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const context_creator_1 = require("./../helpers/context-creator"); +class GuardsContextCreator extends context_creator_1.ContextCreator { + constructor(container, config) { + super(); + this.container = container; + this.config = config; + } + create(instance, callback, module) { + this.moduleContext = module; + return this.createContext(instance, callback, constants_1.GUARDS_METADATA); + } + createConcreteContext(metadata) { + if (shared_utils_1.isUndefined(metadata) || shared_utils_1.isEmpty(metadata) || !this.moduleContext) { + return []; + } + const isGlobalMetadata = metadata === this.getGlobalMetadata(); + return isGlobalMetadata ? + this.createGlobalMetadataContext(metadata) : + iterare_1.default(metadata).filter((metatype) => metatype && metatype.name) + .map((metatype) => this.getInstanceByMetatype(metatype)) + .filter((wrapper) => wrapper && wrapper.instance) + .map((wrapper) => wrapper.instance) + .filter((guard) => guard && shared_utils_1.isFunction(guard.canActivate)) + .toArray(); + } + createGlobalMetadataContext(metadata) { + return iterare_1.default(metadata) + .filter((guard) => guard && guard.canActivate && shared_utils_1.isFunction(guard.canActivate)) + .toArray(); + } + getInstanceByMetatype(metatype) { + const collection = this.container.getModules(); + const module = collection.get(this.moduleContext); + if (!module) { + return undefined; + } + return module.injectables.get(metatype.name); + } + getGlobalMetadata() { + if (!this.config) { + return []; + } + return this.config.getGlobalGuards(); + } +} +exports.GuardsContextCreator = GuardsContextCreator; diff --git a/lib/core/helpers/context-creator.d.ts b/lib/core/helpers/context-creator.d.ts new file mode 100644 index 00000000000..118262b9a0c --- /dev/null +++ b/lib/core/helpers/context-creator.d.ts @@ -0,0 +1,9 @@ +import 'reflect-metadata'; +import { Controller } from '@nestjs/common/interfaces'; +export declare abstract class ContextCreator { + abstract createConcreteContext(metadata: T): R; + getGlobalMetadata?(): T; + createContext(instance: Controller, callback: (...args) => any, metadataKey: string): R; + reflectClassMetadata(instance: Controller, metadataKey: string): T; + reflectMethodMetadata(callback: (...args) => any, metadataKey: string): T; +} diff --git a/lib/core/helpers/context-creator.js b/lib/core/helpers/context-creator.js new file mode 100644 index 00000000000..cde0ff7d159 --- /dev/null +++ b/lib/core/helpers/context-creator.js @@ -0,0 +1,23 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +class ContextCreator { + createContext(instance, callback, metadataKey) { + const globalMetadata = this.getGlobalMetadata && this.getGlobalMetadata(); + const classMetadata = this.reflectClassMetadata(instance, metadataKey); + const methodMetadata = this.reflectMethodMetadata(callback, metadataKey); + return [ + ...this.createConcreteContext(globalMetadata || []), + ...this.createConcreteContext(classMetadata), + ...this.createConcreteContext(methodMetadata), + ]; + } + reflectClassMetadata(instance, metadataKey) { + const prototype = Object.getPrototypeOf(instance); + return Reflect.getMetadata(metadataKey, prototype.constructor); + } + reflectMethodMetadata(callback, metadataKey) { + return Reflect.getMetadata(metadataKey, callback); + } +} +exports.ContextCreator = ContextCreator; diff --git a/lib/core/helpers/messages.d.ts b/lib/core/helpers/messages.d.ts new file mode 100644 index 00000000000..4f0f5732314 --- /dev/null +++ b/lib/core/helpers/messages.d.ts @@ -0,0 +1,3 @@ +export declare const ModuleInitMessage: (module: string) => string; +export declare const RouteMappedMessage: (path: string, method: any) => string; +export declare const ControllerMappingMessage: (name: string, path: string) => string; diff --git a/lib/core/helpers/messages.js b/lib/core/helpers/messages.js new file mode 100644 index 00000000000..e2e005d72f5 --- /dev/null +++ b/lib/core/helpers/messages.js @@ -0,0 +1,6 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const request_method_enum_1 = require("@nestjs/common/enums/request-method.enum"); +exports.ModuleInitMessage = (module) => `${module} dependencies initialized`; +exports.RouteMappedMessage = (path, method) => `Mapped {${path}, ${request_method_enum_1.RequestMethod[method]}} route`; +exports.ControllerMappingMessage = (name, path) => `${name} {${path}}:`; diff --git a/lib/core/helpers/router-method-factory.d.ts b/lib/core/helpers/router-method-factory.d.ts new file mode 100644 index 00000000000..f0f487eb0ee --- /dev/null +++ b/lib/core/helpers/router-method-factory.d.ts @@ -0,0 +1,4 @@ +import { RequestMethod } from '@nestjs/common/enums/request-method.enum'; +export declare class RouterMethodFactory { + get(target: any, requestMethod: RequestMethod): any; +} diff --git a/lib/core/helpers/router-method-factory.js b/lib/core/helpers/router-method-factory.js new file mode 100644 index 00000000000..d4e7b9d6917 --- /dev/null +++ b/lib/core/helpers/router-method-factory.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const request_method_enum_1 = require("@nestjs/common/enums/request-method.enum"); +class RouterMethodFactory { + get(target, requestMethod) { + switch (requestMethod) { + case request_method_enum_1.RequestMethod.POST: return target.post; + case request_method_enum_1.RequestMethod.ALL: return target.all; + case request_method_enum_1.RequestMethod.DELETE: return target.delete; + case request_method_enum_1.RequestMethod.PUT: return target.put; + case request_method_enum_1.RequestMethod.PATCH: return target.patch; + case request_method_enum_1.RequestMethod.OPTIONS: return target.options; + case request_method_enum_1.RequestMethod.HEAD: return target.head; + default: { + return target.get; + } + } + } +} +exports.RouterMethodFactory = RouterMethodFactory; diff --git a/lib/core/index.d.ts b/lib/core/index.d.ts new file mode 100644 index 00000000000..2e02a389224 --- /dev/null +++ b/lib/core/index.d.ts @@ -0,0 +1,7 @@ +export { HttpException } from './exceptions/http-exception'; +export { MiddlewareBuilder } from './middlewares/builder'; +export { ModuleRef } from './injector/module-ref'; +export * from './services/reflector.service'; +export * from './nest-factory'; +export * from './nest-application'; +export * from './nest-application-context'; diff --git a/lib/core/index.js b/lib/core/index.js new file mode 100644 index 00000000000..22b1e6c7ecb --- /dev/null +++ b/lib/core/index.js @@ -0,0 +1,21 @@ +"use strict"; +/* + * Nest @core + * Copyright(c) 2017-... Kamil Mysliwiec + * www.nestjs.com || www.kamilmysliwiec.com + * MIT Licensed + */ +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +var http_exception_1 = require("./exceptions/http-exception"); +exports.HttpException = http_exception_1.HttpException; +var builder_1 = require("./middlewares/builder"); +exports.MiddlewareBuilder = builder_1.MiddlewareBuilder; +var module_ref_1 = require("./injector/module-ref"); +exports.ModuleRef = module_ref_1.ModuleRef; +__export(require("./services/reflector.service")); +__export(require("./nest-factory")); +__export(require("./nest-application")); +__export(require("./nest-application-context")); diff --git a/lib/core/injector/container.d.ts b/lib/core/injector/container.d.ts new file mode 100644 index 00000000000..f877622b555 --- /dev/null +++ b/lib/core/injector/container.d.ts @@ -0,0 +1,32 @@ +import 'reflect-metadata'; +import { Controller, Injectable } from '@nestjs/common/interfaces'; +import { NestModuleMetatype } from '@nestjs/common/interfaces/modules/module-metatype.interface'; +import { Metatype } from '@nestjs/common/interfaces/metatype.interface'; +import { Module } from './module'; +export declare class NestContainer { + private readonly modules; + private readonly moduleTokenFactory; + addModule(metatype: NestModuleMetatype, scope: NestModuleMetatype[]): void; + getModules(): Map; + addRelatedModule(relatedModule: NestModuleMetatype, token: string): void; + addComponent(component: Metatype, token: string): void; + addInjectable(injectable: Metatype, token: string): void; + addExportedComponent(exportedComponent: Metatype, token: string): void; + addController(controller: Metatype, token: string): void; + clear(): void; + replace(toReplace: any, options: any & { + scope: any[] | null; + }): void; +} +export interface InstanceWrapper { + name: any; + metatype: Metatype; + instance: T; + isResolved: boolean; + isPending?: boolean; + done$?: Promise; + inject?: Metatype[]; + isNotMetatype?: boolean; + forwardRef?: boolean; + async?: boolean; +} diff --git a/lib/core/injector/container.js b/lib/core/injector/container.js new file mode 100644 index 00000000000..e6168933bc2 --- /dev/null +++ b/lib/core/injector/container.js @@ -0,0 +1,72 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const module_1 = require("./module"); +const unknown_module_exception_1 = require("../errors/exceptions/unknown-module.exception"); +const module_token_factory_1 = require("./module-token-factory"); +const invalid_module_exception_1 = require("./../errors/exceptions/invalid-module.exception"); +class NestContainer { + constructor() { + this.modules = new Map(); + this.moduleTokenFactory = new module_token_factory_1.ModuleTokenFactory(); + } + addModule(metatype, scope) { + if (!metatype) { + throw new invalid_module_exception_1.InvalidModuleException(scope); + } + const token = this.moduleTokenFactory.create(metatype, scope); + if (this.modules.has(token)) { + return; + } + this.modules.set(token, new module_1.Module(metatype, scope)); + } + getModules() { + return this.modules; + } + addRelatedModule(relatedModule, token) { + if (!this.modules.has(token)) + return; + const module = this.modules.get(token); + const parent = module.metatype; + const relatedModuleToken = this.moduleTokenFactory.create(relatedModule, [].concat(module.scope, parent)); + const related = this.modules.get(relatedModuleToken); + module.addRelatedModule(related); + } + addComponent(component, token) { + if (!this.modules.has(token)) { + throw new unknown_module_exception_1.UnknownModuleException(); + } + const module = this.modules.get(token); + module.addComponent(component); + } + addInjectable(injectable, token) { + if (!this.modules.has(token)) { + throw new unknown_module_exception_1.UnknownModuleException(); + } + const module = this.modules.get(token); + module.addInjectable(injectable); + } + addExportedComponent(exportedComponent, token) { + if (!this.modules.has(token)) { + throw new unknown_module_exception_1.UnknownModuleException(); + } + const module = this.modules.get(token); + module.addExportedComponent(exportedComponent); + } + addController(controller, token) { + if (!this.modules.has(token)) { + throw new unknown_module_exception_1.UnknownModuleException(); + } + const module = this.modules.get(token); + module.addRoute(controller); + } + clear() { + this.modules.clear(); + } + replace(toReplace, options) { + [...this.modules.values()].forEach((module) => { + module.replace(toReplace, options); + }); + } +} +exports.NestContainer = NestContainer; diff --git a/lib/core/injector/injector.d.ts b/lib/core/injector/injector.d.ts new file mode 100644 index 00000000000..792feb155bc --- /dev/null +++ b/lib/core/injector/injector.d.ts @@ -0,0 +1,53 @@ +import 'reflect-metadata'; +import { InstanceWrapper } from './container'; +import { Module } from './module'; +import { Metatype } from '@nestjs/common/interfaces/metatype.interface'; +import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface'; +import { Injectable } from '@nestjs/common/interfaces/injectable.interface'; +import { MiddlewareWrapper } from '../middlewares/container'; +export declare class Injector { + loadInstanceOfMiddleware(wrapper: MiddlewareWrapper, collection: Map, module: Module): Promise; + loadInstanceOfRoute(wrapper: InstanceWrapper, module: Module): Promise; + loadInstanceOfInjectable(wrapper: InstanceWrapper, module: Module): Promise; + loadPrototypeOfInstance({metatype, name}: InstanceWrapper, collection: Map>): any; + loadInstanceOfComponent(wrapper: InstanceWrapper, module: Module, context?: Module[]): Promise; + applyDoneSubject(wrapper: InstanceWrapper): () => void; + loadInstance(wrapper: InstanceWrapper, collection: any, module: Module, context?: Module[]): Promise; + resolveConstructorParams(wrapper: InstanceWrapper, module: Module, inject: any[], context: Module[], callback: (args) => void): Promise; + reflectConstructorParams(type: Metatype): any[]; + reflectSelfParams(type: Metatype): any[]; + resolveSingleParam(wrapper: InstanceWrapper, param: Metatype | string | symbol | any, {index, length}: { + index: number; + length: number; + }, module: Module, context: Module[]): Promise; + resolveParamToken(wrapper: InstanceWrapper, param: Metatype | string | symbol | any): any; + resolveComponentInstance(module: Module, name: any, {index, length}: { + index: number; + length: number; + }, wrapper: InstanceWrapper, context: Module[]): Promise; + scanForComponent(components: Map, module: Module, {name, index, length}: { + name: any; + index: number; + length: number; + }, {metatype}: { + metatype: any; + }, context?: Module[]): any; + scanForComponentInExports(components: Map, {name, index, length}: { + name: any; + index: number; + length: number; + }, module: Module, metatype: any, context?: Module[]): Promise; + scanForComponentInScopes(context: Module[], {name, index, length}: { + name: any; + index: number; + length: number; + }, metatype: any): any; + scanForComponentInScope(context: Module, {name, index, length}: { + name: any; + index: number; + length: number; + }, metatype: any): any; + scanForComponentInRelatedModules(module: Module, name: any, context: Module[]): Promise; + resolveFactoryInstance(factoryResult: any): Promise; + flatMap(modules: Module[]): Module[]; +} diff --git a/lib/core/injector/injector.js b/lib/core/injector/injector.js new file mode 100644 index 00000000000..e48892a41b4 --- /dev/null +++ b/lib/core/injector/injector.js @@ -0,0 +1,228 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const unknown_dependencies_exception_1 = require("../errors/exceptions/unknown-dependencies.exception"); +const runtime_exception_1 = require("../errors/exceptions/runtime.exception"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const constants_1 = require("@nestjs/common/constants"); +const undefined_dependency_exception_1 = require("./../errors/exceptions/undefined-dependency.exception"); +class Injector { + loadInstanceOfMiddleware(wrapper, collection, module) { + return __awaiter(this, void 0, void 0, function* () { + const { metatype } = wrapper; + const currentMetatype = collection.get(metatype.name); + if (currentMetatype.instance !== null) + return; + yield this.resolveConstructorParams(wrapper, module, null, null, (instances) => { + collection.set(metatype.name, { + instance: new metatype(...instances), + metatype, + }); + }); + }); + } + loadInstanceOfRoute(wrapper, module) { + return __awaiter(this, void 0, void 0, function* () { + const routes = module.routes; + yield this.loadInstance(wrapper, routes, module); + }); + } + loadInstanceOfInjectable(wrapper, module) { + return __awaiter(this, void 0, void 0, function* () { + const injectables = module.injectables; + yield this.loadInstance(wrapper, injectables, module); + }); + } + loadPrototypeOfInstance({ metatype, name }, collection) { + if (!collection) + return null; + const target = collection.get(name); + if (target.isResolved || !shared_utils_1.isNil(target.inject)) + return null; + collection.set(name, Object.assign({}, collection.get(name), { instance: Object.create(metatype.prototype) })); + } + loadInstanceOfComponent(wrapper, module, context = []) { + return __awaiter(this, void 0, void 0, function* () { + const components = module.components; + yield this.loadInstance(wrapper, components, module, context); + }); + } + applyDoneSubject(wrapper) { + let done; + wrapper.done$ = new Promise((resolve, reject) => { done = resolve; }); + wrapper.isPending = true; + return done; + } + loadInstance(wrapper, collection, module, context = []) { + return __awaiter(this, void 0, void 0, function* () { + if (wrapper.isPending) { + return yield wrapper.done$; + } + const done = this.applyDoneSubject(wrapper); + const { metatype, name, inject } = wrapper; + const currentMetatype = collection.get(name); + if (shared_utils_1.isUndefined(currentMetatype)) { + throw new runtime_exception_1.RuntimeException(); + } + if (currentMetatype.isResolved) + return null; + yield this.resolveConstructorParams(wrapper, module, inject, context, (instances) => __awaiter(this, void 0, void 0, function* () { + if (shared_utils_1.isNil(inject)) { + currentMetatype.instance = Object.assign(currentMetatype.instance, new metatype(...instances)); + } + else { + const factoryResult = currentMetatype.metatype(...instances); + currentMetatype.instance = yield this.resolveFactoryInstance(factoryResult); + } + currentMetatype.isResolved = true; + done(); + })); + }); + } + resolveConstructorParams(wrapper, module, inject, context, callback) { + return __awaiter(this, void 0, void 0, function* () { + let isResolved = true; + const args = shared_utils_1.isNil(inject) ? this.reflectConstructorParams(wrapper.metatype) : inject; + const instances = yield Promise.all(args.map((param, index) => __awaiter(this, void 0, void 0, function* () { + const paramWrapper = yield this.resolveSingleParam(wrapper, param, { index, length: args.length }, module, context); + if (!paramWrapper.isResolved && !paramWrapper.forwardRef) { + isResolved = false; + } + return paramWrapper.instance; + }))); + isResolved && (yield callback(instances)); + }); + } + reflectConstructorParams(type) { + const paramtypes = Reflect.getMetadata(constants_1.PARAMTYPES_METADATA, type) || []; + const selfParams = this.reflectSelfParams(type); + selfParams.forEach(({ index, param }) => paramtypes[index] = param); + return paramtypes; + } + reflectSelfParams(type) { + return Reflect.getMetadata(constants_1.SELF_DECLARED_DEPS_METADATA, type) || []; + } + resolveSingleParam(wrapper, param, { index, length }, module, context) { + return __awaiter(this, void 0, void 0, function* () { + if (shared_utils_1.isUndefined(param)) { + throw new undefined_dependency_exception_1.UndefinedDependencyException(wrapper.name, index, length); + } + const token = this.resolveParamToken(wrapper, param); + return yield this.resolveComponentInstance(module, shared_utils_1.isFunction(token) ? token.name : token, { index, length }, wrapper, context); + }); + } + resolveParamToken(wrapper, param) { + if (!param.forwardRef) { + return param; + } + wrapper.forwardRef = true; + return param.forwardRef(); + } + resolveComponentInstance(module, name, { index, length }, wrapper, context) { + return __awaiter(this, void 0, void 0, function* () { + const components = module.components; + const instanceWrapper = yield this.scanForComponent(components, module, { name, index, length }, wrapper, context); + if (!instanceWrapper.isResolved && !instanceWrapper.forwardRef) { + yield this.loadInstanceOfComponent(instanceWrapper, module); + } + if (instanceWrapper.async) { + instanceWrapper.instance = yield instanceWrapper.instance; + } + return instanceWrapper; + }); + } + scanForComponent(components, module, { name, index, length }, { metatype }, context = []) { + return __awaiter(this, void 0, void 0, function* () { + const component = yield this.scanForComponentInScopes(context, { name, index, length }, metatype); + if (component) { + return component; + } + const scanInExports = () => this.scanForComponentInExports(components, { name, index, length }, module, metatype, context); + return components.has(name) ? components.get(name) : yield scanInExports(); + }); + } + scanForComponentInExports(components, { name, index, length }, module, metatype, context = []) { + return __awaiter(this, void 0, void 0, function* () { + const instanceWrapper = yield this.scanForComponentInRelatedModules(module, name, context); + if (shared_utils_1.isNil(instanceWrapper)) { + throw new unknown_dependencies_exception_1.UnknownDependenciesException(metatype.name, index, length); + } + return instanceWrapper; + }); + } + scanForComponentInScopes(context, { name, index, length }, metatype) { + return __awaiter(this, void 0, void 0, function* () { + context = context || []; + for (const ctx of context) { + const component = yield this.scanForComponentInScope(ctx, { name, index, length }, metatype); + if (component) + return component; + } + return null; + }); + } + scanForComponentInScope(context, { name, index, length }, metatype) { + return __awaiter(this, void 0, void 0, function* () { + try { + const component = yield this.scanForComponent(context.components, context, { name, index, length }, { metatype }, null); + if (!component.isResolved && !component.forwardRef) { + yield this.loadInstanceOfComponent(component, context); + } + return component; + } + catch (e) { + if (e instanceof undefined_dependency_exception_1.UndefinedDependencyException) { + throw e; + } + return null; + } + }); + } + scanForComponentInRelatedModules(module, name, context) { + return __awaiter(this, void 0, void 0, function* () { + let component = null; + const relatedModules = module.relatedModules || []; + for (const relatedModule of this.flatMap([...relatedModules.values()])) { + const { components, exports } = relatedModule; + const isInScope = context === null; + if ((!exports.has(name) && !isInScope) || !components.has(name)) { + continue; + } + component = components.get(name); + if (!component.isResolved && !component.forwardRef) { + const ctx = isInScope ? [module] : [].concat(context, module); + yield this.loadInstanceOfComponent(component, relatedModule, ctx); + break; + } + } + return component; + }); + } + resolveFactoryInstance(factoryResult) { + return __awaiter(this, void 0, void 0, function* () { + if (!(factoryResult instanceof Promise)) { + return factoryResult; + } + const result = yield factoryResult; + return result; + }); + } + flatMap(modules) { + return modules.concat.apply(modules, modules.map((module) => { + const { relatedModules, exports } = module; + return this.flatMap([...relatedModules.values()].filter((related) => { + const { metatype } = related; + return exports.has(metatype.name); + })); + })); + } +} +exports.Injector = Injector; diff --git a/lib/core/injector/instance-loader.d.ts b/lib/core/injector/instance-loader.d.ts new file mode 100644 index 00000000000..71a0fea8d66 --- /dev/null +++ b/lib/core/injector/instance-loader.d.ts @@ -0,0 +1,16 @@ +import { NestContainer } from './container'; +export declare class InstanceLoader { + private readonly container; + private readonly injector; + private readonly logger; + constructor(container: NestContainer); + createInstancesOfDependencies(): Promise; + private createPrototypes(modules); + private createInstances(modules); + private createPrototypesOfComponents(module); + private createInstancesOfComponents(module); + private createPrototypesOfRoutes(module); + private createInstancesOfRoutes(module); + private createPrototypesOfInjectables(module); + private createInstancesOfInjectables(module); +} diff --git a/lib/core/injector/instance-loader.js b/lib/core/injector/instance-loader.js new file mode 100644 index 00000000000..69f8ee45cd7 --- /dev/null +++ b/lib/core/injector/instance-loader.js @@ -0,0 +1,78 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const injector_1 = require("./injector"); +const common_1 = require("@nestjs/common"); +const messages_1 = require("../helpers/messages"); +class InstanceLoader { + constructor(container) { + this.container = container; + this.injector = new injector_1.Injector(); + this.logger = new common_1.Logger(InstanceLoader.name, true); + } + createInstancesOfDependencies() { + return __awaiter(this, void 0, void 0, function* () { + const modules = this.container.getModules(); + this.createPrototypes(modules); + yield this.createInstances(modules); + }); + } + createPrototypes(modules) { + modules.forEach((module) => { + this.createPrototypesOfComponents(module); + this.createPrototypesOfInjectables(module); + this.createPrototypesOfRoutes(module); + }); + } + createInstances(modules) { + return __awaiter(this, void 0, void 0, function* () { + for (const module of [...modules.values()]) { + yield this.createInstancesOfComponents(module); + yield this.createInstancesOfInjectables(module); + yield this.createInstancesOfRoutes(module); + const { name } = module.metatype; + this.logger.log(messages_1.ModuleInitMessage(name)); + } + }); + } + createPrototypesOfComponents(module) { + module.components.forEach((wrapper) => { + this.injector.loadPrototypeOfInstance(wrapper, module.components); + }); + } + createInstancesOfComponents(module) { + return __awaiter(this, void 0, void 0, function* () { + for (const [key, wrapper] of module.components) { + yield this.injector.loadInstanceOfComponent(wrapper, module); + } + }); + } + createPrototypesOfRoutes(module) { + module.routes.forEach((wrapper) => { + this.injector.loadPrototypeOfInstance(wrapper, module.routes); + }); + } + createInstancesOfRoutes(module) { + return __awaiter(this, void 0, void 0, function* () { + yield Promise.all([...module.routes.values()].map((wrapper) => __awaiter(this, void 0, void 0, function* () { return yield this.injector.loadInstanceOfRoute(wrapper, module); }))); + }); + } + createPrototypesOfInjectables(module) { + module.injectables.forEach((wrapper) => { + this.injector.loadPrototypeOfInstance(wrapper, module.injectables); + }); + } + createInstancesOfInjectables(module) { + return __awaiter(this, void 0, void 0, function* () { + yield Promise.all([...module.injectables.values()].map((wrapper) => __awaiter(this, void 0, void 0, function* () { return yield this.injector.loadInstanceOfInjectable(wrapper, module); }))); + }); + } +} +exports.InstanceLoader = InstanceLoader; diff --git a/lib/core/injector/module-ref.d.ts b/lib/core/injector/module-ref.d.ts new file mode 100644 index 00000000000..eefe16c7326 --- /dev/null +++ b/lib/core/injector/module-ref.d.ts @@ -0,0 +1,4 @@ +import { OpaqueToken } from './module'; +export declare abstract class ModuleRef { + abstract get(type: OpaqueToken): T; +} diff --git a/lib/core/injector/module-ref.js b/lib/core/injector/module-ref.js new file mode 100644 index 00000000000..d5f06f1c973 --- /dev/null +++ b/lib/core/injector/module-ref.js @@ -0,0 +1,5 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class ModuleRef { +} +exports.ModuleRef = ModuleRef; diff --git a/lib/core/injector/module-token-factory.d.ts b/lib/core/injector/module-token-factory.d.ts new file mode 100644 index 00000000000..7406d9d9ee5 --- /dev/null +++ b/lib/core/injector/module-token-factory.d.ts @@ -0,0 +1,7 @@ +import { NestModuleMetatype } from '@nestjs/common/interfaces/modules/module-metatype.interface'; +export declare class ModuleTokenFactory { + create(metatype: NestModuleMetatype, scope: NestModuleMetatype[]): string; + getModuleName(metatype: NestModuleMetatype): string; + getScopeStack(scope: NestModuleMetatype[]): string[]; + private reflectScope(metatype); +} diff --git a/lib/core/injector/module-token-factory.js b/lib/core/injector/module-token-factory.js new file mode 100644 index 00000000000..b0d5aa6199f --- /dev/null +++ b/lib/core/injector/module-token-factory.js @@ -0,0 +1,29 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const constants_1 = require("@nestjs/common/constants"); +class ModuleTokenFactory { + create(metatype, scope) { + const reflectedScope = this.reflectScope(metatype); + const isSingleScoped = reflectedScope === true; + const opaqueToken = { + module: this.getModuleName(metatype), + scope: isSingleScoped ? this.getScopeStack(scope) : reflectedScope, + }; + return JSON.stringify(opaqueToken); + } + getModuleName(metatype) { + return metatype.name; + } + getScopeStack(scope) { + const reversedScope = scope.reverse(); + const firstGlobalIndex = reversedScope.findIndex((s) => this.reflectScope(s) === 'global'); + scope.reverse(); + const stack = firstGlobalIndex >= 0 ? scope.slice(scope.length - firstGlobalIndex - 1) : scope; + return stack.map((module) => module.name); + } + reflectScope(metatype) { + const reflectedScope = Reflect.getMetadata(constants_1.SHARED_MODULE_METADATA, metatype); + return reflectedScope ? reflectedScope : 'global'; + } +} +exports.ModuleTokenFactory = ModuleTokenFactory; diff --git a/lib/core/injector/module.d.ts b/lib/core/injector/module.d.ts new file mode 100644 index 00000000000..0e876d83353 --- /dev/null +++ b/lib/core/injector/module.d.ts @@ -0,0 +1,63 @@ +import { InstanceWrapper } from './container'; +import { Injectable, Controller, NestModule } from '@nestjs/common/interfaces'; +import { NestModuleMetatype } from '@nestjs/common/interfaces/modules/module-metatype.interface'; +import { Metatype } from '@nestjs/common/interfaces/metatype.interface'; +export interface CustomComponent { + provide: any; + name: string; +} +export declare type OpaqueToken = string | symbol | object | Metatype; +export declare type CustomClass = CustomComponent & { + useClass: Metatype; +}; +export declare type CustomFactory = CustomComponent & { + useFactory: (...args) => any; + inject?: Metatype[]; +}; +export declare type CustomValue = CustomComponent & { + useValue: any; +}; +export declare type ComponentMetatype = Metatype | CustomFactory | CustomValue | CustomClass; +export declare class Module { + private _metatype; + private _scope; + private _relatedModules; + private _components; + private _injectables; + private _routes; + private _exports; + constructor(_metatype: NestModuleMetatype, _scope: NestModuleMetatype[]); + readonly scope: NestModuleMetatype[]; + readonly relatedModules: Set; + readonly components: Map>; + readonly injectables: Map>; + readonly routes: Map>; + readonly exports: Set; + readonly instance: NestModule; + readonly metatype: NestModuleMetatype; + addCoreInjectables(): void; + addModuleRef(): void; + addModuleAsComponent(): void; + addReflector(): void; + addInjectable(injectable: Metatype): void; + addComponent(component: ComponentMetatype): void; + isCustomProvider(component: ComponentMetatype): component is CustomClass | CustomFactory | CustomValue; + addCustomProvider(component: CustomFactory | CustomValue | CustomClass, collection: Map): void; + isCustomClass(component: any): component is CustomClass; + isCustomValue(component: any): component is CustomValue; + isCustomFactory(component: any): component is CustomFactory; + addCustomClass(component: CustomClass, collection: Map): void; + addCustomValue(component: CustomValue, collection: Map): void; + addCustomFactory(component: CustomFactory, collection: Map): void; + addExportedComponent(exportedComponent: ComponentMetatype): void; + addCustomExportedComponent(exportedComponent: CustomFactory | CustomValue | CustomClass): void; + addRoute(route: Metatype): void; + addRelatedModule(relatedModule: any): void; + replace(toReplace: any, options: any): void; + createModuleRefMetatype(components: any): { + new (): { + readonly components: any; + get(type: string | symbol | object | Metatype): T; + }; + }; +} diff --git a/lib/core/injector/module.js b/lib/core/injector/module.js new file mode 100644 index 00000000000..bca3af213c1 --- /dev/null +++ b/lib/core/injector/module.js @@ -0,0 +1,192 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const module_ref_1 = require("./module-ref"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const runtime_exception_1 = require("../errors/exceptions/runtime.exception"); +const reflector_service_1 = require("../services/reflector.service"); +class Module { + constructor(_metatype, _scope) { + this._metatype = _metatype; + this._scope = _scope; + this._relatedModules = new Set(); + this._components = new Map(); + this._injectables = new Map(); + this._routes = new Map(); + this._exports = new Set(); + this.addCoreInjectables(); + } + get scope() { + return this._scope; + } + get relatedModules() { + return this._relatedModules; + } + get components() { + return this._components; + } + get injectables() { + return this._injectables; + } + get routes() { + return this._routes; + } + get exports() { + return this._exports; + } + get instance() { + if (!this._components.has(this._metatype.name)) { + throw new runtime_exception_1.RuntimeException(); + } + const module = this._components.get(this._metatype.name); + return module.instance; + } + get metatype() { + return this._metatype; + } + addCoreInjectables() { + this.addModuleRef(); + this.addModuleAsComponent(); + this.addReflector(); + } + addModuleRef() { + const moduleRef = this.createModuleRefMetatype(this._components); + this._components.set(module_ref_1.ModuleRef.name, { + name: module_ref_1.ModuleRef.name, + metatype: module_ref_1.ModuleRef, + isResolved: true, + instance: new moduleRef(), + }); + } + addModuleAsComponent() { + this._components.set(this._metatype.name, { + name: this._metatype.name, + metatype: this._metatype, + isResolved: false, + instance: null, + }); + } + addReflector() { + this._components.set(reflector_service_1.Reflector.name, { + name: reflector_service_1.Reflector.name, + metatype: reflector_service_1.Reflector, + isResolved: false, + instance: null, + }); + } + addInjectable(injectable) { + if (this.isCustomProvider(injectable)) { + return this.addCustomProvider(injectable, this._injectables); + } + this._injectables.set(injectable.name, { + name: injectable.name, + metatype: injectable, + instance: null, + isResolved: false, + }); + } + addComponent(component) { + if (this.isCustomProvider(component)) { + this.addCustomProvider(component, this._components); + return; + } + this._components.set(component.name, { + name: component.name, + metatype: component, + instance: null, + isResolved: false, + }); + } + isCustomProvider(component) { + return !shared_utils_1.isNil(component.provide); + } + addCustomProvider(component, collection) { + const { provide } = component; + const name = shared_utils_1.isFunction(provide) ? provide.name : provide; + const comp = Object.assign({}, component, { name }); + if (this.isCustomClass(comp)) + this.addCustomClass(comp, collection); + else if (this.isCustomValue(comp)) + this.addCustomValue(comp, collection); + else if (this.isCustomFactory(comp)) + this.addCustomFactory(comp, collection); + } + isCustomClass(component) { + return !shared_utils_1.isUndefined(component.useClass); + } + isCustomValue(component) { + return !shared_utils_1.isUndefined(component.useValue); + } + isCustomFactory(component) { + return !shared_utils_1.isUndefined(component.useFactory); + } + addCustomClass(component, collection) { + const { provide, name, useClass } = component; + collection.set(name, { + name, + metatype: useClass, + instance: null, + isResolved: false, + }); + } + addCustomValue(component, collection) { + const { provide, name, useValue: value } = component; + collection.set(name, { + name, + metatype: null, + instance: value, + isResolved: true, + isNotMetatype: true, + async: value instanceof Promise, + }); + } + addCustomFactory(component, collection) { + const { provide, name, useFactory: factory, inject } = component; + collection.set(name, { + name, + metatype: factory, + instance: null, + isResolved: false, + inject: inject || [], + isNotMetatype: true, + }); + } + addExportedComponent(exportedComponent) { + if (this.isCustomProvider(exportedComponent)) { + return this.addCustomExportedComponent(exportedComponent); + } + this._exports.add(exportedComponent.name); + } + addCustomExportedComponent(exportedComponent) { + this._exports.add(exportedComponent.provide); + } + addRoute(route) { + this._routes.set(route.name, { + name: route.name, + metatype: route, + instance: null, + isResolved: false, + }); + } + addRelatedModule(relatedModule) { + this._relatedModules.add(relatedModule); + } + replace(toReplace, options) { + if (options.isComponent) { + return this.addComponent(Object.assign({ provide: toReplace }, options)); + } + this.addInjectable(Object.assign({ provide: toReplace }, options)); + } + createModuleRefMetatype(components) { + return class { + constructor() { + this.components = components; + } + get(type) { + const name = shared_utils_1.isFunction(type) ? type.name : type; + const exists = this.components.has(name); + return exists ? this.components.get(name).instance : null; + } + }; + } +} +exports.Module = Module; diff --git a/lib/core/interceptors/interceptors-consumer.d.ts b/lib/core/interceptors/interceptors-consumer.d.ts new file mode 100644 index 00000000000..58598449dee --- /dev/null +++ b/lib/core/interceptors/interceptors-consumer.d.ts @@ -0,0 +1,11 @@ +import { Controller } from '@nestjs/common/interfaces'; +import { ExecutionContext, NestInterceptor } from '@nestjs/common'; +import { Observable } from 'rxjs/Observable'; +import 'rxjs/add/operator/toPromise'; +import 'rxjs/add/observable/defer'; +import 'rxjs/add/operator/take'; +export declare class InterceptorsConsumer { + intercept(interceptors: NestInterceptor[], dataOrRequest: any, instance: Controller, callback: (...args) => any, next: () => Promise): Promise; + createContext(instance: Controller, callback: (...args) => any): ExecutionContext; + transformDeffered(next: () => any): Promise | Observable; +} diff --git a/lib/core/interceptors/interceptors-consumer.js b/lib/core/interceptors/interceptors-consumer.js new file mode 100644 index 00000000000..e5822bb6142 --- /dev/null +++ b/lib/core/interceptors/interceptors-consumer.js @@ -0,0 +1,40 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const Observable_1 = require("rxjs/Observable"); +require("rxjs/add/operator/toPromise"); +require("rxjs/add/observable/defer"); +require("rxjs/add/operator/take"); +class InterceptorsConsumer { + intercept(interceptors, dataOrRequest, instance, callback, next) { + return __awaiter(this, void 0, void 0, function* () { + if (!interceptors || shared_utils_1.isEmpty(interceptors)) { + return yield next(); + } + const context = this.createContext(instance, callback); + const start$ = Observable_1.Observable.defer(() => this.transformDeffered(next)); + const result$ = yield interceptors.reduce((stream$, interceptor) => __awaiter(this, void 0, void 0, function* () { return yield interceptor.intercept(dataOrRequest, context, yield stream$); }), Promise.resolve(start$)); + return yield result$.toPromise(); + }); + } + createContext(instance, callback) { + return { + parent: instance.constructor, + handler: callback, + }; + } + transformDeffered(next) { + const res = next(); + const isDeffered = res instanceof Promise || res instanceof Observable_1.Observable; + return isDeffered ? res : Promise.resolve(res); + } +} +exports.InterceptorsConsumer = InterceptorsConsumer; diff --git a/lib/core/interceptors/interceptors-context-creator.d.ts b/lib/core/interceptors/interceptors-context-creator.d.ts new file mode 100644 index 00000000000..f8e7acf5741 --- /dev/null +++ b/lib/core/interceptors/interceptors-context-creator.d.ts @@ -0,0 +1,18 @@ +import 'reflect-metadata'; +import { Controller, NestInterceptor } from '@nestjs/common/interfaces'; +import { ContextCreator } from './../helpers/context-creator'; +import { NestContainer } from '../injector/container'; +import { ConfigurationProvider } from '@nestjs/common/interfaces/configuration-provider.interface'; +export declare class InterceptorsContextCreator extends ContextCreator { + private readonly container; + private readonly config; + private moduleContext; + constructor(container: NestContainer, config?: ConfigurationProvider); + create(instance: Controller, callback: (...args) => any, module: string): NestInterceptor[]; + createConcreteContext(metadata: T): R; + createGlobalMetadataContext(metadata: T): R; + getInstanceByMetatype(metatype: any): { + instance: any; + } | undefined; + getGlobalMetadata(): T; +} diff --git a/lib/core/interceptors/interceptors-context-creator.js b/lib/core/interceptors/interceptors-context-creator.js new file mode 100644 index 00000000000..cb5efc31da9 --- /dev/null +++ b/lib/core/interceptors/interceptors-context-creator.js @@ -0,0 +1,52 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const iterare_1 = require("iterare"); +const constants_1 = require("@nestjs/common/constants"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const context_creator_1 = require("./../helpers/context-creator"); +class InterceptorsContextCreator extends context_creator_1.ContextCreator { + constructor(container, config) { + super(); + this.container = container; + this.config = config; + } + create(instance, callback, module) { + this.moduleContext = module; + return this.createContext(instance, callback, constants_1.INTERCEPTORS_METADATA); + } + createConcreteContext(metadata) { + if (shared_utils_1.isUndefined(metadata) || shared_utils_1.isEmpty(metadata) || !this.moduleContext) { + return []; + } + const isGlobalMetadata = metadata === this.getGlobalMetadata(); + return isGlobalMetadata ? + this.createGlobalMetadataContext(metadata) : + iterare_1.default(metadata).filter((metatype) => metatype && metatype.name) + .map((metatype) => this.getInstanceByMetatype(metatype)) + .filter((wrapper) => wrapper && wrapper.instance) + .map((wrapper) => wrapper.instance) + .filter((interceptor) => interceptor && shared_utils_1.isFunction(interceptor.intercept)) + .toArray(); + } + createGlobalMetadataContext(metadata) { + return iterare_1.default(metadata) + .filter((interceptor) => interceptor && interceptor.intercept && shared_utils_1.isFunction(interceptor.intercept)) + .toArray(); + } + getInstanceByMetatype(metatype) { + const collection = this.container.getModules(); + const module = collection.get(this.moduleContext); + if (!module) { + return undefined; + } + return module.injectables.get(metatype.name); + } + getGlobalMetadata() { + if (!this.config) { + return []; + } + return this.config.getGlobalInterceptors(); + } +} +exports.InterceptorsContextCreator = InterceptorsContextCreator; diff --git a/lib/core/metadata-scanner.d.ts b/lib/core/metadata-scanner.d.ts new file mode 100644 index 00000000000..a70e7b963dd --- /dev/null +++ b/lib/core/metadata-scanner.d.ts @@ -0,0 +1,4 @@ +import { Injectable } from '@nestjs/common/interfaces/injectable.interface'; +export declare class MetadataScanner { + scanFromPrototype(instance: T, prototype: any, callback: (name: string) => R): R[]; +} diff --git a/lib/core/metadata-scanner.js b/lib/core/metadata-scanner.js new file mode 100644 index 00000000000..d087662280e --- /dev/null +++ b/lib/core/metadata-scanner.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const iterare_1 = require("iterare"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +class MetadataScanner { + scanFromPrototype(instance, prototype, callback) { + return iterare_1.default(Object.getOwnPropertyNames(prototype)) + .filter((method) => { + const descriptor = Object.getOwnPropertyDescriptor(prototype, method); + if (descriptor.set || descriptor.get) { + return false; + } + return !shared_utils_1.isConstructor(method) && shared_utils_1.isFunction(prototype[method]); + }) + .map(callback) + .filter((metadata) => !shared_utils_1.isNil(metadata)) + .toArray(); + } +} +exports.MetadataScanner = MetadataScanner; diff --git a/lib/core/middlewares/builder.d.ts b/lib/core/middlewares/builder.d.ts new file mode 100644 index 00000000000..69fd53603c5 --- /dev/null +++ b/lib/core/middlewares/builder.d.ts @@ -0,0 +1,19 @@ +import { MiddlewareConfiguration } from '@nestjs/common/interfaces/middlewares/middleware-configuration.interface'; +import { MiddlewaresConsumer } from '@nestjs/common/interfaces'; +import { MiddlewareConfigProxy } from '@nestjs/common/interfaces/middlewares'; +import { RoutesMapper } from './routes-mapper'; +export declare class MiddlewareBuilder implements MiddlewaresConsumer { + private readonly routesMapper; + private readonly middlewaresCollection; + private readonly logger; + constructor(routesMapper: RoutesMapper); + apply(middlewares: any | any[]): MiddlewareConfigProxy; + /** + * @deprecated + * Since version RC.6 this method is deprecated. Use apply() instead. + */ + use(configuration: MiddlewareConfiguration): this; + build(): MiddlewareConfiguration[]; + private bindValuesToResolve(middlewares, resolveParams); + private static ConfigProxy; +} diff --git a/lib/core/middlewares/builder.js b/lib/core/middlewares/builder.js new file mode 100644 index 00000000000..3ec1482d949 --- /dev/null +++ b/lib/core/middlewares/builder.js @@ -0,0 +1,65 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const invalid_middleware_configuration_exception_1 = require("../errors/exceptions/invalid-middleware-configuration.exception"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const bind_resolve_values_util_1 = require("@nestjs/common/utils/bind-resolve-values.util"); +const logger_service_1 = require("@nestjs/common/services/logger.service"); +const utils_1 = require("./utils"); +class MiddlewareBuilder { + constructor(routesMapper) { + this.routesMapper = routesMapper; + this.middlewaresCollection = new Set(); + this.logger = new logger_service_1.Logger(MiddlewareBuilder.name); + } + apply(middlewares) { + return new MiddlewareBuilder.ConfigProxy(this, middlewares); + } + /** + * @deprecated + * Since version RC.6 this method is deprecated. Use apply() instead. + */ + use(configuration) { + this.logger.warn('DEPRECATED! Since version RC.6 `use()` method is deprecated. Use `apply()` instead.'); + const { middlewares, forRoutes } = configuration; + if (shared_utils_1.isUndefined(middlewares) || shared_utils_1.isUndefined(forRoutes)) { + throw new invalid_middleware_configuration_exception_1.InvalidMiddlewareConfigurationException(); + } + this.middlewaresCollection.add(configuration); + return this; + } + build() { + return [...this.middlewaresCollection]; + } + bindValuesToResolve(middlewares, resolveParams) { + if (shared_utils_1.isNil(resolveParams)) { + return middlewares; + } + const bindArgs = bind_resolve_values_util_1.BindResolveMiddlewareValues(resolveParams); + return [].concat(middlewares).map(bindArgs); + } +} +MiddlewareBuilder.ConfigProxy = class { + constructor(builder, middlewares) { + this.builder = builder; + this.contextArgs = null; + this.includedRoutes = utils_1.filterMiddlewares(middlewares); + } + with(...args) { + this.contextArgs = args; + return this; + } + forRoutes(...routes) { + const { middlewaresCollection, bindValuesToResolve, routesMapper } = this.builder; + const forRoutes = this.mapRoutesToFlatList(routes.map((route) => routesMapper.mapRouteToRouteProps(route))); + const configuration = { + middlewares: bindValuesToResolve(this.includedRoutes, this.contextArgs), + forRoutes, + }; + middlewaresCollection.add(configuration); + return this.builder; + } + mapRoutesToFlatList(forRoutes) { + return forRoutes.reduce((a, b) => a.concat(b)); + } +}; +exports.MiddlewareBuilder = MiddlewareBuilder; diff --git a/lib/core/middlewares/container.d.ts b/lib/core/middlewares/container.d.ts new file mode 100644 index 00000000000..849e47d0c7c --- /dev/null +++ b/lib/core/middlewares/container.d.ts @@ -0,0 +1,16 @@ +import { MiddlewareConfiguration } from '@nestjs/common/interfaces/middlewares/middleware-configuration.interface'; +import { NestMiddleware } from '@nestjs/common/interfaces/middlewares/nest-middleware.interface'; +import { Metatype } from '@nestjs/common/interfaces/metatype.interface'; +export declare class MiddlewaresContainer { + private readonly middlewares; + private readonly configs; + getMiddlewares(module: string): Map; + getConfigs(): Map>; + addConfig(configList: MiddlewareConfiguration[], module: string): void; + private getCurrentMiddlewares(module); + private getCurrentConfig(module); +} +export interface MiddlewareWrapper { + instance: NestMiddleware; + metatype: Metatype; +} diff --git a/lib/core/middlewares/container.js b/lib/core/middlewares/container.js new file mode 100644 index 00000000000..86fad48d906 --- /dev/null +++ b/lib/core/middlewares/container.js @@ -0,0 +1,42 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class MiddlewaresContainer { + constructor() { + this.middlewares = new Map(); + this.configs = new Map(); + } + getMiddlewares(module) { + return this.middlewares.get(module) || new Map(); + } + getConfigs() { + return this.configs; + } + addConfig(configList, module) { + const middlewares = this.getCurrentMiddlewares(module); + const currentConfig = this.getCurrentConfig(module); + const configurations = configList || []; + configurations.map((config) => { + [].concat(config.middlewares).map((metatype) => { + const token = metatype.name; + middlewares.set(token, { + instance: null, + metatype, + }); + }); + currentConfig.add(config); + }); + } + getCurrentMiddlewares(module) { + if (!this.middlewares.has(module)) { + this.middlewares.set(module, new Map()); + } + return this.middlewares.get(module); + } + getCurrentConfig(module) { + if (!this.configs.has(module)) { + this.configs.set(module, new Set()); + } + return this.configs.get(module); + } +} +exports.MiddlewaresContainer = MiddlewaresContainer; diff --git a/lib/core/middlewares/middlewares-module.d.ts b/lib/core/middlewares/middlewares-module.d.ts new file mode 100644 index 00000000000..ba5e0ef4f8b --- /dev/null +++ b/lib/core/middlewares/middlewares-module.d.ts @@ -0,0 +1,25 @@ +import { NestContainer } from '../injector/container'; +import { MiddlewaresContainer } from './container'; +import { ControllerMetadata } from '@nestjs/common/interfaces/controllers/controller-metadata.interface'; +import { NestModule } from '@nestjs/common/interfaces/modules/nest-module.interface'; +import { MiddlewareConfiguration } from '@nestjs/common/interfaces/middlewares/middleware-configuration.interface'; +import { RequestMethod } from '@nestjs/common/enums/request-method.enum'; +import { Module } from '../injector/module'; +import { ApplicationConfig } from './../application-config'; +export declare class MiddlewaresModule { + private readonly routesMapper; + private readonly routerProxy; + private readonly routerMethodFactory; + private routerExceptionFilter; + private resolver; + setup(middlewaresContainer: MiddlewaresContainer, container: NestContainer, config: ApplicationConfig): Promise; + resolveMiddlewares(middlewaresContainer: MiddlewaresContainer, modules: Map): Promise; + loadConfiguration(middlewaresContainer: MiddlewaresContainer, instance: NestModule, module: string): void; + setupMiddlewares(middlewaresContainer: MiddlewaresContainer, app: any): Promise; + setupMiddlewareConfig(middlewaresContainer: MiddlewaresContainer, config: MiddlewareConfiguration, module: string, app: any): Promise; + setupRouteMiddleware(middlewaresContainer: MiddlewaresContainer, route: ControllerMetadata & { + method: RequestMethod; + }, config: MiddlewareConfiguration, module: string, app: any): Promise; + private setupHandler(instance, metatype, app, method, path); + private setupHandlerWithProxy(exceptionsHandler, router, middleware, path); +} diff --git a/lib/core/middlewares/middlewares-module.js b/lib/core/middlewares/middlewares-module.js new file mode 100644 index 00000000000..5d87c887a24 --- /dev/null +++ b/lib/core/middlewares/middlewares-module.js @@ -0,0 +1,108 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const builder_1 = require("./builder"); +const resolver_1 = require("./resolver"); +const invalid_middleware_exception_1 = require("../errors/exceptions/invalid-middleware.exception"); +const routes_mapper_1 = require("./routes-mapper"); +const router_proxy_1 = require("../router/router-proxy"); +const router_method_factory_1 = require("../helpers/router-method-factory"); +const runtime_exception_1 = require("../errors/exceptions/runtime.exception"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const router_exception_filters_1 = require("./../router/router-exception-filters"); +class MiddlewaresModule { + constructor() { + this.routesMapper = new routes_mapper_1.RoutesMapper(); + this.routerProxy = new router_proxy_1.RouterProxy(); + this.routerMethodFactory = new router_method_factory_1.RouterMethodFactory(); + } + setup(middlewaresContainer, container, config) { + return __awaiter(this, void 0, void 0, function* () { + this.routerExceptionFilter = new router_exception_filters_1.RouterExceptionFilters(config); + this.resolver = new resolver_1.MiddlewaresResolver(middlewaresContainer); + const modules = container.getModules(); + yield this.resolveMiddlewares(middlewaresContainer, modules); + }); + } + resolveMiddlewares(middlewaresContainer, modules) { + return __awaiter(this, void 0, void 0, function* () { + yield Promise.all([...modules.entries()].map(([name, module]) => __awaiter(this, void 0, void 0, function* () { + const instance = module.instance; + this.loadConfiguration(middlewaresContainer, instance, name); + yield this.resolver.resolveInstances(module, name); + }))); + }); + } + loadConfiguration(middlewaresContainer, instance, module) { + if (!instance.configure) + return; + const middlewaresBuilder = new builder_1.MiddlewareBuilder(this.routesMapper); + instance.configure(middlewaresBuilder); + if (!(middlewaresBuilder instanceof builder_1.MiddlewareBuilder)) + return; + const config = middlewaresBuilder.build(); + middlewaresContainer.addConfig(config, module); + } + setupMiddlewares(middlewaresContainer, app) { + return __awaiter(this, void 0, void 0, function* () { + const configs = middlewaresContainer.getConfigs(); + yield Promise.all([...configs.entries()].map(([module, moduleConfigs]) => __awaiter(this, void 0, void 0, function* () { + yield Promise.all([...moduleConfigs].map((config) => __awaiter(this, void 0, void 0, function* () { + yield this.setupMiddlewareConfig(middlewaresContainer, config, module, app); + }))); + }))); + }); + } + setupMiddlewareConfig(middlewaresContainer, config, module, app) { + return __awaiter(this, void 0, void 0, function* () { + const { forRoutes } = config; + yield Promise.all(forRoutes.map((route) => __awaiter(this, void 0, void 0, function* () { + yield this.setupRouteMiddleware(middlewaresContainer, route, config, module, app); + }))); + }); + } + setupRouteMiddleware(middlewaresContainer, route, config, module, app) { + return __awaiter(this, void 0, void 0, function* () { + const { path, method } = route; + const middlewares = [].concat(config.middlewares); + yield Promise.all(middlewares.map((metatype) => __awaiter(this, void 0, void 0, function* () { + const collection = middlewaresContainer.getMiddlewares(module); + const middleware = collection.get(metatype.name); + if (shared_utils_1.isUndefined(middleware)) { + throw new runtime_exception_1.RuntimeException(); + } + const { instance } = middleware; + yield this.setupHandler(instance, metatype, app, method, path); + }))); + }); + } + setupHandler(instance, metatype, app, method, path) { + return __awaiter(this, void 0, void 0, function* () { + if (shared_utils_1.isUndefined(instance.resolve)) { + throw new invalid_middleware_exception_1.InvalidMiddlewareException(metatype.name); + } + const exceptionsHandler = this.routerExceptionFilter.create(instance, instance.resolve); + const router = this.routerMethodFactory.get(app, method).bind(app); + const setupWithProxy = (middleware) => this.setupHandlerWithProxy(exceptionsHandler, router, middleware, path); + const resolve = instance.resolve(); + if (!(resolve instanceof Promise)) { + setupWithProxy(resolve); + return; + } + const middleware = yield resolve; + setupWithProxy(middleware); + }); + } + setupHandlerWithProxy(exceptionsHandler, router, middleware, path) { + const proxy = this.routerProxy.createProxy(middleware, exceptionsHandler); + router(path, proxy); + } +} +exports.MiddlewaresModule = MiddlewaresModule; diff --git a/lib/core/middlewares/resolver.d.ts b/lib/core/middlewares/resolver.d.ts new file mode 100644 index 00000000000..cd82405f852 --- /dev/null +++ b/lib/core/middlewares/resolver.d.ts @@ -0,0 +1,9 @@ +import { MiddlewaresContainer } from './container'; +import { Module } from '../injector/module'; +export declare class MiddlewaresResolver { + private readonly middlewaresContainer; + private readonly instanceLoader; + constructor(middlewaresContainer: MiddlewaresContainer); + resolveInstances(module: Module, moduleName: string): Promise; + private resolveMiddlewareInstance(wrapper, middlewares, module); +} diff --git a/lib/core/middlewares/resolver.js b/lib/core/middlewares/resolver.js new file mode 100644 index 00000000000..9b02787739b --- /dev/null +++ b/lib/core/middlewares/resolver.js @@ -0,0 +1,29 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const injector_1 = require("../injector/injector"); +class MiddlewaresResolver { + constructor(middlewaresContainer) { + this.middlewaresContainer = middlewaresContainer; + this.instanceLoader = new injector_1.Injector(); + } + resolveInstances(module, moduleName) { + return __awaiter(this, void 0, void 0, function* () { + const middlewares = this.middlewaresContainer.getMiddlewares(moduleName); + yield Promise.all([...middlewares.values()].map((wrapper) => __awaiter(this, void 0, void 0, function* () { return yield this.resolveMiddlewareInstance(wrapper, middlewares, module); }))); + }); + } + resolveMiddlewareInstance(wrapper, middlewares, module) { + return __awaiter(this, void 0, void 0, function* () { + yield this.instanceLoader.loadInstanceOfMiddleware(wrapper, middlewares, module); + }); + } +} +exports.MiddlewaresResolver = MiddlewaresResolver; diff --git a/lib/core/middlewares/routes-mapper.d.ts b/lib/core/middlewares/routes-mapper.d.ts new file mode 100644 index 00000000000..7edc27cf9a8 --- /dev/null +++ b/lib/core/middlewares/routes-mapper.d.ts @@ -0,0 +1,11 @@ +import 'reflect-metadata'; +export declare class RoutesMapper { + private readonly routerExplorer; + mapRouteToRouteProps(routeMetatype: any): { + path: string; + method: any; + }[]; + private mapObjectToRouteProps(route); + private validateGlobalPath(path); + private validateRoutePath(path); +} diff --git a/lib/core/middlewares/routes-mapper.js b/lib/core/middlewares/routes-mapper.js new file mode 100644 index 00000000000..24fbb63ec70 --- /dev/null +++ b/lib/core/middlewares/routes-mapper.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const router_explorer_1 = require("../router/router-explorer"); +const unknown_request_mapping_exception_1 = require("../errors/exceptions/unknown-request-mapping.exception"); +const request_method_enum_1 = require("@nestjs/common/enums/request-method.enum"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const constants_1 = require("@nestjs/common/constants"); +const metadata_scanner_1 = require("../metadata-scanner"); +class RoutesMapper { + constructor() { + this.routerExplorer = new router_explorer_1.ExpressRouterExplorer(new metadata_scanner_1.MetadataScanner()); + } + mapRouteToRouteProps(routeMetatype) { + const routePath = Reflect.getMetadata(constants_1.PATH_METADATA, routeMetatype); + if (shared_utils_1.isUndefined(routePath)) { + return [this.mapObjectToRouteProps(routeMetatype)]; + } + const paths = this.routerExplorer.scanForPaths(Object.create(routeMetatype), routeMetatype.prototype); + return paths.map((route) => ({ + path: this.validateGlobalPath(routePath) + this.validateRoutePath(route.path), + method: route.requestMethod, + })); + } + mapObjectToRouteProps(route) { + const { path, method } = route; + if (shared_utils_1.isUndefined(path)) { + throw new unknown_request_mapping_exception_1.UnknownRequestMappingException(); + } + return { + path: this.validateRoutePath(path), + method: shared_utils_1.isUndefined(method) ? request_method_enum_1.RequestMethod.ALL : method, + }; + } + validateGlobalPath(path) { + const prefix = shared_utils_1.validatePath(path); + return prefix === '/' ? '' : prefix; + } + validateRoutePath(path) { + return shared_utils_1.validatePath(path); + } +} +exports.RoutesMapper = RoutesMapper; diff --git a/lib/core/middlewares/utils.d.ts b/lib/core/middlewares/utils.d.ts new file mode 100644 index 00000000000..fe978f7bc21 --- /dev/null +++ b/lib/core/middlewares/utils.d.ts @@ -0,0 +1,5 @@ +import { Metatype } from '@nestjs/common/interfaces'; +export declare const filterMiddlewares: (middlewares: any) => any[]; +export declare const mapToClass: (middleware: any) => any; +export declare const isClass: (middleware: any) => boolean; +export declare const assignToken: (metatype: any) => Metatype; diff --git a/lib/core/middlewares/utils.js b/lib/core/middlewares/utils.js new file mode 100644 index 00000000000..59a0b66db1f --- /dev/null +++ b/lib/core/middlewares/utils.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +exports.filterMiddlewares = (middlewares) => { + return [].concat(middlewares) + .filter(shared_utils_1.isFunction) + .map((middleware) => exports.mapToClass(middleware)); +}; +exports.mapToClass = (middleware) => { + if (this.isClass(middleware)) { + return middleware; + } + return exports.assignToken(class { + constructor() { + this.resolve = (...args) => (req, res, next) => middleware(req, res, next); + } + }); +}; +exports.isClass = (middleware) => { + return middleware.toString().substring(0, 5) === 'class'; +}; +exports.assignToken = (metatype) => { + this.id = this.id || 1; + Object.defineProperty(metatype, 'name', { value: ++this.id }); + return metatype; +}; diff --git a/lib/core/nest-application-context.d.ts b/lib/core/nest-application-context.d.ts new file mode 100644 index 00000000000..9bf3d4717de --- /dev/null +++ b/lib/core/nest-application-context.d.ts @@ -0,0 +1,14 @@ +import { NestContainer } from './injector/container'; +import { NestModuleMetatype } from '@nestjs/common/interfaces/modules/module-metatype.interface'; +import { Metatype } from '@nestjs/common/interfaces'; +import { INestApplicationContext } from '@nestjs/common'; +export declare class NestApplicationContext implements INestApplicationContext { + protected readonly container: NestContainer; + private readonly scope; + private readonly contextModule; + private readonly moduleTokenFactory; + constructor(container: NestContainer, scope: NestModuleMetatype[], contextModule: any); + select(module: Metatype): INestApplicationContext; + get(metatypeOrToken: Metatype | string): T; + private findInstanceByPrototypeOrToken(metatypeOrToken); +} diff --git a/lib/core/nest-application-context.js b/lib/core/nest-application-context.js new file mode 100644 index 00000000000..17f37b940d9 --- /dev/null +++ b/lib/core/nest-application-context.js @@ -0,0 +1,38 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const module_token_factory_1 = require("./injector/module-token-factory"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +class NestApplicationContext { + constructor(container, scope, contextModule) { + this.container = container; + this.scope = scope; + this.contextModule = contextModule; + this.moduleTokenFactory = new module_token_factory_1.ModuleTokenFactory(); + } + select(module) { + const modules = this.container.getModules(); + const moduleMetatype = this.contextModule.metatype; + const scope = this.scope.concat(moduleMetatype); + const token = this.moduleTokenFactory.create(module, scope); + const selectedModule = modules.get(token); + return selectedModule + ? new NestApplicationContext(this.container, scope, selectedModule) + : null; + } + get(metatypeOrToken) { + return this.findInstanceByPrototypeOrToken(metatypeOrToken); + } + findInstanceByPrototypeOrToken(metatypeOrToken) { + const dependencies = new Map([ + ...this.contextModule.components, + ...this.contextModule.routes, + ...this.contextModule.injectables, + ]); + const name = shared_utils_1.isFunction(metatypeOrToken) ? metatypeOrToken.name : metatypeOrToken; + const instanceWrapper = dependencies.get(name); + return instanceWrapper + ? instanceWrapper.instance + : null; + } +} +exports.NestApplicationContext = NestApplicationContext; diff --git a/lib/core/nest-application.d.ts b/lib/core/nest-application.d.ts new file mode 100644 index 00000000000..aef0eb71e9e --- /dev/null +++ b/lib/core/nest-application.d.ts @@ -0,0 +1,46 @@ +import { CanActivate, ExceptionFilter, NestInterceptor, PipeTransform, WebSocketAdapter } from '@nestjs/common'; +import { INestApplication, INestMicroservice } from '@nestjs/common'; +import { MicroserviceConfiguration } from '@nestjs/common/interfaces/microservices/microservice-configuration.interface'; +import { NestContainer } from './injector/container'; +export declare class NestApplication implements INestApplication { + private readonly container; + private readonly express; + private readonly logger; + private readonly middlewaresModule; + private readonly middlewaresContainer; + private readonly microservicesModule; + private readonly socketModule; + private readonly httpServer; + private readonly routesResolver; + private readonly config; + private readonly microservices; + private isInitialized; + constructor(container: NestContainer, express: any); + setupParserMiddlewares(): void; + setupModules(): Promise; + init(): Promise; + setupRouter(): Promise; + connectMicroservice(config: MicroserviceConfiguration): INestMicroservice; + getMicroservices(): INestMicroservice[]; + startAllMicroservices(callback?: () => void): void; + startAllMicroservicesAsync(): Promise; + use(requestHandler: any): void; + listen(port: number, callback?: () => void): any; + listen(port: number, hostname: string, callback?: () => void): any; + listenAsync(port: number, hostname?: string): Promise; + close(): void; + setGlobalPrefix(prefix: string): void; + useWebSocketAdapter(adapter: WebSocketAdapter): void; + useGlobalFilters(...filters: ExceptionFilter[]): void; + useGlobalPipes(...pipes: PipeTransform[]): void; + useGlobalInterceptors(...interceptors: NestInterceptor[]): void; + useGlobalGuards(...guards: CanActivate[]): void; + private setupMiddlewares(instance); + private listenToPromise(microservice); + private callInitHook(); + private callModuleInitHook(module); + private hasOnModuleInitHook(instance); + private callDestroyHook(); + private callModuleDestroyHook(module); + private hasOnModuleDestroyHook(instance); +} diff --git a/lib/core/nest-application.js b/lib/core/nest-application.js new file mode 100644 index 00000000000..e1d141bc0a5 --- /dev/null +++ b/lib/core/nest-application.js @@ -0,0 +1,187 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const http = require("http"); +const optional = require("optional"); +const bodyParser = require("body-parser"); +const iterare_1 = require("iterare"); +const logger_service_1 = require("@nestjs/common/services/logger.service"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const express_adapter_1 = require("./adapters/express-adapter"); +const application_config_1 = require("./application-config"); +const constants_1 = require("./constants"); +const middlewares_module_1 = require("./middlewares/middlewares-module"); +const routes_resolver_1 = require("./router/routes-resolver"); +const microservices_package_not_found_exception_1 = require("./errors/exceptions/microservices-package-not-found.exception"); +const container_1 = require("./middlewares/container"); +const { SocketModule } = optional('@nestjs/websockets/socket-module') || {}; +const { MicroservicesModule } = optional('@nestjs/microservices/microservices-module') || {}; +const { NestMicroservice } = optional('@nestjs/microservices/nest-microservice') || {}; +const { IoAdapter } = optional('@nestjs/websockets/adapters/io-adapter') || {}; +class NestApplication { + constructor(container, express) { + this.container = container; + this.express = express; + this.logger = new logger_service_1.Logger(NestApplication.name, true); + this.middlewaresModule = new middlewares_module_1.MiddlewaresModule(); + this.middlewaresContainer = new container_1.MiddlewaresContainer(); + this.microservicesModule = MicroservicesModule + ? new MicroservicesModule() + : null; + this.socketModule = SocketModule + ? new SocketModule() + : null; + this.httpServer = null; + this.routesResolver = null; + this.microservices = []; + this.isInitialized = false; + this.setupParserMiddlewares(); + this.httpServer = http.createServer(express); + const ioAdapter = IoAdapter ? new IoAdapter(this.httpServer) : null; + this.config = new application_config_1.ApplicationConfig(ioAdapter); + this.routesResolver = new routes_resolver_1.RoutesResolver(container, express_adapter_1.ExpressAdapter, this.config); + } + setupParserMiddlewares() { + this.express.use(bodyParser.json()); + this.express.use(bodyParser.urlencoded({ extended: true })); + } + setupModules() { + return __awaiter(this, void 0, void 0, function* () { + this.socketModule && this.socketModule.setup(this.container, this.config); + if (this.microservicesModule) { + this.microservicesModule.setup(this.container, this.config); + this.microservicesModule.setupClients(this.container); + } + yield this.middlewaresModule.setup(this.middlewaresContainer, this.container, this.config); + }); + } + init() { + return __awaiter(this, void 0, void 0, function* () { + yield this.setupModules(); + yield this.setupRouter(); + this.callInitHook(); + this.logger.log(constants_1.messages.APPLICATION_READY); + this.isInitialized = true; + }); + } + setupRouter() { + return __awaiter(this, void 0, void 0, function* () { + const router = express_adapter_1.ExpressAdapter.createRouter(); + yield this.setupMiddlewares(router); + this.routesResolver.resolve(router); + this.express.use(shared_utils_1.validatePath(this.config.getGlobalPrefix()), router); + }); + } + connectMicroservice(config) { + if (!NestMicroservice) { + throw new microservices_package_not_found_exception_1.MicroservicesPackageNotFoundException(); + } + const instance = new NestMicroservice(this.container, config); + instance.setupListeners(); + instance.setIsInitialized(true); + instance.setIsInitHookCalled(true); + this.microservices.push(instance); + return instance; + } + getMicroservices() { + return this.microservices; + } + startAllMicroservices(callback) { + Promise.all(this.microservices.map(this.listenToPromise)).then(() => callback && callback()); + } + startAllMicroservicesAsync() { + return new Promise((resolve) => this.startAllMicroservices(resolve)); + } + use(requestHandler) { + this.express.use(requestHandler); + } + listen(port, ...args) { + return __awaiter(this, void 0, void 0, function* () { + (!this.isInitialized) && (yield this.init()); + this.httpServer.listen(port, ...args); + return this.httpServer; + }); + } + listenAsync(port, hostname) { + return new Promise((resolve) => { + const server = this.listen(port, hostname, () => resolve(server)); + }); + } + close() { + this.socketModule && this.socketModule.close(); + this.httpServer && this.httpServer.close(); + this.microservices.forEach((microservice) => { + microservice.setIsTerminated(true); + microservice.close(); + }); + this.callDestroyHook(); + } + setGlobalPrefix(prefix) { + this.config.setGlobalPrefix(prefix); + } + useWebSocketAdapter(adapter) { + this.config.setIoAdapter(adapter); + } + useGlobalFilters(...filters) { + this.config.useGlobalFilters(...filters); + } + useGlobalPipes(...pipes) { + this.config.useGlobalPipes(...pipes); + } + useGlobalInterceptors(...interceptors) { + this.config.useGlobalInterceptors(...interceptors); + } + useGlobalGuards(...guards) { + this.config.useGlobalGuards(...guards); + } + setupMiddlewares(instance) { + return __awaiter(this, void 0, void 0, function* () { + yield this.middlewaresModule.setupMiddlewares(this.middlewaresContainer, instance); + }); + } + listenToPromise(microservice) { + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + yield microservice.listen(resolve); + })); + } + callInitHook() { + const modules = this.container.getModules(); + modules.forEach((module) => { + this.callModuleInitHook(module); + }); + } + callModuleInitHook(module) { + const components = [...module.routes, ...module.components]; + iterare_1.default(components).map(([key, { instance }]) => instance) + .filter((instance) => !shared_utils_1.isNil(instance)) + .filter(this.hasOnModuleInitHook) + .forEach((instance) => instance.onModuleInit()); + } + hasOnModuleInitHook(instance) { + return !shared_utils_1.isUndefined(instance.onModuleInit); + } + callDestroyHook() { + const modules = this.container.getModules(); + modules.forEach((module) => { + this.callModuleDestroyHook(module); + }); + } + callModuleDestroyHook(module) { + const components = [...module.routes, ...module.components]; + iterare_1.default(components).map(([key, { instance }]) => instance) + .filter((instance) => !shared_utils_1.isNil(instance)) + .filter(this.hasOnModuleDestroyHook) + .forEach((instance) => instance.onModuleDestroy()); + } + hasOnModuleDestroyHook(instance) { + return !shared_utils_1.isUndefined(instance.onModuleDestroy); + } +} +exports.NestApplication = NestApplication; diff --git a/lib/core/nest-factory.d.ts b/lib/core/nest-factory.d.ts new file mode 100644 index 00000000000..821d1e32ea5 --- /dev/null +++ b/lib/core/nest-factory.d.ts @@ -0,0 +1,36 @@ +import { MicroserviceConfiguration } from '@nestjs/common/interfaces/microservices/microservice-configuration.interface'; +import { INestApplication, INestMicroservice, INestApplicationContext } from '@nestjs/common'; +export declare class NestFactoryStatic { + private container; + private instanceLoader; + private logger; + private dependenciesScanner; + /** + * Creates an instance of the NestApplication (returns Promise) + * + * @param {} module Entry (root) application module class + * @param {} express Optional express() server instance + * @returns an `Promise` of the INestApplication instance + */ + create(module: any, express?: any): Promise; + /** + * Creates an instance of the NestMicroservice (returns Promise) + * + * @param {} module Entry (root) application module class + * @param {MicroserviceConfiguration} config Optional microservice configuration + * @returns an `Promise` of the INestMicroservice instance + */ + createMicroservice(module: any, config?: MicroserviceConfiguration): Promise; + /** + * Creates an instance of the NestApplicationContext (returns Promise) + * + * @param {} module Entry (root) application module class + * @returns an `Promise` of the INestApplicationContext instance + */ + createApplicationContext(module: any): Promise; + private createNestInstance(instance); + private initialize(module); + private createProxy(target); + private createExceptionProxy(); +} +export declare const NestFactory: NestFactoryStatic; diff --git a/lib/core/nest-factory.js b/lib/core/nest-factory.js new file mode 100644 index 00000000000..8453137efbb --- /dev/null +++ b/lib/core/nest-factory.js @@ -0,0 +1,117 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const optional = require("optional"); +const scanner_1 = require("./scanner"); +const instance_loader_1 = require("./injector/instance-loader"); +const container_1 = require("./injector/container"); +const exceptions_zone_1 = require("./errors/exceptions-zone"); +const logger_service_1 = require("@nestjs/common/services/logger.service"); +const constants_1 = require("./constants"); +const nest_application_1 = require("./nest-application"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const express_adapter_1 = require("./adapters/express-adapter"); +const metadata_scanner_1 = require("./metadata-scanner"); +const microservices_package_not_found_exception_1 = require("./errors/exceptions/microservices-package-not-found.exception"); +const nest_application_context_1 = require("./nest-application-context"); +const { NestMicroservice } = optional('@nestjs/microservices/nest-microservice') || {}; +class NestFactoryStatic { + constructor() { + this.container = new container_1.NestContainer(); + this.instanceLoader = new instance_loader_1.InstanceLoader(this.container); + this.logger = new logger_service_1.Logger('NestFactory', true); + this.dependenciesScanner = new scanner_1.DependenciesScanner(this.container, new metadata_scanner_1.MetadataScanner()); + } + /** + * Creates an instance of the NestApplication (returns Promise) + * + * @param {} module Entry (root) application module class + * @param {} express Optional express() server instance + * @returns an `Promise` of the INestApplication instance + */ + create(module, express = express_adapter_1.ExpressAdapter.create()) { + return __awaiter(this, void 0, void 0, function* () { + yield this.initialize(module); + return this.createNestInstance(new nest_application_1.NestApplication(this.container, express)); + }); + } + /** + * Creates an instance of the NestMicroservice (returns Promise) + * + * @param {} module Entry (root) application module class + * @param {MicroserviceConfiguration} config Optional microservice configuration + * @returns an `Promise` of the INestMicroservice instance + */ + createMicroservice(module, config) { + return __awaiter(this, void 0, void 0, function* () { + if (!NestMicroservice) { + throw new microservices_package_not_found_exception_1.MicroservicesPackageNotFoundException(); + } + yield this.initialize(module); + return this.createNestInstance(new NestMicroservice(this.container, config)); + }); + } + /** + * Creates an instance of the NestApplicationContext (returns Promise) + * + * @param {} module Entry (root) application module class + * @returns an `Promise` of the INestApplicationContext instance + */ + createApplicationContext(module) { + return __awaiter(this, void 0, void 0, function* () { + yield this.initialize(module); + const modules = this.container.getModules().values(); + const root = modules.next().value; + return this.createNestInstance(new nest_application_context_1.NestApplicationContext(this.container, [], root)); + }); + } + createNestInstance(instance) { + return this.createProxy(instance); + } + initialize(module) { + return __awaiter(this, void 0, void 0, function* () { + try { + this.logger.log(constants_1.messages.APPLICATION_START); + yield exceptions_zone_1.ExceptionsZone.asyncRun(() => __awaiter(this, void 0, void 0, function* () { + this.dependenciesScanner.scan(module); + yield this.instanceLoader.createInstancesOfDependencies(); + })); + } + catch (e) { + process.abort(); + } + }); + } + createProxy(target) { + const proxy = this.createExceptionProxy(); + return new Proxy(target, { + get: proxy, + set: proxy, + }); + } + createExceptionProxy() { + return (receiver, prop) => { + if (!(prop in receiver)) + return; + if (shared_utils_1.isFunction(receiver[prop])) { + return (...args) => { + let result; + exceptions_zone_1.ExceptionsZone.run(() => { + result = receiver[prop](...args); + }); + return result; + }; + } + return receiver[prop]; + }; + } +} +exports.NestFactoryStatic = NestFactoryStatic; +exports.NestFactory = new NestFactoryStatic(); diff --git a/lib/core/pipes/params-token-factory.d.ts b/lib/core/pipes/params-token-factory.d.ts new file mode 100644 index 00000000000..221008b8935 --- /dev/null +++ b/lib/core/pipes/params-token-factory.d.ts @@ -0,0 +1,5 @@ +import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum'; +import { Paramtype } from '@nestjs/common'; +export declare class ParamsTokenFactory { + exchangeEnumForString(type: RouteParamtypes): Paramtype; +} diff --git a/lib/core/pipes/params-token-factory.js b/lib/core/pipes/params-token-factory.js new file mode 100644 index 00000000000..8ca9495e616 --- /dev/null +++ b/lib/core/pipes/params-token-factory.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const route_paramtypes_enum_1 = require("@nestjs/common/enums/route-paramtypes.enum"); +class ParamsTokenFactory { + exchangeEnumForString(type) { + switch (type) { + case route_paramtypes_enum_1.RouteParamtypes.BODY: return 'body'; + case route_paramtypes_enum_1.RouteParamtypes.PARAM: return 'param'; + case route_paramtypes_enum_1.RouteParamtypes.QUERY: return 'query'; + default: return null; + } + } +} +exports.ParamsTokenFactory = ParamsTokenFactory; diff --git a/lib/core/pipes/pipes-consumer.d.ts b/lib/core/pipes/pipes-consumer.d.ts new file mode 100644 index 00000000000..0ab5d8f6d19 --- /dev/null +++ b/lib/core/pipes/pipes-consumer.d.ts @@ -0,0 +1,14 @@ +import { Transform } from '@nestjs/common/interfaces'; +export declare class PipesConsumer { + private readonly paramsTokenFactory; + apply(value: any, {metatype, type, data}: { + metatype: any; + type: any; + data: any; + }, transforms: Transform[]): Promise; + applyPipes(value: any, {metatype, type, data}: { + metatype; + type?; + data?; + }, transforms: Transform[]): Promise; +} diff --git a/lib/core/pipes/pipes-consumer.js b/lib/core/pipes/pipes-consumer.js new file mode 100644 index 00000000000..6965ce392f6 --- /dev/null +++ b/lib/core/pipes/pipes-consumer.js @@ -0,0 +1,35 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const params_token_factory_1 = require("./../pipes/params-token-factory"); +class PipesConsumer { + constructor() { + this.paramsTokenFactory = new params_token_factory_1.ParamsTokenFactory(); + } + apply(value, { metatype, type, data }, transforms) { + return __awaiter(this, void 0, void 0, function* () { + const token = this.paramsTokenFactory.exchangeEnumForString(type); + return yield this.applyPipes(value, { metatype, type: token, data }, transforms); + }); + } + applyPipes(value, { metatype, type, data }, transforms) { + return __awaiter(this, void 0, void 0, function* () { + return yield transforms.reduce((defferedValue, fn) => __awaiter(this, void 0, void 0, function* () { + const val = yield defferedValue; + const result = fn(val, { metatype, type, data }); + if (result instanceof Promise) { + return result; + } + return Promise.resolve(result); + }), Promise.resolve(value)); + }); + } +} +exports.PipesConsumer = PipesConsumer; diff --git a/lib/core/pipes/pipes-context-creator.d.ts b/lib/core/pipes/pipes-context-creator.d.ts new file mode 100644 index 00000000000..f627cb58425 --- /dev/null +++ b/lib/core/pipes/pipes-context-creator.d.ts @@ -0,0 +1,11 @@ +import 'reflect-metadata'; +import { Controller, Transform } from '@nestjs/common/interfaces'; +import { ApplicationConfig } from './../application-config'; +import { ContextCreator } from './../helpers/context-creator'; +export declare class PipesContextCreator extends ContextCreator { + private readonly config; + constructor(config?: ApplicationConfig); + create(instance: Controller, callback: (...args) => any): Transform[]; + createConcreteContext(metadata: T): R; + getGlobalMetadata(): T; +} diff --git a/lib/core/pipes/pipes-context-creator.js b/lib/core/pipes/pipes-context-creator.js new file mode 100644 index 00000000000..50a7eb6150c --- /dev/null +++ b/lib/core/pipes/pipes-context-creator.js @@ -0,0 +1,31 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const iterare_1 = require("iterare"); +const constants_1 = require("@nestjs/common/constants"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const context_creator_1 = require("./../helpers/context-creator"); +class PipesContextCreator extends context_creator_1.ContextCreator { + constructor(config) { + super(); + this.config = config; + } + create(instance, callback) { + return this.createContext(instance, callback, constants_1.PIPES_METADATA); + } + createConcreteContext(metadata) { + if (shared_utils_1.isUndefined(metadata) || shared_utils_1.isEmpty(metadata)) { + return []; + } + return iterare_1.default(metadata).filter((pipe) => pipe && pipe.transform && shared_utils_1.isFunction(pipe.transform)) + .map((pipe) => pipe.transform.bind(pipe)) + .toArray(); + } + getGlobalMetadata() { + if (!this.config) { + return []; + } + return this.config.getGlobalPipes(); + } +} +exports.PipesContextCreator = PipesContextCreator; diff --git a/lib/core/router/interfaces/exceptions-filter.interface.d.ts b/lib/core/router/interfaces/exceptions-filter.interface.d.ts new file mode 100644 index 00000000000..d2b0809070b --- /dev/null +++ b/lib/core/router/interfaces/exceptions-filter.interface.d.ts @@ -0,0 +1,5 @@ +import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface'; +import { ExceptionsHandler } from '../../exceptions/exceptions-handler'; +export interface ExceptionsFilter { + create(instance: Controller, callback: any): ExceptionsHandler; +} diff --git a/lib/core/router/interfaces/exceptions-filter.interface.js b/lib/core/router/interfaces/exceptions-filter.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/core/router/interfaces/exceptions-filter.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/core/router/interfaces/explorer.inteface.d.ts b/lib/core/router/interfaces/explorer.inteface.d.ts new file mode 100644 index 00000000000..e70b8064bbc --- /dev/null +++ b/lib/core/router/interfaces/explorer.inteface.d.ts @@ -0,0 +1,6 @@ +import { Controller } from '@nestjs/common/interfaces/index'; +import { Metatype } from '@nestjs/common/interfaces/metatype.interface'; +export interface RouterExplorer { + explore(instance: Controller, metatype: Metatype, module: string): any; + fetchRouterPath(metatype: Metatype): string; +} diff --git a/lib/core/router/interfaces/explorer.inteface.js b/lib/core/router/interfaces/explorer.inteface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/core/router/interfaces/explorer.inteface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/core/router/interfaces/resolver.interface.d.ts b/lib/core/router/interfaces/resolver.interface.d.ts new file mode 100644 index 00000000000..9d7b066456a --- /dev/null +++ b/lib/core/router/interfaces/resolver.interface.d.ts @@ -0,0 +1,3 @@ +export interface Resolver { + resolve(express: any): any; +} diff --git a/lib/core/router/interfaces/resolver.interface.js b/lib/core/router/interfaces/resolver.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/core/router/interfaces/resolver.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/core/router/interfaces/route-params-factory.interface.d.ts b/lib/core/router/interfaces/route-params-factory.interface.d.ts new file mode 100644 index 00000000000..59562cb9b4d --- /dev/null +++ b/lib/core/router/interfaces/route-params-factory.interface.d.ts @@ -0,0 +1,8 @@ +import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum'; +export interface IRouteParamsFactory { + exchangeKeyForValue(key: RouteParamtypes, data: any, {req, res, next}: { + req: any; + res: any; + next: any; + }): any; +} diff --git a/lib/core/router/interfaces/route-params-factory.interface.js b/lib/core/router/interfaces/route-params-factory.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/core/router/interfaces/route-params-factory.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/core/router/route-params-factory.d.ts b/lib/core/router/route-params-factory.d.ts new file mode 100644 index 00000000000..90e96011f49 --- /dev/null +++ b/lib/core/router/route-params-factory.d.ts @@ -0,0 +1,9 @@ +import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum'; +import { IRouteParamsFactory } from './interfaces/route-params-factory.interface'; +export declare class RouteParamsFactory implements IRouteParamsFactory { + exchangeKeyForValue(key: RouteParamtypes, data: any, {req, res, next}: { + req: any; + res: any; + next: any; + }): any; +} diff --git a/lib/core/router/route-params-factory.js b/lib/core/router/route-params-factory.js new file mode 100644 index 00000000000..e4c9c985f47 --- /dev/null +++ b/lib/core/router/route-params-factory.js @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const route_paramtypes_enum_1 = require("@nestjs/common/enums/route-paramtypes.enum"); +class RouteParamsFactory { + exchangeKeyForValue(key, data, { req, res, next }) { + switch (key) { + case route_paramtypes_enum_1.RouteParamtypes.NEXT: return next; + case route_paramtypes_enum_1.RouteParamtypes.REQUEST: return req; + case route_paramtypes_enum_1.RouteParamtypes.RESPONSE: return res; + case route_paramtypes_enum_1.RouteParamtypes.BODY: return data && req.body ? req.body[data] : req.body; + case route_paramtypes_enum_1.RouteParamtypes.PARAM: return data ? req.params[data] : req.params; + case route_paramtypes_enum_1.RouteParamtypes.QUERY: return data ? req.query[data] : req.query; + case route_paramtypes_enum_1.RouteParamtypes.HEADERS: return data ? req.headers[data] : req.headers; + case route_paramtypes_enum_1.RouteParamtypes.SESSION: return req.session; + default: return null; + } + } +} +exports.RouteParamsFactory = RouteParamsFactory; diff --git a/lib/core/router/router-exception-filters.d.ts b/lib/core/router/router-exception-filters.d.ts new file mode 100644 index 00000000000..21387c4e346 --- /dev/null +++ b/lib/core/router/router-exception-filters.d.ts @@ -0,0 +1,12 @@ +import 'reflect-metadata'; +import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface'; +import { ExceptionsHandler } from '../exceptions/exceptions-handler'; +import { RouterProxyCallback } from './../router/router-proxy'; +import { ApplicationConfig } from './../application-config'; +import { BaseExceptionFilterContext } from '../exceptions/base-exception-filter-context'; +export declare class RouterExceptionFilters extends BaseExceptionFilterContext { + private readonly config; + constructor(config: ApplicationConfig); + create(instance: Controller, callback: RouterProxyCallback): ExceptionsHandler; + getGlobalMetadata(): T; +} diff --git a/lib/core/router/router-exception-filters.js b/lib/core/router/router-exception-filters.js new file mode 100644 index 00000000000..cd629a5b3b7 --- /dev/null +++ b/lib/core/router/router-exception-filters.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const exceptions_handler_1 = require("../exceptions/exceptions-handler"); +const constants_1 = require("@nestjs/common/constants"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const base_exception_filter_context_1 = require("../exceptions/base-exception-filter-context"); +class RouterExceptionFilters extends base_exception_filter_context_1.BaseExceptionFilterContext { + constructor(config) { + super(); + this.config = config; + } + create(instance, callback) { + const exceptionHandler = new exceptions_handler_1.ExceptionsHandler(); + const filters = this.createContext(instance, callback, constants_1.EXCEPTION_FILTERS_METADATA); + if (shared_utils_1.isEmpty(filters)) { + return exceptionHandler; + } + exceptionHandler.setCustomFilters(filters); + return exceptionHandler; + } + getGlobalMetadata() { + return this.config.getGlobalFilters(); + } +} +exports.RouterExceptionFilters = RouterExceptionFilters; diff --git a/lib/core/router/router-execution-context.d.ts b/lib/core/router/router-execution-context.d.ts new file mode 100644 index 00000000000..37d26ee0f1a --- /dev/null +++ b/lib/core/router/router-execution-context.d.ts @@ -0,0 +1,47 @@ +import 'reflect-metadata'; +import { RouteParamtypes } from '@nestjs/common/enums/route-paramtypes.enum'; +import { Controller, Transform } from '@nestjs/common/interfaces'; +import { RouteParamsMetadata } from '@nestjs/common/utils'; +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 } from '@nestjs/common'; +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'; +export interface ParamProperties { + index: number; + type: RouteParamtypes; + data: ParamData; + pipes: PipeTransform[]; + extractValue: (req, res, next) => any; +} +export declare class RouterExecutionContext { + private readonly paramsFactory; + private readonly pipesContextCreator; + private readonly pipesConsumer; + private readonly guardsContextCreator; + private readonly guardsConsumer; + private readonly interceptorsContextCreator; + private readonly interceptorsConsumer; + private readonly responseController; + constructor(paramsFactory: IRouteParamsFactory, pipesContextCreator: PipesContextCreator, pipesConsumer: PipesConsumer, guardsContextCreator: GuardsContextCreator, guardsConsumer: GuardsConsumer, interceptorsContextCreator: InterceptorsContextCreator, interceptorsConsumer: InterceptorsConsumer); + create(instance: Controller, callback: (...args) => any, methodName: string, module: string, requestMethod: RequestMethod): (req: any, res: any, next: any) => Promise; + mapParamType(key: string): RouteParamtypes | number; + reflectCallbackMetadata(instance: Controller, methodName: string): RouteParamsMetadata; + reflectCallbackParamtypes(instance: Controller, methodName: string): any[]; + reflectHttpStatusCode(callback: (...args) => any): number; + getArgumentsLength(keys: string[], metadata: RouteParamsMetadata): number; + createNullArray(length: number): any[]; + exchangeKeysForValues(keys: string[], metadata: RouteParamsMetadata): ParamProperties[]; + getCustomFactory(factory: (...args) => void, data: any): (...args) => any; + mergeParamsMetatypes(paramsProperties: ParamProperties[], paramtypes: any[]): (ParamProperties & { + metatype?: any; + })[]; + getParamValue(value: T, {metatype, type, data}: { + metatype: any; + type: any; + data: any; + }, transforms: Transform[]): Promise; +} diff --git a/lib/core/router/router-execution-context.js b/lib/core/router/router-execution-context.js new file mode 100644 index 00000000000..3de1d5a536b --- /dev/null +++ b/lib/core/router/router-execution-context.js @@ -0,0 +1,113 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("@nestjs/common/constants"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const route_paramtypes_enum_1 = require("@nestjs/common/enums/route-paramtypes.enum"); +const common_1 = require("@nestjs/common"); +const constants_2 = require("../guards/constants"); +const router_response_controller_1 = require("./router-response-controller"); +class RouterExecutionContext { + constructor(paramsFactory, pipesContextCreator, pipesConsumer, guardsContextCreator, guardsConsumer, interceptorsContextCreator, interceptorsConsumer) { + this.paramsFactory = paramsFactory; + this.pipesContextCreator = pipesContextCreator; + this.pipesConsumer = pipesConsumer; + this.guardsContextCreator = guardsContextCreator; + this.guardsConsumer = guardsConsumer; + this.interceptorsContextCreator = interceptorsContextCreator; + this.interceptorsConsumer = interceptorsConsumer; + this.responseController = new router_response_controller_1.RouterResponseController(); + } + create(instance, callback, methodName, module, requestMethod) { + const metadata = this.reflectCallbackMetadata(instance, methodName) || {}; + const keys = Object.keys(metadata); + const argsLength = this.getArgumentsLength(keys, metadata); + const pipes = this.pipesContextCreator.create(instance, callback); + const paramtypes = this.reflectCallbackParamtypes(instance, methodName); + const guards = this.guardsContextCreator.create(instance, callback, module); + const interceptors = this.interceptorsContextCreator.create(instance, callback, module); + const httpCode = this.reflectHttpStatusCode(callback); + const paramsMetadata = this.exchangeKeysForValues(keys, metadata); + const isResponseHandled = paramsMetadata.some(({ type }) => type === route_paramtypes_enum_1.RouteParamtypes.RESPONSE || type === route_paramtypes_enum_1.RouteParamtypes.NEXT); + const paramsOptions = this.mergeParamsMetatypes(paramsMetadata, paramtypes); + return (req, res, next) => __awaiter(this, void 0, void 0, function* () { + const args = this.createNullArray(argsLength); + const canActivate = yield this.guardsConsumer.tryActivate(guards, req, instance, callback); + if (!canActivate) { + throw new common_1.HttpException(constants_2.FORBIDDEN_MESSAGE, common_1.HttpStatus.FORBIDDEN); + } + yield Promise.all(paramsOptions.map((param) => __awaiter(this, void 0, void 0, function* () { + const { index, extractValue, type, data, metatype, pipes: paramPipes } = param; + const value = extractValue(req, res, next); + args[index] = yield this.getParamValue(value, { metatype, type, data }, pipes.concat(this.pipesContextCreator.createConcreteContext(paramPipes))); + }))); + const handler = () => callback.apply(instance, args); + const result = yield this.interceptorsConsumer.intercept(interceptors, req, instance, callback, handler); + return !isResponseHandled ? + this.responseController.apply(result, res, requestMethod, httpCode) : + undefined; + }); + } + mapParamType(key) { + const keyPair = key.split(':'); + return Number(keyPair[0]); + } + reflectCallbackMetadata(instance, methodName) { + return Reflect.getMetadata(constants_1.ROUTE_ARGS_METADATA, instance, methodName); + } + reflectCallbackParamtypes(instance, methodName) { + return Reflect.getMetadata(constants_1.PARAMTYPES_METADATA, instance, methodName); + } + reflectHttpStatusCode(callback) { + return Reflect.getMetadata(constants_1.HTTP_CODE_METADATA, callback); + } + getArgumentsLength(keys, metadata) { + return Math.max(...keys.map(key => metadata[key].index)) + 1; + } + createNullArray(length) { + return Array.apply(null, { length }).fill(null); + } + exchangeKeysForValues(keys, metadata) { + return keys.map(key => { + const { index, data, pipes } = metadata[key]; + const type = this.mapParamType(key); + if (key.includes(constants_1.CUSTOM_ROUTE_AGRS_METADATA)) { + const { factory } = metadata[key]; + const customExtractValue = this.getCustomFactory(factory, data); + return { index, extractValue: customExtractValue, type, data, pipes }; + } + const extractValue = (req, res, next) => this.paramsFactory.exchangeKeyForValue(type, data, { req, res, next }); + return { index, extractValue, type, data, pipes }; + }); + } + getCustomFactory(factory, data) { + return !shared_utils_1.isUndefined(factory) && shared_utils_1.isFunction(factory) + ? (req, res, next) => factory(data, req) + : () => null; + } + mergeParamsMetatypes(paramsProperties, paramtypes) { + if (!paramtypes) { + return paramsProperties; + } + return paramsProperties.map((param) => (Object.assign({}, param, { metatype: paramtypes[param.index] }))); + } + getParamValue(value, { metatype, type, data }, transforms) { + return __awaiter(this, void 0, void 0, function* () { + if (type === route_paramtypes_enum_1.RouteParamtypes.BODY + || type === route_paramtypes_enum_1.RouteParamtypes.QUERY + || type === route_paramtypes_enum_1.RouteParamtypes.PARAM) { + return yield this.pipesConsumer.apply(value, { metatype, type, data }, transforms); + } + return Promise.resolve(value); + }); + } +} +exports.RouterExecutionContext = RouterExecutionContext; diff --git a/lib/core/router/router-explorer.d.ts b/lib/core/router/router-explorer.d.ts new file mode 100644 index 00000000000..e2f9367a0f0 --- /dev/null +++ b/lib/core/router/router-explorer.d.ts @@ -0,0 +1,36 @@ +import 'reflect-metadata'; +import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface'; +import { RequestMethod } from '@nestjs/common/enums/request-method.enum'; +import { RouterProxy, RouterProxyCallback } from './router-proxy'; +import { ExpressAdapter } from '../adapters/express-adapter'; +import { Metatype } from '@nestjs/common/interfaces/metatype.interface'; +import { ExceptionsFilter } from './interfaces/exceptions-filter.interface'; +import { RouterExplorer } from './interfaces/explorer.inteface'; +import { MetadataScanner } from '../metadata-scanner'; +import { ApplicationConfig } from './../application-config'; +import { NestContainer } from '../injector/container'; +export declare class ExpressRouterExplorer implements RouterExplorer { + private readonly metadataScanner; + private readonly routerProxy; + private readonly expressAdapter; + private readonly exceptionsFilter; + private readonly config; + private readonly executionContextCreator; + private readonly routerMethodFactory; + private readonly logger; + constructor(metadataScanner?: MetadataScanner, routerProxy?: RouterProxy, expressAdapter?: ExpressAdapter, exceptionsFilter?: ExceptionsFilter, config?: ApplicationConfig, container?: NestContainer); + explore(instance: Controller, metatype: Metatype, module: string): any; + fetchRouterPath(metatype: Metatype): string; + validateRoutePath(path: string): string; + scanForPaths(instance: Controller, prototype?: any): RoutePathProperties[]; + exploreMethodMetadata(instance: Controller, instancePrototype: any, methodName: string): RoutePathProperties; + applyPathsToRouterProxy(router: any, routePaths: RoutePathProperties[], instance: Controller, module: string): void; + private applyCallbackToRouter(router, pathProperties, instance, module); + private createCallbackProxy(instance, callback, methodName, module, requestMethod); +} +export interface RoutePathProperties { + path: string; + requestMethod: RequestMethod; + targetCallback: RouterProxyCallback; + methodName: string; +} diff --git a/lib/core/router/router-explorer.js b/lib/core/router/router-explorer.js new file mode 100644 index 00000000000..cb16e33eca0 --- /dev/null +++ b/lib/core/router/router-explorer.js @@ -0,0 +1,82 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const unknown_request_mapping_exception_1 = require("../errors/exceptions/unknown-request-mapping.exception"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const router_method_factory_1 = require("../helpers/router-method-factory"); +const constants_1 = require("@nestjs/common/constants"); +const logger_service_1 = require("@nestjs/common/services/logger.service"); +const messages_1 = require("../helpers/messages"); +const router_execution_context_1 = require("./router-execution-context"); +const route_params_factory_1 = require("./route-params-factory"); +const pipes_context_creator_1 = require("./../pipes/pipes-context-creator"); +const pipes_consumer_1 = require("./../pipes/pipes-consumer"); +const guards_context_creator_1 = require("../guards/guards-context-creator"); +const guards_consumer_1 = require("../guards/guards-consumer"); +const interceptors_context_creator_1 = require("../interceptors/interceptors-context-creator"); +const interceptors_consumer_1 = require("../interceptors/interceptors-consumer"); +class ExpressRouterExplorer { + constructor(metadataScanner, routerProxy, expressAdapter, exceptionsFilter, config, container) { + this.metadataScanner = metadataScanner; + this.routerProxy = routerProxy; + this.expressAdapter = expressAdapter; + this.exceptionsFilter = exceptionsFilter; + this.config = config; + this.routerMethodFactory = new router_method_factory_1.RouterMethodFactory(); + this.logger = new logger_service_1.Logger('RouterExplorer', true); + this.executionContextCreator = new router_execution_context_1.RouterExecutionContext(new route_params_factory_1.RouteParamsFactory(), new pipes_context_creator_1.PipesContextCreator(config), new pipes_consumer_1.PipesConsumer(), new guards_context_creator_1.GuardsContextCreator(container, config), new guards_consumer_1.GuardsConsumer(), new interceptors_context_creator_1.InterceptorsContextCreator(container, config), new interceptors_consumer_1.InterceptorsConsumer()); + } + explore(instance, metatype, module) { + const router = this.expressAdapter.createRouter(); + const routerPaths = this.scanForPaths(instance); + this.applyPathsToRouterProxy(router, routerPaths, instance, module); + return router; + } + fetchRouterPath(metatype) { + const path = Reflect.getMetadata(constants_1.PATH_METADATA, metatype); + return this.validateRoutePath(path); + } + validateRoutePath(path) { + if (shared_utils_1.isUndefined(path)) { + throw new unknown_request_mapping_exception_1.UnknownRequestMappingException(); + } + return shared_utils_1.validatePath(path); + } + scanForPaths(instance, prototype) { + const instancePrototype = shared_utils_1.isUndefined(prototype) ? Object.getPrototypeOf(instance) : prototype; + return this.metadataScanner.scanFromPrototype(instance, instancePrototype, (method) => this.exploreMethodMetadata(instance, instancePrototype, method)); + } + exploreMethodMetadata(instance, instancePrototype, methodName) { + const targetCallback = instancePrototype[methodName]; + const routePath = Reflect.getMetadata(constants_1.PATH_METADATA, targetCallback); + if (shared_utils_1.isUndefined(routePath)) { + return null; + } + const requestMethod = Reflect.getMetadata(constants_1.METHOD_METADATA, targetCallback); + return { + path: this.validateRoutePath(routePath), + requestMethod, + targetCallback, + methodName, + }; + } + applyPathsToRouterProxy(router, routePaths, instance, module) { + (routePaths || []).map((pathProperties) => { + const { path, requestMethod } = pathProperties; + this.applyCallbackToRouter(router, pathProperties, instance, module); + this.logger.log(messages_1.RouteMappedMessage(path, requestMethod)); + }); + } + applyCallbackToRouter(router, pathProperties, instance, module) { + const { path, requestMethod, targetCallback, methodName } = pathProperties; + const routerMethod = this.routerMethodFactory.get(router, requestMethod).bind(router); + const proxy = this.createCallbackProxy(instance, targetCallback, methodName, module, requestMethod); + routerMethod(path, proxy); + } + createCallbackProxy(instance, callback, methodName, module, requestMethod) { + const executionContext = this.executionContextCreator.create(instance, callback, methodName, module, requestMethod); + const exceptionFilter = this.exceptionsFilter.create(instance, callback); + return this.routerProxy.createProxy(executionContext, exceptionFilter); + } +} +exports.ExpressRouterExplorer = ExpressRouterExplorer; diff --git a/lib/core/router/router-proxy.d.ts b/lib/core/router/router-proxy.d.ts new file mode 100644 index 00000000000..e97414bb7e6 --- /dev/null +++ b/lib/core/router/router-proxy.d.ts @@ -0,0 +1,6 @@ +import { ExceptionsHandler } from '../exceptions/exceptions-handler'; +export declare type RouterProxyCallback = (req?, res?, next?) => void; +export declare class RouterProxy { + createProxy(targetCallback: RouterProxyCallback, exceptionsHandler: ExceptionsHandler): (req: any, res: any, next: any) => void; + createExceptionLayerProxy(targetCallback: (err, req, res, next) => void, exceptionsHandler: ExceptionsHandler): (err: any, req: any, res: any, next: any) => void; +} diff --git a/lib/core/router/router-proxy.js b/lib/core/router/router-proxy.js new file mode 100644 index 00000000000..68d6151aff1 --- /dev/null +++ b/lib/core/router/router-proxy.js @@ -0,0 +1,31 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class RouterProxy { + createProxy(targetCallback, exceptionsHandler) { + return (req, res, next) => { + try { + Promise.resolve(targetCallback(req, res, next)) + .catch((e) => { + exceptionsHandler.next(e, res); + }); + } + catch (e) { + exceptionsHandler.next(e, res); + } + }; + } + createExceptionLayerProxy(targetCallback, exceptionsHandler) { + return (err, req, res, next) => { + try { + Promise.resolve(targetCallback(err, req, res, next)) + .catch((e) => { + exceptionsHandler.next(e, res); + }); + } + catch (e) { + exceptionsHandler.next(e, res); + } + }; + } +} +exports.RouterProxy = RouterProxy; diff --git a/lib/core/router/router-response-controller.d.ts b/lib/core/router/router-response-controller.d.ts new file mode 100644 index 00000000000..ba2047d4e34 --- /dev/null +++ b/lib/core/router/router-response-controller.d.ts @@ -0,0 +1,7 @@ +import { RequestMethod } from '@nestjs/common'; +import 'rxjs/add/operator/toPromise'; +export declare class RouterResponseController { + apply(resultOrDeffered: any, response: any, requestMethod: RequestMethod, httpCode: number): Promise; + transformToResult(resultOrDeffered: any): Promise; + getStatusByMethod(requestMethod: RequestMethod): number; +} diff --git a/lib/core/router/router-response-controller.js b/lib/core/router/router-response-controller.js new file mode 100644 index 00000000000..d7567ab7750 --- /dev/null +++ b/lib/core/router/router-response-controller.js @@ -0,0 +1,45 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Observable_1 = require("rxjs/Observable"); +const common_1 = require("@nestjs/common"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +require("rxjs/add/operator/toPromise"); +class RouterResponseController { + apply(resultOrDeffered, response, requestMethod, httpCode) { + return __awaiter(this, void 0, void 0, function* () { + const result = yield this.transformToResult(resultOrDeffered); + const statusCode = httpCode ? httpCode : this.getStatusByMethod(requestMethod); + const res = response.status(statusCode); + if (shared_utils_1.isNil(result)) { + return res.send(); + } + return shared_utils_1.isObject(result) ? res.json(result) : res.send(String(result)); + }); + } + transformToResult(resultOrDeffered) { + return __awaiter(this, void 0, void 0, function* () { + if (resultOrDeffered instanceof Promise) { + return yield resultOrDeffered; + } + else if (resultOrDeffered instanceof Observable_1.Observable) { + return yield resultOrDeffered.toPromise(); + } + return resultOrDeffered; + }); + } + getStatusByMethod(requestMethod) { + switch (requestMethod) { + case common_1.RequestMethod.POST: return common_1.HttpStatus.CREATED; + default: return common_1.HttpStatus.OK; + } + } +} +exports.RouterResponseController = RouterResponseController; diff --git a/lib/core/router/routes-resolver.d.ts b/lib/core/router/routes-resolver.d.ts new file mode 100644 index 00000000000..6a24bfaf875 --- /dev/null +++ b/lib/core/router/routes-resolver.d.ts @@ -0,0 +1,19 @@ +/// +import { Application } from 'express'; +import { NestContainer, InstanceWrapper } from '../injector/container'; +import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface'; +import { Resolver } from './interfaces/resolver.interface'; +import { ApplicationConfig } from './../application-config'; +export declare class RoutesResolver implements Resolver { + private readonly container; + private readonly expressAdapter; + private readonly config; + private readonly logger; + private readonly routerProxy; + private readonly routerExceptionsFilter; + private readonly routerBuilder; + constructor(container: NestContainer, expressAdapter: any, config: ApplicationConfig); + resolve(express: Application): void; + setupRouters(routes: Map>, moduleName: string, express: Application): void; + setupExceptionHandler(express: Application): void; +} diff --git a/lib/core/router/routes-resolver.js b/lib/core/router/routes-resolver.js new file mode 100644 index 00000000000..8d00fd7b4b0 --- /dev/null +++ b/lib/core/router/routes-resolver.js @@ -0,0 +1,42 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const router_proxy_1 = require("./router-proxy"); +const logger_service_1 = require("@nestjs/common/services/logger.service"); +const messages_1 = require("../helpers/messages"); +const router_exception_filters_1 = require("./router-exception-filters"); +const metadata_scanner_1 = require("../metadata-scanner"); +const router_explorer_1 = require("./router-explorer"); +class RoutesResolver { + constructor(container, expressAdapter, config) { + this.container = container; + this.expressAdapter = expressAdapter; + this.config = config; + this.logger = new logger_service_1.Logger(RoutesResolver.name, true); + this.routerProxy = new router_proxy_1.RouterProxy(); + this.routerExceptionsFilter = new router_exception_filters_1.RouterExceptionFilters(config); + this.routerBuilder = new router_explorer_1.ExpressRouterExplorer(new metadata_scanner_1.MetadataScanner(), this.routerProxy, expressAdapter, this.routerExceptionsFilter, config, this.container); + } + resolve(express) { + const modules = this.container.getModules(); + modules.forEach(({ routes }, moduleName) => this.setupRouters(routes, moduleName, express)); + } + setupRouters(routes, moduleName, express) { + routes.forEach(({ instance, metatype }) => { + const path = this.routerBuilder.fetchRouterPath(metatype); + const controllerName = metatype.name; + this.logger.log(messages_1.ControllerMappingMessage(controllerName, path)); + const router = this.routerBuilder.explore(instance, metatype, moduleName); + express.use(path, router); + }); + this.setupExceptionHandler(express); + } + setupExceptionHandler(express) { + const callback = (err, req, res, next) => { + throw err; + }; + const exceptionHandler = this.routerExceptionsFilter.create({}, callback); + const proxy = this.routerProxy.createExceptionLayerProxy(callback, exceptionHandler); + express.use(proxy); + } +} +exports.RoutesResolver = RoutesResolver; diff --git a/lib/core/scanner.d.ts b/lib/core/scanner.d.ts new file mode 100644 index 00000000000..da2b873a2d2 --- /dev/null +++ b/lib/core/scanner.d.ts @@ -0,0 +1,32 @@ +import 'reflect-metadata'; +import { NestContainer } from './injector/container'; +import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface'; +import { Injectable } from '@nestjs/common/interfaces/injectable.interface'; +import { NestModuleMetatype } from '@nestjs/common/interfaces/modules/module-metatype.interface'; +import { Metatype } from '@nestjs/common/interfaces/metatype.interface'; +import { MetadataScanner } from '../core/metadata-scanner'; +export declare class DependenciesScanner { + private readonly container; + private readonly metadataScanner; + constructor(container: NestContainer, metadataScanner: MetadataScanner); + scan(module: NestModuleMetatype): void; + scanForModules(module: NestModuleMetatype, scope?: NestModuleMetatype[]): void; + storeModule(module: any, scope: NestModuleMetatype[]): void; + scanModulesForDependencies(): void; + reflectRelatedModules(module: NestModuleMetatype, token: string): void; + reflectComponents(module: NestModuleMetatype, token: string): void; + reflectComponentMetadata(component: Metatype, token: string): void; + reflectControllers(module: NestModuleMetatype, token: string): void; + reflectDynamicMetadata(obj: Metatype, token: string): void; + reflectExports(module: NestModuleMetatype, token: string): void; + reflectGatewaysMiddlewares(component: Metatype, token: string): void; + reflectGuards(component: Metatype, token: string): void; + reflectInterceptors(component: Metatype, token: string): void; + reflectKeyMetadata(component: Metatype, key: string, method: string): any; + storeRelatedModule(related: any, token: string): void; + storeComponent(component: Metatype, token: string): void; + storeInjectable(component: Metatype, token: string): void; + storeExportedComponent(exportedComponent: Metatype, token: string): void; + storeRoute(route: Metatype, token: string): void; + reflectMetadata(metatype: any, metadata: string): any; +} diff --git a/lib/core/scanner.js b/lib/core/scanner.js new file mode 100644 index 00000000000..f0350c3baaf --- /dev/null +++ b/lib/core/scanner.js @@ -0,0 +1,111 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("@nestjs/common/constants"); +class DependenciesScanner { + constructor(container, metadataScanner) { + this.container = container; + this.metadataScanner = metadataScanner; + } + scan(module) { + this.scanForModules(module); + this.scanModulesForDependencies(); + } + scanForModules(module, scope = []) { + this.storeModule(module, scope); + const importedModules = this.reflectMetadata(module, constants_1.metadata.MODULES); + importedModules.map((innerModule) => { + this.scanForModules(innerModule, [].concat(scope, module)); + }); + } + storeModule(module, scope) { + if (module && module.forwardRef) { + return this.container.addModule(module.forwardRef(), scope); + } + this.container.addModule(module, scope); + } + scanModulesForDependencies() { + const modules = this.container.getModules(); + modules.forEach(({ metatype }, token) => { + this.reflectRelatedModules(metatype, token); + this.reflectComponents(metatype, token); + this.reflectControllers(metatype, token); + this.reflectExports(metatype, token); + }); + } + reflectRelatedModules(module, token) { + const modules = this.reflectMetadata(module, constants_1.metadata.MODULES); + modules.map((related) => this.storeRelatedModule(related, token)); + } + reflectComponents(module, token) { + const components = this.reflectMetadata(module, constants_1.metadata.COMPONENTS); + components.map((component) => { + this.storeComponent(component, token); + this.reflectComponentMetadata(component, token); + this.reflectDynamicMetadata(component, token); + }); + } + reflectComponentMetadata(component, token) { + this.reflectGatewaysMiddlewares(component, token); + } + reflectControllers(module, token) { + const routes = this.reflectMetadata(module, constants_1.metadata.CONTROLLERS); + routes.map((route) => { + this.storeRoute(route, token); + this.reflectDynamicMetadata(route, token); + }); + } + reflectDynamicMetadata(obj, token) { + if (!obj.prototype) { + return; + } + this.reflectGuards(obj, token); + this.reflectInterceptors(obj, token); + } + reflectExports(module, token) { + const exports = this.reflectMetadata(module, constants_1.metadata.EXPORTS); + exports.map((exportedComponent) => this.storeExportedComponent(exportedComponent, token)); + } + reflectGatewaysMiddlewares(component, token) { + const middlewares = this.reflectMetadata(component, constants_1.GATEWAY_MIDDLEWARES); + middlewares.map((middleware) => this.storeComponent(middleware, token)); + } + reflectGuards(component, token) { + const controllerGuards = this.reflectMetadata(component, constants_1.GUARDS_METADATA); + const methodsGuards = this.metadataScanner.scanFromPrototype(null, component.prototype, this.reflectKeyMetadata.bind(this, component, constants_1.GUARDS_METADATA)); + const flattenMethodsGuards = methodsGuards.reduce((a, b) => a.concat(b), []); + [...controllerGuards, ...flattenMethodsGuards].map((guard) => this.storeInjectable(guard, token)); + } + reflectInterceptors(component, token) { + const controllerInterceptors = this.reflectMetadata(component, constants_1.INTERCEPTORS_METADATA); + const methodsInterceptors = this.metadataScanner.scanFromPrototype(null, component.prototype, this.reflectKeyMetadata.bind(this, component, constants_1.INTERCEPTORS_METADATA)); + const flattenMethodsInterceptors = methodsInterceptors.reduce((a, b) => a.concat(b), []); + [...controllerInterceptors, ...flattenMethodsInterceptors].map((guard) => this.storeInjectable(guard, token)); + } + reflectKeyMetadata(component, key, method) { + const descriptor = Reflect.getOwnPropertyDescriptor(component.prototype, method); + return descriptor ? Reflect.getMetadata(key, descriptor.value) : undefined; + } + storeRelatedModule(related, token) { + if (related.forwardRef) { + return this.container.addRelatedModule(related.forwardRef(), token); + } + this.container.addRelatedModule(related, token); + } + storeComponent(component, token) { + this.container.addComponent(component, token); + } + storeInjectable(component, token) { + this.container.addInjectable(component, token); + } + storeExportedComponent(exportedComponent, token) { + this.container.addExportedComponent(exportedComponent, token); + } + storeRoute(route, token) { + this.container.addController(route, token); + } + reflectMetadata(metatype, metadata) { + return Reflect.getMetadata(metadata, metatype) || []; + } +} +exports.DependenciesScanner = DependenciesScanner; diff --git a/lib/core/services/reflector.service.d.ts b/lib/core/services/reflector.service.d.ts new file mode 100644 index 00000000000..2a175378a8c --- /dev/null +++ b/lib/core/services/reflector.service.d.ts @@ -0,0 +1,3 @@ +export declare class Reflector { + get(metadataKey: any, target: any): T; +} diff --git a/lib/core/services/reflector.service.js b/lib/core/services/reflector.service.js new file mode 100644 index 00000000000..2b788a1a0c5 --- /dev/null +++ b/lib/core/services/reflector.service.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class Reflector { + get(metadataKey, target) { + return Reflect.getMetadata(metadataKey, target); + } +} +exports.Reflector = Reflector; diff --git a/lib/microservices/LICENSE b/lib/microservices/LICENSE new file mode 100644 index 00000000000..be7581ff84f --- /dev/null +++ b/lib/microservices/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2017 Kamil Myƛliwiec + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/microservices/Readme.md b/lib/microservices/Readme.md new file mode 100644 index 00000000000..280bd354356 --- /dev/null +++ b/lib/microservices/Readme.md @@ -0,0 +1,125 @@ +

    + Nest Logo +

    + +[travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master +[travis-url]: https://travis-ci.org/nestjs/nest +[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux +[linux-url]: https://travis-ci.org/nestjs/nest + +

    A progressive Node.js framework for building efficient and scalable web applications. :cat:

    +

    +NPM Version +Package License +NPM Downloads +Travis +Linux +Coverage +Gitter +Backers on Open Collective +Sponsors on Open Collective +

    + + +## Description + +

    Nest is a framework for building efficient, scalable Node.js web applications. It uses modern JavaScript, is built with TypeScript (preserves compatibility with pure JavaScript) and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reactive Programming).

    +

    Under the hood, Nest makes use of Express, allowing for easy use of the myriad third-party plugins which are available.

    + +## Philosophy + +

    In recent years, thanks to Node.js, JavaScript has become the “lingua franca” of the web for both front and backend applications, giving rise to awesome projects like Angular, React and Vue which improve developer productivity and enable the construction of fast, testable, extensible frontend applications. However, on the server-side, while there are a lot of superb libraries, helpers and tools for Node, none of them effectively solve the main problem - the architecture.

    +

    Nest aims to provide an application architecture out of the box which allows for effortless creation of highly testable, scalable, loosely coupled and easily maintainable applications.

    + +## Features + +
      +
    • Built with TypeScript (compatible with pure JavaScript + Babel)
    • +
    • Easy to learn - syntax similar to Angular
    • +
    • Familiar - based on well-known libraries (Express / socket.io)
    • +
    • Dependency Injection - built-in asynchronous IoC container with a hierarchical injector
    • +
    • WebSockets module (based on socket.io, but you can bring your own library, by making use of WsAdapter)
    • +
    • Modular - defines an easy to follow module definition pattern so you can split your system into reusable modules
    • +
    • Reactive microservice support with message patterns (built-in transport via TCP / Redis, but other communication schemes can be implemented with CustomTransportStrategy)
    • +
    • Exception layer - throwable web exceptions with status codes, exception filters
    • +
    • Pipes - synchronous & asynchronous (e.g. validation purposes)
    • +
    • Guards - attach additional logic in a declarative manner (e.g. role-based access control)
    • +
    • Interceptors - built on top of RxJS
    • +
    • Testing utilities (both e2e & unit tests)
    • +
    + +## Installation + +**Install the TypeScript Starter Project with Git:** +```bash +$ git clone https://github.com/nestjs/typescript-starter.git project +$ cd project +$ npm install +$ npm run start +``` + +**Install the JavaScript (Babel) Starter Project with Git:** +```bash +$ git clone https://github.com/nestjs/javascript-starter.git project +$ cd project +$ npm install +$ npm run start +``` + +**Start a New Project from Scratch with NPM:** +```bash +$ npm i --save @nestjs/core @nestjs/common @nestjs/microservices @nestjs/websockets @nestjs/testing reflect-metadata rxjs +``` + +## Documentation & Quick Start + +:books: [Documentation & Tutorial](https://docs.nestjs.com) + +## Sponsors + + + +## Backers + +I am on a mission to provide an architecture to create truly flexible, scalable and loosely coupled systems using the Node.js platform. It takes a lot of time, so if you want to support me, please [become a backer / sponsor]((https://opencollective.com/nest#backer)). I appreciate your help. Thanks! :heart_eyes: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## People + +- Author - [Kamil Myƛliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) + +## License + + [MIT](LICENSE) diff --git a/lib/microservices/client/client-proxy-factory.d.ts b/lib/microservices/client/client-proxy-factory.d.ts new file mode 100644 index 00000000000..1afa50f4734 --- /dev/null +++ b/lib/microservices/client/client-proxy-factory.d.ts @@ -0,0 +1,6 @@ +import { ClientMetadata } from '../interfaces/client-metadata.interface'; +import { ClientProxy } from './client-proxy'; +import { Closeable } from '../interfaces/closeable.interface'; +export declare class ClientProxyFactory { + static create(metadata: ClientMetadata): ClientProxy & Closeable; +} diff --git a/lib/microservices/client/client-proxy-factory.js b/lib/microservices/client/client-proxy-factory.js new file mode 100644 index 00000000000..b94cdbc6786 --- /dev/null +++ b/lib/microservices/client/client-proxy-factory.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const client_tcp_1 = require("./client-tcp"); +const client_redis_1 = require("./client-redis"); +const transport_enum_1 = require("../enums/transport.enum"); +class ClientProxyFactory { + static create(metadata) { + const { transport } = metadata; + switch (transport) { + case transport_enum_1.Transport.REDIS: return new client_redis_1.ClientRedis(metadata); + default: return new client_tcp_1.ClientTCP(metadata); + } + } +} +exports.ClientProxyFactory = ClientProxyFactory; diff --git a/lib/microservices/client/client-proxy.d.ts b/lib/microservices/client/client-proxy.d.ts new file mode 100644 index 00000000000..344d81ad736 --- /dev/null +++ b/lib/microservices/client/client-proxy.d.ts @@ -0,0 +1,7 @@ +import { Observable } from 'rxjs/Observable'; +import { Observer } from 'rxjs/Observer'; +export declare abstract class ClientProxy { + protected abstract sendSingleMessage(msg: any, callback: (err, result, disposed?: boolean) => void): any; + send(pattern: any, data: any): Observable; + protected createObserver(observer: Observer): (err, result, disposed?: boolean) => void; +} diff --git a/lib/microservices/client/client-proxy.js b/lib/microservices/client/client-proxy.js new file mode 100644 index 00000000000..dc35b32c0a7 --- /dev/null +++ b/lib/microservices/client/client-proxy.js @@ -0,0 +1,29 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Observable_1 = require("rxjs/Observable"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const invalid_message_exception_1 = require("../exceptions/invalid-message.exception"); +class ClientProxy { + send(pattern, data) { + if (shared_utils_1.isNil(pattern) || shared_utils_1.isNil(data)) { + return Observable_1.Observable.throw(new invalid_message_exception_1.InvalidMessageException()); + } + return Observable_1.Observable.create((observer) => { + this.sendSingleMessage({ pattern, data }, this.createObserver(observer)); + }); + } + createObserver(observer) { + return (err, result, disposed) => { + if (err) { + observer.error(err); + return; + } + else if (disposed) { + observer.complete(); + return; + } + observer.next(result); + }; + } +} +exports.ClientProxy = ClientProxy; diff --git a/lib/microservices/client/client-redis.d.ts b/lib/microservices/client/client-redis.d.ts new file mode 100644 index 00000000000..01f86a63d96 --- /dev/null +++ b/lib/microservices/client/client-redis.d.ts @@ -0,0 +1,17 @@ +import * as redis from 'redis'; +import { ClientProxy } from './client-proxy'; +import { ClientMetadata } from '../interfaces/client-metadata.interface'; +export declare class ClientRedis extends ClientProxy { + private readonly logger; + private readonly url; + private pub; + private sub; + constructor(metadata: ClientMetadata); + protected sendSingleMessage(msg: any, callback: (...args) => any): (channel: any, message: any) => void; + getAckPatternName(pattern: string): string; + getResPatternName(pattern: string): string; + close(): void; + init(): void; + createClient(): redis.RedisClient; + handleErrors(stream: any): void; +} diff --git a/lib/microservices/client/client-redis.js b/lib/microservices/client/client-redis.js new file mode 100644 index 00000000000..9fa36641293 --- /dev/null +++ b/lib/microservices/client/client-redis.js @@ -0,0 +1,59 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const redis = require("redis"); +const client_proxy_1 = require("./client-proxy"); +const logger_service_1 = require("@nestjs/common/services/logger.service"); +const DEFAULT_URL = 'redis://localhost:6379'; +const MESSAGE_EVENT = 'message'; +const ERROR_EVENT = 'error'; +class ClientRedis extends client_proxy_1.ClientProxy { + constructor(metadata) { + super(); + this.logger = new logger_service_1.Logger(client_proxy_1.ClientProxy.name); + const { url } = metadata; + this.url = url || DEFAULT_URL; + } + sendSingleMessage(msg, callback) { + if (!this.pub || !this.sub) { + this.init(); + } + const pattern = JSON.stringify(msg.pattern); + const responseCallback = (channel, message) => { + const { err, response, disposed } = JSON.parse(message); + if (disposed) { + callback(null, null, true); + this.sub.unsubscribe(this.getResPatternName(pattern)); + this.sub.removeListener(MESSAGE_EVENT, responseCallback); + return; + } + callback(err, response); + }; + this.sub.on(MESSAGE_EVENT, responseCallback); + this.sub.subscribe(this.getResPatternName(pattern)); + this.pub.publish(this.getAckPatternName(pattern), JSON.stringify(msg)); + return responseCallback; + } + getAckPatternName(pattern) { + return `${pattern}_ack`; + } + getResPatternName(pattern) { + return `${pattern}_res`; + } + close() { + this.pub && this.pub.quit(); + this.sub && this.sub.quit(); + } + init() { + this.pub = this.createClient(); + this.sub = this.createClient(); + this.handleErrors(this.pub); + this.handleErrors(this.sub); + } + createClient() { + return redis.createClient({ url: this.url }); + } + handleErrors(stream) { + stream.on(ERROR_EVENT, (err) => this.logger.error(err)); + } +} +exports.ClientRedis = ClientRedis; diff --git a/lib/microservices/client/client-tcp.d.ts b/lib/microservices/client/client-tcp.d.ts new file mode 100644 index 00000000000..470d1541105 --- /dev/null +++ b/lib/microservices/client/client-tcp.d.ts @@ -0,0 +1,16 @@ +import { ClientProxy } from './client-proxy'; +import { ClientMetadata } from '../interfaces/client-metadata.interface'; +export declare class ClientTCP extends ClientProxy { + private readonly logger; + private readonly port; + private readonly host; + private isConnected; + private socket; + constructor({port, host}: ClientMetadata); + init(): Promise<{}>; + protected sendSingleMessage(msg: any, callback: (...args) => any): Promise; + handleResponse(socket: any, callback: (...args) => any, buffer: any): void; + createSocket(): any; + close(): void; + bindEvents(socket: any): void; +} diff --git a/lib/microservices/client/client-tcp.js b/lib/microservices/client/client-tcp.js new file mode 100644 index 00000000000..d10dd362b6a --- /dev/null +++ b/lib/microservices/client/client-tcp.js @@ -0,0 +1,81 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const net = require("net"); +const JsonSocket = require("json-socket"); +const client_proxy_1 = require("./client-proxy"); +const common_1 = require("@nestjs/common"); +const DEFAULT_PORT = 3000; +const DEFAULT_HOST = 'localhost'; +const CONNECT_EVENT = 'connect'; +const MESSAGE_EVENT = 'message'; +const ERROR_EVENT = 'error'; +const CLOSE_EVENT = 'close'; +class ClientTCP extends client_proxy_1.ClientProxy { + constructor({ port, host }) { + super(); + this.logger = new common_1.Logger(ClientTCP.name); + this.isConnected = false; + this.port = port || DEFAULT_PORT; + this.host = host || DEFAULT_HOST; + } + init() { + this.socket = this.createSocket(); + return new Promise((resolve) => { + this.socket.on(CONNECT_EVENT, () => { + this.isConnected = true; + this.bindEvents(this.socket); + resolve(this.socket); + }); + this.socket.connect(this.port, this.host); + }); + } + sendSingleMessage(msg, callback) { + return __awaiter(this, void 0, void 0, function* () { + const sendMessage = (socket) => { + socket.sendMessage(msg); + socket.on(MESSAGE_EVENT, (buffer) => this.handleResponse(socket, callback, buffer)); + }; + if (this.isConnected) { + sendMessage(this.socket); + return Promise.resolve(); + } + const socket = yield this.init(); + sendMessage(socket); + }); + } + handleResponse(socket, callback, buffer) { + const { err, response, disposed } = buffer; + if (disposed) { + callback(null, null, true); + socket.end(); + return; + } + callback(err, response); + } + createSocket() { + return new JsonSocket(new net.Socket()); + } + close() { + if (this.socket) { + this.socket.end(); + this.isConnected = false; + this.socket = null; + } + } + bindEvents(socket) { + socket.on(ERROR_EVENT, (err) => this.logger.error(err)); + socket.on(CLOSE_EVENT, () => { + this.isConnected = false; + this.socket = null; + }); + } +} +exports.ClientTCP = ClientTCP; diff --git a/lib/microservices/client/index.d.ts b/lib/microservices/client/index.d.ts new file mode 100644 index 00000000000..d6867e23115 --- /dev/null +++ b/lib/microservices/client/index.d.ts @@ -0,0 +1,2 @@ +export * from './client-proxy'; +export * from './client-proxy-factory'; diff --git a/lib/microservices/client/index.js b/lib/microservices/client/index.js new file mode 100644 index 00000000000..2bc15850e0d --- /dev/null +++ b/lib/microservices/client/index.js @@ -0,0 +1,7 @@ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./client-proxy")); +__export(require("./client-proxy-factory")); diff --git a/lib/microservices/constants.d.ts b/lib/microservices/constants.d.ts new file mode 100644 index 00000000000..37916977e6f --- /dev/null +++ b/lib/microservices/constants.d.ts @@ -0,0 +1,5 @@ +export declare const PATTERN_METADATA = "pattern"; +export declare const CLIENT_CONFIGURATION_METADATA = "client"; +export declare const CLIENT_METADATA = "__isClient"; +export declare const PATTERN_HANDLER_METADATA = "__isPattern"; +export declare const NO_PATTERN_MESSAGE: string; diff --git a/lib/microservices/constants.js b/lib/microservices/constants.js new file mode 100644 index 00000000000..a8f241efc0b --- /dev/null +++ b/lib/microservices/constants.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PATTERN_METADATA = 'pattern'; +exports.CLIENT_CONFIGURATION_METADATA = 'client'; +exports.CLIENT_METADATA = '__isClient'; +exports.PATTERN_HANDLER_METADATA = '__isPattern'; +exports.NO_PATTERN_MESSAGE = `There's no equivalent message pattern.`; diff --git a/lib/microservices/container.d.ts b/lib/microservices/container.d.ts new file mode 100644 index 00000000000..8760c769be6 --- /dev/null +++ b/lib/microservices/container.d.ts @@ -0,0 +1,9 @@ +import { ClientProxy } from './index'; +import { Closeable } from './interfaces/closeable.interface'; +export declare type CloseableClient = Closeable & ClientProxy; +export declare class ClientsContainer { + private clients; + getAllClients(): CloseableClient[]; + addClient(client: CloseableClient): void; + clear(): void; +} diff --git a/lib/microservices/container.js b/lib/microservices/container.js new file mode 100644 index 00000000000..ca568057fc5 --- /dev/null +++ b/lib/microservices/container.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class ClientsContainer { + constructor() { + this.clients = []; + } + getAllClients() { + return this.clients; + } + addClient(client) { + this.clients.push(client); + } + clear() { + this.clients = []; + } +} +exports.ClientsContainer = ClientsContainer; diff --git a/lib/microservices/context/exception-filters-context.d.ts b/lib/microservices/context/exception-filters-context.d.ts new file mode 100644 index 00000000000..c626cb18891 --- /dev/null +++ b/lib/microservices/context/exception-filters-context.d.ts @@ -0,0 +1,12 @@ +import 'reflect-metadata'; +import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface'; +import { Observable } from 'rxjs/Observable'; +import { RpcExceptionsHandler } from '../exceptions/rpc-exceptions-handler'; +import { BaseExceptionFilterContext } from '@nestjs/core/exceptions/base-exception-filter-context'; +import { ApplicationConfig } from '@nestjs/core/application-config'; +export declare class ExceptionFiltersContext extends BaseExceptionFilterContext { + private readonly config; + constructor(config: ApplicationConfig); + create(instance: Controller, callback: (data) => Observable): RpcExceptionsHandler; + getGlobalMetadata(): T; +} diff --git a/lib/microservices/context/exception-filters-context.js b/lib/microservices/context/exception-filters-context.js new file mode 100644 index 00000000000..f68b9ccf498 --- /dev/null +++ b/lib/microservices/context/exception-filters-context.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const rpc_exceptions_handler_1 = require("../exceptions/rpc-exceptions-handler"); +const constants_1 = require("@nestjs/common/constants"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const base_exception_filter_context_1 = require("@nestjs/core/exceptions/base-exception-filter-context"); +class ExceptionFiltersContext extends base_exception_filter_context_1.BaseExceptionFilterContext { + constructor(config) { + super(); + this.config = config; + } + create(instance, callback) { + const exceptionHandler = new rpc_exceptions_handler_1.RpcExceptionsHandler(); + const filters = this.createContext(instance, callback, constants_1.EXCEPTION_FILTERS_METADATA); + if (shared_utils_1.isEmpty(filters)) { + return exceptionHandler; + } + exceptionHandler.setCustomFilters(filters); + return exceptionHandler; + } + getGlobalMetadata() { + return this.config.getGlobalFilters(); + } +} +exports.ExceptionFiltersContext = ExceptionFiltersContext; diff --git a/lib/microservices/context/rpc-context-creator.d.ts b/lib/microservices/context/rpc-context-creator.d.ts new file mode 100644 index 00000000000..e6126b3a65d --- /dev/null +++ b/lib/microservices/context/rpc-context-creator.d.ts @@ -0,0 +1,24 @@ +import { Observable } from 'rxjs/Observable'; +import { RpcProxy } from './rpc-proxy'; +import { ExceptionFiltersContext } from './exception-filters-context'; +import { Controller } from '@nestjs/common/interfaces'; +import { PipesContextCreator } from '@nestjs/core/pipes/pipes-context-creator'; +import { PipesConsumer } from '@nestjs/core/pipes/pipes-consumer'; +import { GuardsContextCreator } from '@nestjs/core/guards/guards-context-creator'; +import { GuardsConsumer } from '@nestjs/core/guards/guards-consumer'; +import { InterceptorsContextCreator } from '@nestjs/core/interceptors/interceptors-context-creator'; +import { InterceptorsConsumer } from '@nestjs/core/interceptors/interceptors-consumer'; +export declare class RpcContextCreator { + private readonly rpcProxy; + private readonly exceptionFiltersContext; + private readonly pipesCreator; + private readonly pipesConsumer; + private readonly guardsContextCreator; + private readonly guardsConsumer; + private readonly interceptorsContextCreator; + private readonly interceptorsConsumer; + constructor(rpcProxy: RpcProxy, exceptionFiltersContext: ExceptionFiltersContext, pipesCreator: PipesContextCreator, pipesConsumer: PipesConsumer, guardsContextCreator: GuardsContextCreator, guardsConsumer: GuardsConsumer, interceptorsContextCreator: InterceptorsContextCreator, interceptorsConsumer: InterceptorsConsumer); + create(instance: Controller, callback: (data) => Observable, module: any): (data) => Promise>; + reflectCallbackParamtypes(instance: Controller, callback: (...args) => any): any[]; + getDataMetatype(instance: any, callback: any): any; +} diff --git a/lib/microservices/context/rpc-context-creator.js b/lib/microservices/context/rpc-context-creator.js new file mode 100644 index 00000000000..181fb9071f0 --- /dev/null +++ b/lib/microservices/context/rpc-context-creator.js @@ -0,0 +1,49 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const constants_1 = require("@nestjs/common/constants"); +const constants_2 = require("@nestjs/core/guards/constants"); +const index_1 = require("../index"); +class RpcContextCreator { + constructor(rpcProxy, exceptionFiltersContext, pipesCreator, pipesConsumer, guardsContextCreator, guardsConsumer, interceptorsContextCreator, interceptorsConsumer) { + this.rpcProxy = rpcProxy; + this.exceptionFiltersContext = exceptionFiltersContext; + this.pipesCreator = pipesCreator; + this.pipesConsumer = pipesConsumer; + this.guardsContextCreator = guardsContextCreator; + this.guardsConsumer = guardsConsumer; + this.interceptorsContextCreator = interceptorsContextCreator; + this.interceptorsConsumer = interceptorsConsumer; + } + create(instance, callback, module) { + const exceptionHandler = this.exceptionFiltersContext.create(instance, callback); + const pipes = this.pipesCreator.create(instance, callback); + const guards = this.guardsContextCreator.create(instance, callback, module); + const metatype = this.getDataMetatype(instance, callback); + const interceptors = this.interceptorsContextCreator.create(instance, callback, module); + return this.rpcProxy.create((data) => __awaiter(this, void 0, void 0, function* () { + const canActivate = yield this.guardsConsumer.tryActivate(guards, data, instance, callback); + if (!canActivate) { + throw new index_1.RpcException(constants_2.FORBIDDEN_MESSAGE); + } + const result = yield this.pipesConsumer.applyPipes(data, { metatype }, pipes); + const handler = () => callback.call(instance, result); + return yield this.interceptorsConsumer.intercept(interceptors, result, instance, callback, handler); + }), exceptionHandler); + } + reflectCallbackParamtypes(instance, callback) { + return Reflect.getMetadata(constants_1.PARAMTYPES_METADATA, instance, callback.name); + } + getDataMetatype(instance, callback) { + const paramtypes = this.reflectCallbackParamtypes(instance, callback); + return paramtypes && paramtypes.length ? paramtypes[0] : null; + } +} +exports.RpcContextCreator = RpcContextCreator; diff --git a/lib/microservices/context/rpc-proxy.d.ts b/lib/microservices/context/rpc-proxy.d.ts new file mode 100644 index 00000000000..1865dd669e2 --- /dev/null +++ b/lib/microservices/context/rpc-proxy.d.ts @@ -0,0 +1,5 @@ +import { Observable } from 'rxjs/Observable'; +import { RpcExceptionsHandler } from '../exceptions/rpc-exceptions-handler'; +export declare class RpcProxy { + create(targetCallback: (data) => Promise>, exceptionsHandler: RpcExceptionsHandler): (data) => Promise>; +} diff --git a/lib/microservices/context/rpc-proxy.js b/lib/microservices/context/rpc-proxy.js new file mode 100644 index 00000000000..e6f488a0c78 --- /dev/null +++ b/lib/microservices/context/rpc-proxy.js @@ -0,0 +1,23 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +class RpcProxy { + create(targetCallback, exceptionsHandler) { + return (data) => __awaiter(this, void 0, void 0, function* () { + try { + return yield targetCallback(data); + } + catch (e) { + return exceptionsHandler.handle(e); + } + }); + } +} +exports.RpcProxy = RpcProxy; diff --git a/lib/microservices/enums/index.d.ts b/lib/microservices/enums/index.d.ts new file mode 100644 index 00000000000..cce3c6aee76 --- /dev/null +++ b/lib/microservices/enums/index.d.ts @@ -0,0 +1 @@ +export * from './transport.enum'; diff --git a/lib/microservices/enums/index.js b/lib/microservices/enums/index.js new file mode 100644 index 00000000000..f4f13b4cdb8 --- /dev/null +++ b/lib/microservices/enums/index.js @@ -0,0 +1,6 @@ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./transport.enum")); diff --git a/lib/microservices/enums/transport.enum.d.ts b/lib/microservices/enums/transport.enum.d.ts new file mode 100644 index 00000000000..5f116ab7c12 --- /dev/null +++ b/lib/microservices/enums/transport.enum.d.ts @@ -0,0 +1,4 @@ +export declare enum Transport { + TCP = 0, + REDIS = 1, +} diff --git a/lib/microservices/enums/transport.enum.js b/lib/microservices/enums/transport.enum.js new file mode 100644 index 00000000000..059d1078e20 --- /dev/null +++ b/lib/microservices/enums/transport.enum.js @@ -0,0 +1,7 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var Transport; +(function (Transport) { + Transport[Transport["TCP"] = 0] = "TCP"; + Transport[Transport["REDIS"] = 1] = "REDIS"; +})(Transport = exports.Transport || (exports.Transport = {})); diff --git a/lib/microservices/exceptions/index.d.ts b/lib/microservices/exceptions/index.d.ts new file mode 100644 index 00000000000..b44d5af56bf --- /dev/null +++ b/lib/microservices/exceptions/index.d.ts @@ -0,0 +1 @@ +export * from './rpc-exception'; diff --git a/lib/microservices/exceptions/index.js b/lib/microservices/exceptions/index.js new file mode 100644 index 00000000000..a406b433c4e --- /dev/null +++ b/lib/microservices/exceptions/index.js @@ -0,0 +1,6 @@ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./rpc-exception")); diff --git a/lib/microservices/exceptions/invalid-message.exception.d.ts b/lib/microservices/exceptions/invalid-message.exception.d.ts new file mode 100644 index 00000000000..0bf90a240f5 --- /dev/null +++ b/lib/microservices/exceptions/invalid-message.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from '@nestjs/core/errors/exceptions/runtime.exception'; +export declare class InvalidMessageException extends RuntimeException { + constructor(); +} diff --git a/lib/microservices/exceptions/invalid-message.exception.js b/lib/microservices/exceptions/invalid-message.exception.js new file mode 100644 index 00000000000..13ca8af5bde --- /dev/null +++ b/lib/microservices/exceptions/invalid-message.exception.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("@nestjs/core/errors/exceptions/runtime.exception"); +class InvalidMessageException extends runtime_exception_1.RuntimeException { + constructor() { + super(`Invalid message pattern or data!`); + } +} +exports.InvalidMessageException = InvalidMessageException; diff --git a/lib/microservices/exceptions/rpc-exception.d.ts b/lib/microservices/exceptions/rpc-exception.d.ts new file mode 100644 index 00000000000..8a8f8d28617 --- /dev/null +++ b/lib/microservices/exceptions/rpc-exception.d.ts @@ -0,0 +1,5 @@ +export declare class RpcException { + private readonly error; + constructor(error: string | object); + getError(): string | object; +} diff --git a/lib/microservices/exceptions/rpc-exception.js b/lib/microservices/exceptions/rpc-exception.js new file mode 100644 index 00000000000..6d8d4785ead --- /dev/null +++ b/lib/microservices/exceptions/rpc-exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class RpcException { + constructor(error) { + this.error = error; + } + getError() { + return this.error; + } +} +exports.RpcException = RpcException; diff --git a/lib/microservices/exceptions/rpc-exceptions-handler.d.ts b/lib/microservices/exceptions/rpc-exceptions-handler.d.ts new file mode 100644 index 00000000000..1a44f352611 --- /dev/null +++ b/lib/microservices/exceptions/rpc-exceptions-handler.d.ts @@ -0,0 +1,10 @@ +import { Observable } from 'rxjs/Observable'; +import { RpcException } from './rpc-exception'; +import { RpcExceptionFilterMetadata } from '@nestjs/common/interfaces/exceptions'; +import 'rxjs/add/observable/throw'; +export declare class RpcExceptionsHandler { + private filters; + handle(exception: Error | RpcException | any): Observable; + setCustomFilters(filters: RpcExceptionFilterMetadata[]): void; + invokeCustomFilters(exception: any): Observable | null; +} diff --git a/lib/microservices/exceptions/rpc-exceptions-handler.js b/lib/microservices/exceptions/rpc-exceptions-handler.js new file mode 100644 index 00000000000..1c29e2b9a40 --- /dev/null +++ b/lib/microservices/exceptions/rpc-exceptions-handler.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const invalid_exception_filter_exception_1 = require("@nestjs/core/errors/exceptions/invalid-exception-filter.exception"); +const constants_1 = require("@nestjs/core/constants"); +const Observable_1 = require("rxjs/Observable"); +const rpc_exception_1 = require("./rpc-exception"); +require("rxjs/add/observable/throw"); +class RpcExceptionsHandler { + constructor() { + this.filters = []; + } + handle(exception) { + const filterResult$ = this.invokeCustomFilters(exception); + if (filterResult$) { + return filterResult$; + } + const status = 'error'; + if (!(exception instanceof rpc_exception_1.RpcException)) { + const message = constants_1.messages.UNKNOWN_EXCEPTION_MESSAGE; + return Observable_1.Observable.throw({ status, message }); + } + const res = exception.getError(); + const message = shared_utils_1.isObject(res) ? res : ({ status, message: res }); + return Observable_1.Observable.throw(message); + } + setCustomFilters(filters) { + if (!Array.isArray(filters)) { + throw new invalid_exception_filter_exception_1.InvalidExceptionFilterException(); + } + this.filters = filters; + } + invokeCustomFilters(exception) { + if (shared_utils_1.isEmpty(this.filters)) + return null; + const filter = this.filters.find(({ exceptionMetatypes, func }) => { + const hasMetatype = !!exceptionMetatypes.find(ExceptionMetatype => exception instanceof ExceptionMetatype); + return hasMetatype; + }); + return filter ? filter.func(exception) : null; + } +} +exports.RpcExceptionsHandler = RpcExceptionsHandler; diff --git a/lib/microservices/index.d.ts b/lib/microservices/index.d.ts new file mode 100644 index 00000000000..6f585b0436b --- /dev/null +++ b/lib/microservices/index.d.ts @@ -0,0 +1,7 @@ +export * from './utils'; +export * from './interfaces'; +export * from './client'; +export * from './enums'; +export * from './server'; +export * from './exceptions'; +export * from './nest-microservice'; diff --git a/lib/microservices/index.js b/lib/microservices/index.js new file mode 100644 index 00000000000..53e2c3d9b03 --- /dev/null +++ b/lib/microservices/index.js @@ -0,0 +1,17 @@ +"use strict"; +/* + * Nest @microservices + * Copyright(c) 2017-... Kamil Mysliwiec + * www.nestjs.com || www.kamilmysliwiec.com + * MIT Licensed + */ +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./utils")); +__export(require("./client")); +__export(require("./enums")); +__export(require("./server")); +__export(require("./exceptions")); +__export(require("./nest-microservice")); diff --git a/lib/microservices/interfaces/client-metadata.interface.d.ts b/lib/microservices/interfaces/client-metadata.interface.d.ts new file mode 100644 index 00000000000..6a9ccb04755 --- /dev/null +++ b/lib/microservices/interfaces/client-metadata.interface.d.ts @@ -0,0 +1,7 @@ +import { Transport } from './../enums/transport.enum'; +export interface ClientMetadata { + transport?: Transport; + url?: string; + port?: number; + host?: string; +} diff --git a/lib/microservices/interfaces/client-metadata.interface.js b/lib/microservices/interfaces/client-metadata.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/microservices/interfaces/client-metadata.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/microservices/interfaces/closeable.interface.d.ts b/lib/microservices/interfaces/closeable.interface.d.ts new file mode 100644 index 00000000000..45097299a8a --- /dev/null +++ b/lib/microservices/interfaces/closeable.interface.d.ts @@ -0,0 +1,3 @@ +export interface Closeable { + close(): void; +} diff --git a/lib/microservices/interfaces/closeable.interface.js b/lib/microservices/interfaces/closeable.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/microservices/interfaces/closeable.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/microservices/interfaces/custom-transport-strategy.interface.d.ts b/lib/microservices/interfaces/custom-transport-strategy.interface.d.ts new file mode 100644 index 00000000000..b743506b902 --- /dev/null +++ b/lib/microservices/interfaces/custom-transport-strategy.interface.d.ts @@ -0,0 +1,4 @@ +export interface CustomTransportStrategy { + listen(callback: () => void): any; + close(): any; +} diff --git a/lib/microservices/interfaces/custom-transport-strategy.interface.js b/lib/microservices/interfaces/custom-transport-strategy.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/microservices/interfaces/custom-transport-strategy.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/microservices/interfaces/index.d.ts b/lib/microservices/interfaces/index.d.ts new file mode 100644 index 00000000000..d385fc445b0 --- /dev/null +++ b/lib/microservices/interfaces/index.d.ts @@ -0,0 +1,7 @@ +export * from './client-metadata.interface'; +export * from './microservice-configuration.interface'; +export * from './pattern-metadata.interface'; +export * from './custom-transport-strategy.interface'; +export * from './message-handlers.interface'; +export * from './microservice-response.interface'; +export * from './closeable.interface'; diff --git a/lib/microservices/interfaces/index.js b/lib/microservices/interfaces/index.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/microservices/interfaces/index.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/microservices/interfaces/message-handlers.interface.d.ts b/lib/microservices/interfaces/message-handlers.interface.d.ts new file mode 100644 index 00000000000..9131cce636f --- /dev/null +++ b/lib/microservices/interfaces/message-handlers.interface.d.ts @@ -0,0 +1,4 @@ +import { Observable } from 'rxjs/Observable'; +export interface MessageHandlers { + [pattern: string]: (data) => Promise>; +} diff --git a/lib/microservices/interfaces/message-handlers.interface.js b/lib/microservices/interfaces/message-handlers.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/microservices/interfaces/message-handlers.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/microservices/interfaces/microservice-configuration.interface.d.ts b/lib/microservices/interfaces/microservice-configuration.interface.d.ts new file mode 100644 index 00000000000..0d515554d8f --- /dev/null +++ b/lib/microservices/interfaces/microservice-configuration.interface.d.ts @@ -0,0 +1,10 @@ +import { Transport } from '../enums/transport.enum'; +import { CustomTransportStrategy } from './custom-transport-strategy.interface'; +import { Server } from './../server/server'; +export interface MicroserviceConfiguration { + transport?: Transport; + url?: string; + port?: number; + host?: string; + strategy?: Server & CustomTransportStrategy; +} diff --git a/lib/microservices/interfaces/microservice-configuration.interface.js b/lib/microservices/interfaces/microservice-configuration.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/microservices/interfaces/microservice-configuration.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/microservices/interfaces/microservice-response.interface.d.ts b/lib/microservices/interfaces/microservice-response.interface.d.ts new file mode 100644 index 00000000000..9040f00b60f --- /dev/null +++ b/lib/microservices/interfaces/microservice-response.interface.d.ts @@ -0,0 +1,5 @@ +export interface MicroserviceResponse { + response?: any; + err?: any; + disposed?: boolean; +} diff --git a/lib/microservices/interfaces/microservice-response.interface.js b/lib/microservices/interfaces/microservice-response.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/microservices/interfaces/microservice-response.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/microservices/interfaces/pattern-metadata.interface.d.ts b/lib/microservices/interfaces/pattern-metadata.interface.d.ts new file mode 100644 index 00000000000..817171de21d --- /dev/null +++ b/lib/microservices/interfaces/pattern-metadata.interface.d.ts @@ -0,0 +1,3 @@ +export interface PatternMetadata { + [prop: string]: any; +} diff --git a/lib/microservices/interfaces/pattern-metadata.interface.js b/lib/microservices/interfaces/pattern-metadata.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/microservices/interfaces/pattern-metadata.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/microservices/listener-metadata-explorer.d.ts b/lib/microservices/listener-metadata-explorer.d.ts new file mode 100644 index 00000000000..cf926686683 --- /dev/null +++ b/lib/microservices/listener-metadata-explorer.d.ts @@ -0,0 +1,19 @@ +import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface'; +import { PatternMetadata } from './interfaces/pattern-metadata.interface'; +import { ClientMetadata } from './interfaces/client-metadata.interface'; +import { MetadataScanner } from '@nestjs/core/metadata-scanner'; +export declare class ListenerMetadataExplorer { + private readonly metadataScanner; + constructor(metadataScanner: MetadataScanner); + explore(instance: Controller): PatternProperties[]; + exploreMethodMetadata(instance: any, instancePrototype: any, methodName: string): PatternProperties; + scanForClientHooks(instance: Controller): IterableIterator; +} +export interface ClientProperties { + property: string; + metadata: ClientMetadata; +} +export interface PatternProperties { + pattern: PatternMetadata; + targetCallback: (...args) => any; +} diff --git a/lib/microservices/listener-metadata-explorer.js b/lib/microservices/listener-metadata-explorer.js new file mode 100644 index 00000000000..e097401948d --- /dev/null +++ b/lib/microservices/listener-metadata-explorer.js @@ -0,0 +1,38 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const constants_1 = require("./constants"); +class ListenerMetadataExplorer { + constructor(metadataScanner) { + this.metadataScanner = metadataScanner; + } + explore(instance) { + const instancePrototype = Object.getPrototypeOf(instance); + return this.metadataScanner.scanFromPrototype(instance, instancePrototype, (method) => this.exploreMethodMetadata(instance, instancePrototype, method)); + } + exploreMethodMetadata(instance, instancePrototype, methodName) { + const targetCallback = instancePrototype[methodName]; + const isPattern = Reflect.getMetadata(constants_1.PATTERN_HANDLER_METADATA, targetCallback); + if (shared_utils_1.isUndefined(isPattern)) { + return null; + } + const pattern = Reflect.getMetadata(constants_1.PATTERN_METADATA, targetCallback); + return { + targetCallback, + pattern, + }; + } + *scanForClientHooks(instance) { + for (const propertyKey in instance) { + if (shared_utils_1.isFunction(propertyKey)) + continue; + const property = String(propertyKey); + const isClient = Reflect.getMetadata(constants_1.CLIENT_METADATA, instance, property); + if (shared_utils_1.isUndefined(isClient)) + continue; + const metadata = Reflect.getMetadata(constants_1.CLIENT_CONFIGURATION_METADATA, instance, property); + yield { property, metadata }; + } + } +} +exports.ListenerMetadataExplorer = ListenerMetadataExplorer; diff --git a/lib/microservices/listeners-controller.d.ts b/lib/microservices/listeners-controller.d.ts new file mode 100644 index 00000000000..4e48632bb89 --- /dev/null +++ b/lib/microservices/listeners-controller.d.ts @@ -0,0 +1,14 @@ +import 'reflect-metadata'; +import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface'; +import { Server } from './server/server'; +import { CustomTransportStrategy } from './interfaces'; +import { ClientsContainer } from './container'; +import { RpcContextCreator } from './context/rpc-context-creator'; +export declare class ListenersController { + private readonly clientsContainer; + private readonly contextCreator; + private readonly metadataExplorer; + constructor(clientsContainer: ClientsContainer, contextCreator: RpcContextCreator); + bindPatternHandlers(instance: Controller, server: Server & CustomTransportStrategy, module: string): void; + bindClientsToProperties(instance: Controller): void; +} diff --git a/lib/microservices/listeners-controller.js b/lib/microservices/listeners-controller.js new file mode 100644 index 00000000000..5f5f6da6f46 --- /dev/null +++ b/lib/microservices/listeners-controller.js @@ -0,0 +1,28 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const listener_metadata_explorer_1 = require("./listener-metadata-explorer"); +const client_proxy_factory_1 = require("./client/client-proxy-factory"); +const metadata_scanner_1 = require("@nestjs/core/metadata-scanner"); +class ListenersController { + constructor(clientsContainer, contextCreator) { + this.clientsContainer = clientsContainer; + this.contextCreator = contextCreator; + this.metadataExplorer = new listener_metadata_explorer_1.ListenerMetadataExplorer(new metadata_scanner_1.MetadataScanner()); + } + bindPatternHandlers(instance, server, module) { + const patternHandlers = this.metadataExplorer.explore(instance); + patternHandlers.forEach(({ pattern, targetCallback }) => { + const proxy = this.contextCreator.create(instance, targetCallback, module); + server.add(pattern, proxy); + }); + } + bindClientsToProperties(instance) { + for (const { property, metadata } of this.metadataExplorer.scanForClientHooks(instance)) { + const client = client_proxy_factory_1.ClientProxyFactory.create(metadata); + this.clientsContainer.addClient(client); + Reflect.set(instance, property, client); + } + } +} +exports.ListenersController = ListenersController; diff --git a/lib/microservices/microservices-module.d.ts b/lib/microservices/microservices-module.d.ts new file mode 100644 index 00000000000..81cd8d6b5f5 --- /dev/null +++ b/lib/microservices/microservices-module.d.ts @@ -0,0 +1,14 @@ +import { InstanceWrapper } from '@nestjs/core/injector/container'; +import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface'; +import { CustomTransportStrategy } from './interfaces'; +import { Server } from './server/server'; +export declare class MicroservicesModule { + private readonly clientsContainer; + private listenersController; + setup(container: any, config: any): void; + setupListeners(container: any, server: Server & CustomTransportStrategy): void; + setupClients(container: any): void; + bindListeners(controllers: Map>, server: Server & CustomTransportStrategy, module: string): void; + bindClients(controllers: Map>): void; + close(): void; +} diff --git a/lib/microservices/microservices-module.js b/lib/microservices/microservices-module.js new file mode 100644 index 00000000000..348feef811f --- /dev/null +++ b/lib/microservices/microservices-module.js @@ -0,0 +1,56 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const listeners_controller_1 = require("./listeners-controller"); +const container_1 = require("./container"); +const rpc_context_creator_1 = require("./context/rpc-context-creator"); +const rpc_proxy_1 = require("./context/rpc-proxy"); +const exception_filters_context_1 = require("./context/exception-filters-context"); +const pipes_context_creator_1 = require("@nestjs/core/pipes/pipes-context-creator"); +const pipes_consumer_1 = require("@nestjs/core/pipes/pipes-consumer"); +const guards_context_creator_1 = require("@nestjs/core/guards/guards-context-creator"); +const runtime_exception_1 = require("@nestjs/core/errors/exceptions/runtime.exception"); +const guards_consumer_1 = require("@nestjs/core/guards/guards-consumer"); +const interceptors_context_creator_1 = require("@nestjs/core/interceptors/interceptors-context-creator"); +const interceptors_consumer_1 = require("@nestjs/core/interceptors/interceptors-consumer"); +class MicroservicesModule { + constructor() { + this.clientsContainer = new container_1.ClientsContainer(); + } + setup(container, config) { + const contextCreator = new rpc_context_creator_1.RpcContextCreator(new rpc_proxy_1.RpcProxy(), new exception_filters_context_1.ExceptionFiltersContext(config), new pipes_context_creator_1.PipesContextCreator(config), new pipes_consumer_1.PipesConsumer(), new guards_context_creator_1.GuardsContextCreator(container, config), new guards_consumer_1.GuardsConsumer(), new interceptors_context_creator_1.InterceptorsContextCreator(container, config), new interceptors_consumer_1.InterceptorsConsumer()); + this.listenersController = new listeners_controller_1.ListenersController(this.clientsContainer, contextCreator); + } + setupListeners(container, server) { + if (!this.listenersController) { + throw new runtime_exception_1.RuntimeException(); + } + const modules = container.getModules(); + modules.forEach(({ routes }, module) => this.bindListeners(routes, server, module)); + } + setupClients(container) { + if (!this.listenersController) { + throw new runtime_exception_1.RuntimeException(); + } + const modules = container.getModules(); + modules.forEach(({ routes, components }) => { + this.bindClients(routes); + this.bindClients(components); + }); + } + bindListeners(controllers, server, module) { + controllers.forEach(({ instance }) => { + this.listenersController.bindPatternHandlers(instance, server, module); + }); + } + bindClients(controllers) { + controllers.forEach(({ instance, isNotMetatype }) => { + !isNotMetatype && this.listenersController.bindClientsToProperties(instance); + }); + } + close() { + const clients = this.clientsContainer.getAllClients(); + clients.forEach((client) => client.close()); + this.clientsContainer.clear(); + } +} +exports.MicroservicesModule = MicroservicesModule; diff --git a/lib/microservices/nest-microservice.d.ts b/lib/microservices/nest-microservice.d.ts new file mode 100644 index 00000000000..b216d98d2f9 --- /dev/null +++ b/lib/microservices/nest-microservice.d.ts @@ -0,0 +1,35 @@ +import { NestContainer } from '@nestjs/core/injector/container'; +import { MicroserviceConfiguration } from './interfaces/microservice-configuration.interface'; +import { INestMicroservice, WebSocketAdapter, CanActivate, PipeTransform, NestInterceptor, ExceptionFilter } from '@nestjs/common'; +export declare class NestMicroservice implements INestMicroservice { + private readonly container; + private readonly logger; + private readonly microservicesModule; + private readonly socketModule; + private readonly microserviceConfig; + private readonly server; + private readonly config; + private isTerminated; + private isInitialized; + private isInitHookCalled; + constructor(container: NestContainer, config?: MicroserviceConfiguration); + setupModules(): void; + setupListeners(): void; + useWebSocketAdapter(adapter: WebSocketAdapter): void; + useGlobalFilters(...filters: ExceptionFilter[]): void; + useGlobalPipes(...pipes: PipeTransform[]): void; + useGlobalInterceptors(...interceptors: NestInterceptor[]): void; + useGlobalGuards(...guards: CanActivate[]): void; + listen(callback: () => void): void; + close(): void; + setIsInitialized(isInitialized: boolean): void; + setIsTerminated(isTerminaed: boolean): void; + setIsInitHookCalled(isInitHookCalled: boolean): void; + private closeApplication(); + private callInitHook(); + private callModuleInitHook(module); + private hasOnModuleInitHook(instance); + private callDestroyHook(); + private callModuleDestroyHook(module); + private hasOnModuleDestroyHook(instance); +} diff --git a/lib/microservices/nest-microservice.js b/lib/microservices/nest-microservice.js new file mode 100644 index 00000000000..5e4b6a8e8e2 --- /dev/null +++ b/lib/microservices/nest-microservice.js @@ -0,0 +1,114 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const optional = require("optional"); +const iterare_1 = require("iterare"); +const microservices_module_1 = require("./microservices-module"); +const constants_1 = require("@nestjs/core/constants"); +const logger_service_1 = require("@nestjs/common/services/logger.service"); +const server_factory_1 = require("./server/server-factory"); +const transport_enum_1 = require("./enums/transport.enum"); +const application_config_1 = require("@nestjs/core/application-config"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const { SocketModule } = optional('@nestjs/websockets/socket-module') || {}; +const { IoAdapter } = optional('@nestjs/websockets/adapters/io-adapter') || {}; +class NestMicroservice { + constructor(container, config = {}) { + this.container = container; + this.logger = new logger_service_1.Logger(NestMicroservice.name, true); + this.microservicesModule = new microservices_module_1.MicroservicesModule(); + this.socketModule = SocketModule + ? new SocketModule() + : null; + this.isTerminated = false; + this.isInitialized = false; + this.isInitHookCalled = false; + const ioAdapter = IoAdapter ? new IoAdapter() : null; + this.config = new application_config_1.ApplicationConfig(ioAdapter); + this.microservicesModule.setup(container, this.config); + this.microserviceConfig = Object.assign({ transport: transport_enum_1.Transport.TCP }, config); + const { strategy } = config; + this.server = strategy ? strategy : server_factory_1.ServerFactory.create(this.microserviceConfig); + } + setupModules() { + this.socketModule && this.socketModule.setup(this.container, this.config); + this.microservicesModule.setupClients(this.container); + this.setupListeners(); + this.setIsInitialized(true); + !this.isInitHookCalled && this.callInitHook(); + } + setupListeners() { + this.microservicesModule.setupListeners(this.container, this.server); + } + useWebSocketAdapter(adapter) { + this.config.setIoAdapter(adapter); + } + useGlobalFilters(...filters) { + this.config.useGlobalFilters(...filters); + } + useGlobalPipes(...pipes) { + this.config.useGlobalPipes(...pipes); + } + useGlobalInterceptors(...interceptors) { + this.config.useGlobalInterceptors(...interceptors); + } + useGlobalGuards(...guards) { + this.config.useGlobalGuards(...guards); + } + listen(callback) { + (!this.isInitialized) && this.setupModules(); + this.logger.log(constants_1.messages.MICROSERVICE_READY); + this.server.listen(callback); + } + close() { + this.server.close(); + !this.isTerminated && this.closeApplication(); + } + setIsInitialized(isInitialized) { + this.isInitialized = isInitialized; + } + setIsTerminated(isTerminaed) { + this.isTerminated = isTerminaed; + } + setIsInitHookCalled(isInitHookCalled) { + this.isInitHookCalled = isInitHookCalled; + } + closeApplication() { + this.socketModule && this.socketModule.close(); + this.callDestroyHook(); + this.setIsTerminated(true); + } + callInitHook() { + const modules = this.container.getModules(); + modules.forEach((module) => { + this.callModuleInitHook(module); + }); + this.setIsInitHookCalled(true); + } + callModuleInitHook(module) { + const components = [...module.routes, ...module.components]; + iterare_1.default(components).map(([key, { instance }]) => instance) + .filter((instance) => !shared_utils_1.isNil(instance)) + .filter(this.hasOnModuleInitHook) + .forEach((instance) => instance.onModuleInit()); + } + hasOnModuleInitHook(instance) { + return !shared_utils_1.isUndefined(instance.onModuleInit); + } + callDestroyHook() { + const modules = this.container.getModules(); + modules.forEach((module) => { + this.callModuleDestroyHook(module); + }); + } + callModuleDestroyHook(module) { + const components = [...module.routes, ...module.components]; + iterare_1.default(components).map(([key, { instance }]) => instance) + .filter((instance) => !shared_utils_1.isNil(instance)) + .filter(this.hasOnModuleDestroyHook) + .forEach((instance) => instance.onModuleDestroy()); + } + hasOnModuleDestroyHook(instance) { + return !shared_utils_1.isUndefined(instance.onModuleDestroy); + } +} +exports.NestMicroservice = NestMicroservice; diff --git a/lib/microservices/server/index.d.ts b/lib/microservices/server/index.d.ts new file mode 100644 index 00000000000..0ce5251aa32 --- /dev/null +++ b/lib/microservices/server/index.d.ts @@ -0,0 +1 @@ +export * from './server'; diff --git a/lib/microservices/server/index.js b/lib/microservices/server/index.js new file mode 100644 index 00000000000..d380db1ddc5 --- /dev/null +++ b/lib/microservices/server/index.js @@ -0,0 +1,6 @@ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./server")); diff --git a/lib/microservices/server/server-factory.d.ts b/lib/microservices/server/server-factory.d.ts new file mode 100644 index 00000000000..be4251a337f --- /dev/null +++ b/lib/microservices/server/server-factory.d.ts @@ -0,0 +1,5 @@ +import { MicroserviceConfiguration, CustomTransportStrategy } from '../interfaces'; +import { Server } from './server'; +export declare class ServerFactory { + static create(config: MicroserviceConfiguration): Server & CustomTransportStrategy; +} diff --git a/lib/microservices/server/server-factory.js b/lib/microservices/server/server-factory.js new file mode 100644 index 00000000000..3a165ef39b0 --- /dev/null +++ b/lib/microservices/server/server-factory.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const server_tcp_1 = require("./server-tcp"); +const server_redis_1 = require("./server-redis"); +const transport_enum_1 = require("../enums/transport.enum"); +class ServerFactory { + static create(config) { + const { transport } = config; + switch (transport) { + case transport_enum_1.Transport.REDIS: return new server_redis_1.ServerRedis(config); + default: return new server_tcp_1.ServerTCP(config); + } + } +} +exports.ServerFactory = ServerFactory; diff --git a/lib/microservices/server/server-redis.d.ts b/lib/microservices/server/server-redis.d.ts new file mode 100644 index 00000000000..419d2e755c4 --- /dev/null +++ b/lib/microservices/server/server-redis.d.ts @@ -0,0 +1,25 @@ +import * as redis from 'redis'; +import { Server } from './server'; +import { MicroserviceConfiguration } from '../interfaces/microservice-configuration.interface'; +import { CustomTransportStrategy } from './../interfaces'; +import 'rxjs/add/operator/catch'; +import 'rxjs/add/observable/empty'; +import 'rxjs/add/operator/finally'; +export declare class ServerRedis extends Server implements CustomTransportStrategy { + private readonly url; + private sub; + private pub; + constructor(config: MicroserviceConfiguration); + listen(callback: () => void): void; + start(callback?: () => void): void; + close(): void; + createRedisClient(): redis.RedisClient; + handleConnection(callback: any, sub: any, pub: any): void; + getMessageHandler(pub: any): (channel: any, buffer: any) => Promise; + handleMessage(channel: any, buffer: any, pub: any): Promise; + getPublisher(pub: any, pattern: any): (respond: any) => void; + tryParse(content: any): any; + getAckQueueName(pattern: any): string; + getResQueueName(pattern: any): string; + handleErrors(stream: any): void; +} diff --git a/lib/microservices/server/server-redis.js b/lib/microservices/server/server-redis.js new file mode 100644 index 00000000000..53ce228a432 --- /dev/null +++ b/lib/microservices/server/server-redis.js @@ -0,0 +1,92 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const redis = require("redis"); +const server_1 = require("./server"); +const constants_1 = require("../constants"); +require("rxjs/add/operator/catch"); +require("rxjs/add/observable/empty"); +require("rxjs/add/operator/finally"); +const DEFAULT_URL = 'redis://localhost:6379'; +const CONNECT_EVENT = 'connect'; +const MESSAGE_EVENT = 'message'; +const ERROR_EVENT = 'error'; +class ServerRedis extends server_1.Server { + constructor(config) { + super(); + this.sub = null; + this.pub = null; + this.url = config.url || DEFAULT_URL; + } + listen(callback) { + this.sub = this.createRedisClient(); + this.pub = this.createRedisClient(); + this.handleErrors(this.pub); + this.handleErrors(this.sub); + this.start(callback); + } + start(callback) { + this.sub.on(CONNECT_EVENT, () => this.handleConnection(callback, this.sub, this.pub)); + } + close() { + this.pub && this.pub.quit(); + this.sub && this.sub.quit(); + } + createRedisClient() { + return redis.createClient({ url: this.url }); + } + handleConnection(callback, sub, pub) { + sub.on(MESSAGE_EVENT, this.getMessageHandler(pub).bind(this)); + const patterns = Object.keys(this.messageHandlers); + patterns.forEach((pattern) => sub.subscribe(this.getAckQueueName(pattern))); + callback && callback(); + } + getMessageHandler(pub) { + return (channel, buffer) => __awaiter(this, void 0, void 0, function* () { return yield this.handleMessage(channel, buffer, pub); }); + } + handleMessage(channel, buffer, pub) { + return __awaiter(this, void 0, void 0, function* () { + const msg = this.tryParse(buffer); + const pattern = channel.replace(/_ack$/, ''); + const publish = this.getPublisher(pub, pattern); + const status = 'error'; + if (!this.messageHandlers[pattern]) { + publish({ status, error: constants_1.NO_PATTERN_MESSAGE }); + return; + } + const handler = this.messageHandlers[pattern]; + const response$ = this.transformToObservable(yield handler(msg.data)); + response$ && this.send(response$, publish); + }); + } + getPublisher(pub, pattern) { + return (respond) => { + pub.publish(this.getResQueueName(pattern), JSON.stringify(respond)); + }; + } + tryParse(content) { + try { + return JSON.parse(content); + } + catch (e) { + return content; + } + } + getAckQueueName(pattern) { + return `${pattern}_ack`; + } + getResQueueName(pattern) { + return `${pattern}_res`; + } + handleErrors(stream) { + stream.on(ERROR_EVENT, (err) => this.logger.error(err)); + } +} +exports.ServerRedis = ServerRedis; diff --git a/lib/microservices/server/server-tcp.d.ts b/lib/microservices/server/server-tcp.d.ts new file mode 100644 index 00000000000..c94b29ad082 --- /dev/null +++ b/lib/microservices/server/server-tcp.d.ts @@ -0,0 +1,19 @@ +import { Server } from './server'; +import { CustomTransportStrategy } from './../interfaces'; +import 'rxjs/add/operator/catch'; +import 'rxjs/add/observable/empty'; +import 'rxjs/add/operator/finally'; +export declare class ServerTCP extends Server implements CustomTransportStrategy { + private readonly port; + private server; + constructor(config: any); + listen(callback: () => void): void; + close(): void; + bindHandler(socket: any): void; + handleMessage(socket: any, msg: { + pattern: any; + data: {}; + }): Promise; + private init(); + private getSocketInstance(socket); +} diff --git a/lib/microservices/server/server-tcp.js b/lib/microservices/server/server-tcp.js new file mode 100644 index 00000000000..636d6ec7ae1 --- /dev/null +++ b/lib/microservices/server/server-tcp.js @@ -0,0 +1,58 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const net = require("net"); +const JsonSocket = require("json-socket"); +const constants_1 = require("../constants"); +const server_1 = require("./server"); +require("rxjs/add/operator/catch"); +require("rxjs/add/observable/empty"); +require("rxjs/add/operator/finally"); +const DEFAULT_PORT = 3000; +const MESSAGE_EVENT = 'message'; +const ERROR_EVENT = 'error'; +class ServerTCP extends server_1.Server { + constructor(config) { + super(); + this.port = config.port || DEFAULT_PORT; + this.init(); + } + listen(callback) { + this.server.listen(this.port, callback); + } + close() { + this.server.close(); + } + bindHandler(socket) { + const sock = this.getSocketInstance(socket); + sock.on(MESSAGE_EVENT, (msg) => __awaiter(this, void 0, void 0, function* () { return yield this.handleMessage(sock, msg); })); + } + handleMessage(socket, msg) { + return __awaiter(this, void 0, void 0, function* () { + const pattern = JSON.stringify(msg.pattern); + const status = 'error'; + if (!this.messageHandlers[pattern]) { + socket.sendMessage({ status, error: constants_1.NO_PATTERN_MESSAGE }); + return; + } + const handler = this.messageHandlers[pattern]; + const response$ = this.transformToObservable(yield handler(msg.data)); + response$ && this.send(response$, socket.sendMessage.bind(socket)); + }); + } + init() { + this.server = net.createServer(this.bindHandler.bind(this)); + this.server.on(ERROR_EVENT, this.handleError.bind(this)); + } + getSocketInstance(socket) { + return new JsonSocket(socket); + } +} +exports.ServerTCP = ServerTCP; diff --git a/lib/microservices/server/server.d.ts b/lib/microservices/server/server.d.ts new file mode 100644 index 00000000000..22c7a10dd42 --- /dev/null +++ b/lib/microservices/server/server.d.ts @@ -0,0 +1,19 @@ +import { Logger } from '@nestjs/common/services/logger.service'; +import { MessageHandlers } from '../interfaces/message-handlers.interface'; +import { Observable } from 'rxjs/Observable'; +import { MicroserviceResponse } from '../index'; +import { Subscription } from 'rxjs/Subscription'; +import 'rxjs/add/operator/catch'; +import 'rxjs/add/operator/finally'; +import 'rxjs/add/observable/empty'; +import 'rxjs/add/observable/of'; +import 'rxjs/add/observable/fromPromise'; +export declare abstract class Server { + protected readonly messageHandlers: MessageHandlers; + protected readonly logger: Logger; + getHandlers(): MessageHandlers; + add(pattern: any, callback: (data) => Promise>): void; + send(stream$: Observable, respond: (data: MicroserviceResponse) => void): Subscription; + transformToObservable(resultOrDeffered: any): Observable; + protected handleError(error: string): void; +} diff --git a/lib/microservices/server/server.js b/lib/microservices/server/server.js new file mode 100644 index 00000000000..c2e77880f38 --- /dev/null +++ b/lib/microservices/server/server.js @@ -0,0 +1,42 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const logger_service_1 = require("@nestjs/common/services/logger.service"); +const Observable_1 = require("rxjs/Observable"); +require("rxjs/add/operator/catch"); +require("rxjs/add/operator/finally"); +require("rxjs/add/observable/empty"); +require("rxjs/add/observable/of"); +require("rxjs/add/observable/fromPromise"); +class Server { + constructor() { + this.messageHandlers = {}; + this.logger = new logger_service_1.Logger(Server.name); + } + getHandlers() { + return this.messageHandlers; + } + add(pattern, callback) { + this.messageHandlers[JSON.stringify(pattern)] = callback; + } + send(stream$, respond) { + return stream$.catch((err) => { + respond({ err, response: null }); + return Observable_1.Observable.empty(); + }) + .finally(() => respond({ disposed: true })) + .subscribe((response) => respond({ err: null, response })); + } + transformToObservable(resultOrDeffered) { + if (resultOrDeffered instanceof Promise) { + return Observable_1.Observable.fromPromise(resultOrDeffered); + } + else if (!(resultOrDeffered instanceof Observable_1.Observable)) { + return Observable_1.Observable.of(resultOrDeffered); + } + return resultOrDeffered; + } + handleError(error) { + this.logger.error(error); + } +} +exports.Server = Server; diff --git a/lib/microservices/utils/client.decorator.d.ts b/lib/microservices/utils/client.decorator.d.ts new file mode 100644 index 00000000000..31ffc195a66 --- /dev/null +++ b/lib/microservices/utils/client.decorator.d.ts @@ -0,0 +1,13 @@ +import 'reflect-metadata'; +import { ClientMetadata } from '../interfaces/client-metadata.interface'; +/** + * Attaches the `ClientProxy` instance to the given property + * + * @param {ClientMetadata} metadata Optional client metadata + * ``` + * transport?: Transport; + * url?: string; + * port?: number; + * host?: string; + */ +export declare const Client: (metadata?: ClientMetadata) => (target: object, propertyKey: string | symbol) => void; diff --git a/lib/microservices/utils/client.decorator.js b/lib/microservices/utils/client.decorator.js new file mode 100644 index 00000000000..681a27194d0 --- /dev/null +++ b/lib/microservices/utils/client.decorator.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("../constants"); +/** + * Attaches the `ClientProxy` instance to the given property + * + * @param {ClientMetadata} metadata Optional client metadata + * ``` + * transport?: Transport; + * url?: string; + * port?: number; + * host?: string; + */ +exports.Client = (metadata) => { + return (target, propertyKey) => { + Reflect.set(target, propertyKey, null); + Reflect.defineMetadata(constants_1.CLIENT_METADATA, true, target, propertyKey); + Reflect.defineMetadata(constants_1.CLIENT_CONFIGURATION_METADATA, metadata, target, propertyKey); + }; +}; diff --git a/lib/microservices/utils/index.d.ts b/lib/microservices/utils/index.d.ts new file mode 100644 index 00000000000..e357597db85 --- /dev/null +++ b/lib/microservices/utils/index.d.ts @@ -0,0 +1,2 @@ +export * from './client.decorator'; +export * from './pattern.decorator'; diff --git a/lib/microservices/utils/index.js b/lib/microservices/utils/index.js new file mode 100644 index 00000000000..f924421a403 --- /dev/null +++ b/lib/microservices/utils/index.js @@ -0,0 +1,7 @@ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./client.decorator")); +__export(require("./pattern.decorator")); diff --git a/lib/microservices/utils/pattern.decorator.d.ts b/lib/microservices/utils/pattern.decorator.d.ts new file mode 100644 index 00000000000..fb99bc2c0f1 --- /dev/null +++ b/lib/microservices/utils/pattern.decorator.d.ts @@ -0,0 +1,6 @@ +import 'reflect-metadata'; +import { PatternMetadata } from '../interfaces/pattern-metadata.interface'; +/** + * Subscribes to the messages, which fulfils chosen pattern. + */ +export declare const MessagePattern: (metadata?: string | PatternMetadata) => MethodDecorator; diff --git a/lib/microservices/utils/pattern.decorator.js b/lib/microservices/utils/pattern.decorator.js new file mode 100644 index 00000000000..7787cc131dd --- /dev/null +++ b/lib/microservices/utils/pattern.decorator.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("../constants"); +/** + * Subscribes to the messages, which fulfils chosen pattern. + */ +exports.MessagePattern = (metadata) => { + return (target, key, descriptor) => { + Reflect.defineMetadata(constants_1.PATTERN_METADATA, metadata, descriptor.value); + Reflect.defineMetadata(constants_1.PATTERN_HANDLER_METADATA, true, descriptor.value); + return descriptor; + }; +}; diff --git a/lib/testing/LICENSE b/lib/testing/LICENSE new file mode 100644 index 00000000000..be7581ff84f --- /dev/null +++ b/lib/testing/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2017 Kamil Myƛliwiec + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/testing/Readme.md b/lib/testing/Readme.md new file mode 100644 index 00000000000..280bd354356 --- /dev/null +++ b/lib/testing/Readme.md @@ -0,0 +1,125 @@ +

    + Nest Logo +

    + +[travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master +[travis-url]: https://travis-ci.org/nestjs/nest +[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux +[linux-url]: https://travis-ci.org/nestjs/nest + +

    A progressive Node.js framework for building efficient and scalable web applications. :cat:

    +

    +NPM Version +Package License +NPM Downloads +Travis +Linux +Coverage +Gitter +Backers on Open Collective +Sponsors on Open Collective +

    + + +## Description + +

    Nest is a framework for building efficient, scalable Node.js web applications. It uses modern JavaScript, is built with TypeScript (preserves compatibility with pure JavaScript) and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reactive Programming).

    +

    Under the hood, Nest makes use of Express, allowing for easy use of the myriad third-party plugins which are available.

    + +## Philosophy + +

    In recent years, thanks to Node.js, JavaScript has become the “lingua franca” of the web for both front and backend applications, giving rise to awesome projects like Angular, React and Vue which improve developer productivity and enable the construction of fast, testable, extensible frontend applications. However, on the server-side, while there are a lot of superb libraries, helpers and tools for Node, none of them effectively solve the main problem - the architecture.

    +

    Nest aims to provide an application architecture out of the box which allows for effortless creation of highly testable, scalable, loosely coupled and easily maintainable applications.

    + +## Features + +
      +
    • Built with TypeScript (compatible with pure JavaScript + Babel)
    • +
    • Easy to learn - syntax similar to Angular
    • +
    • Familiar - based on well-known libraries (Express / socket.io)
    • +
    • Dependency Injection - built-in asynchronous IoC container with a hierarchical injector
    • +
    • WebSockets module (based on socket.io, but you can bring your own library, by making use of WsAdapter)
    • +
    • Modular - defines an easy to follow module definition pattern so you can split your system into reusable modules
    • +
    • Reactive microservice support with message patterns (built-in transport via TCP / Redis, but other communication schemes can be implemented with CustomTransportStrategy)
    • +
    • Exception layer - throwable web exceptions with status codes, exception filters
    • +
    • Pipes - synchronous & asynchronous (e.g. validation purposes)
    • +
    • Guards - attach additional logic in a declarative manner (e.g. role-based access control)
    • +
    • Interceptors - built on top of RxJS
    • +
    • Testing utilities (both e2e & unit tests)
    • +
    + +## Installation + +**Install the TypeScript Starter Project with Git:** +```bash +$ git clone https://github.com/nestjs/typescript-starter.git project +$ cd project +$ npm install +$ npm run start +``` + +**Install the JavaScript (Babel) Starter Project with Git:** +```bash +$ git clone https://github.com/nestjs/javascript-starter.git project +$ cd project +$ npm install +$ npm run start +``` + +**Start a New Project from Scratch with NPM:** +```bash +$ npm i --save @nestjs/core @nestjs/common @nestjs/microservices @nestjs/websockets @nestjs/testing reflect-metadata rxjs +``` + +## Documentation & Quick Start + +:books: [Documentation & Tutorial](https://docs.nestjs.com) + +## Sponsors + + + +## Backers + +I am on a mission to provide an architecture to create truly flexible, scalable and loosely coupled systems using the Node.js platform. It takes a lot of time, so if you want to support me, please [become a backer / sponsor]((https://opencollective.com/nest#backer)). I appreciate your help. Thanks! :heart_eyes: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## People + +- Author - [Kamil Myƛliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) + +## License + + [MIT](LICENSE) diff --git a/lib/testing/errors/unknown-module.exception.d.ts b/lib/testing/errors/unknown-module.exception.d.ts new file mode 100644 index 00000000000..086aa145aad --- /dev/null +++ b/lib/testing/errors/unknown-module.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from '@nestjs/core/errors/exceptions/runtime.exception'; +export declare class UnknownModuleException extends RuntimeException { + constructor(); +} diff --git a/lib/testing/errors/unknown-module.exception.js b/lib/testing/errors/unknown-module.exception.js new file mode 100644 index 00000000000..6aaa26507fe --- /dev/null +++ b/lib/testing/errors/unknown-module.exception.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("@nestjs/core/errors/exceptions/runtime.exception"); +class UnknownModuleException extends runtime_exception_1.RuntimeException { + constructor() { + super(); + } +} +exports.UnknownModuleException = UnknownModuleException; diff --git a/lib/testing/index.d.ts b/lib/testing/index.d.ts new file mode 100644 index 00000000000..41c8707363d --- /dev/null +++ b/lib/testing/index.d.ts @@ -0,0 +1,2 @@ +export * from './interfaces'; +export * from './test'; diff --git a/lib/testing/index.js b/lib/testing/index.js new file mode 100644 index 00000000000..8cb6ad4d7fa --- /dev/null +++ b/lib/testing/index.js @@ -0,0 +1,12 @@ +"use strict"; +/* + * Nest @testing + * Copyright(c) 2017-... Kamil Mysliwiec + * www.nestjs.com || www.kamilmysliwiec.com + * MIT Licensed + */ +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./test")); diff --git a/lib/testing/interfaces/index.d.ts b/lib/testing/interfaces/index.d.ts new file mode 100644 index 00000000000..33f61d966c8 --- /dev/null +++ b/lib/testing/interfaces/index.d.ts @@ -0,0 +1,2 @@ +export * from './override-by-factory-options.interface'; +export * from './override-by.interface'; diff --git a/lib/testing/interfaces/index.js b/lib/testing/interfaces/index.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/testing/interfaces/index.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/testing/interfaces/override-by-factory-options.interface.d.ts b/lib/testing/interfaces/override-by-factory-options.interface.d.ts new file mode 100644 index 00000000000..87bffb82d28 --- /dev/null +++ b/lib/testing/interfaces/override-by-factory-options.interface.d.ts @@ -0,0 +1,4 @@ +export interface OverrideByFactoryOptions { + factory: (...args) => any; + inject?: any[]; +} diff --git a/lib/testing/interfaces/override-by-factory-options.interface.js b/lib/testing/interfaces/override-by-factory-options.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/testing/interfaces/override-by-factory-options.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/testing/interfaces/override-by.interface.d.ts b/lib/testing/interfaces/override-by.interface.d.ts new file mode 100644 index 00000000000..3e4447fdc80 --- /dev/null +++ b/lib/testing/interfaces/override-by.interface.d.ts @@ -0,0 +1,7 @@ +import { OverrideByFactoryOptions } from './override-by-factory-options.interface'; +import { TestingModuleBuilder } from '../testing-module.builder'; +export interface OverrideBy { + useValue: (value) => TestingModuleBuilder; + useFactory: (options: OverrideByFactoryOptions) => TestingModuleBuilder; + useClass: (metatype) => TestingModuleBuilder; +} diff --git a/lib/testing/interfaces/override-by.interface.js b/lib/testing/interfaces/override-by.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/testing/interfaces/override-by.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/testing/test.d.ts b/lib/testing/test.d.ts new file mode 100644 index 00000000000..bebc805af2e --- /dev/null +++ b/lib/testing/test.d.ts @@ -0,0 +1,7 @@ +import { ModuleMetadata } from '@nestjs/common/interfaces/modules/module-metadata.interface'; +import { TestingModuleBuilder } from './testing-module.builder'; +export declare class Test { + private static metadataScanner; + static createTestingModule(metadata: ModuleMetadata): TestingModuleBuilder; + private static init(); +} diff --git a/lib/testing/test.js b/lib/testing/test.js new file mode 100644 index 00000000000..4da1e7b9d15 --- /dev/null +++ b/lib/testing/test.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const logger_service_1 = require("@nestjs/common/services/logger.service"); +const nest_environment_enum_1 = require("@nestjs/common/enums/nest-environment.enum"); +const metadata_scanner_1 = require("@nestjs/core/metadata-scanner"); +const testing_module_builder_1 = require("./testing-module.builder"); +class Test { + static createTestingModule(metadata) { + this.init(); + return new testing_module_builder_1.TestingModuleBuilder(this.metadataScanner, metadata); + } + static init() { + logger_service_1.Logger.setMode(nest_environment_enum_1.NestEnvironment.TEST); + } +} +Test.metadataScanner = new metadata_scanner_1.MetadataScanner(); +exports.Test = Test; diff --git a/lib/testing/testing-module.builder.d.ts b/lib/testing/testing-module.builder.d.ts new file mode 100644 index 00000000000..f6c85cb7b3d --- /dev/null +++ b/lib/testing/testing-module.builder.d.ts @@ -0,0 +1,19 @@ +import { OverrideBy } from './interfaces'; +import { MetadataScanner } from '@nestjs/core/metadata-scanner'; +import { ModuleMetadata } from '@nestjs/common/interfaces'; +import { TestingModule } from './testing-module'; +export declare class TestingModuleBuilder { + private readonly container; + private readonly overloadsMap; + private readonly scanner; + private readonly instanceLoader; + private readonly module; + constructor(metadataScanner: MetadataScanner, metadata: ModuleMetadata); + overrideGuard(typeOrToken: any): OverrideBy; + overrideInterceptor(typeOrToken: any): OverrideBy; + overrideComponent(typeOrToken: any): OverrideBy; + compile(): Promise; + private override(typeOrToken, isComponent); + private createOverrideByBuilder(add); + private createModule(metadata); +} diff --git a/lib/testing/testing-module.builder.js b/lib/testing/testing-module.builder.js new file mode 100644 index 00000000000..0a8e477dab4 --- /dev/null +++ b/lib/testing/testing-module.builder.js @@ -0,0 +1,66 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const instance_loader_1 = require("@nestjs/core/injector/instance-loader"); +const container_1 = require("@nestjs/core/injector/container"); +const common_1 = require("@nestjs/common"); +const scanner_1 = require("@nestjs/core/scanner"); +const testing_module_1 = require("./testing-module"); +class TestingModuleBuilder { + constructor(metadataScanner, metadata) { + this.container = new container_1.NestContainer(); + this.overloadsMap = new Map(); + this.instanceLoader = new instance_loader_1.InstanceLoader(this.container); + this.scanner = new scanner_1.DependenciesScanner(this.container, metadataScanner); + this.module = this.createModule(metadata); + this.scanner.scan(this.module); + } + overrideGuard(typeOrToken) { + return this.override(typeOrToken, false); + } + overrideInterceptor(typeOrToken) { + return this.override(typeOrToken, false); + } + overrideComponent(typeOrToken) { + return this.override(typeOrToken, true); + } + compile() { + return __awaiter(this, void 0, void 0, function* () { + [...this.overloadsMap.entries()].map(([component, options]) => { + this.container.replace(component, options); + }); + yield this.instanceLoader.createInstancesOfDependencies(); + const modules = this.container.getModules().values(); + const root = modules.next().value; + return new testing_module_1.TestingModule(this.container, [], root); + }); + } + override(typeOrToken, isComponent) { + const addOverload = (options) => { + this.overloadsMap.set(typeOrToken, Object.assign({}, options, { isComponent })); + return this; + }; + return this.createOverrideByBuilder(addOverload); + } + createOverrideByBuilder(add) { + return { + useValue: (value) => add({ useValue: value }), + useFactory: (options) => add(Object.assign({}, options, { useFactory: options.factory })), + useClass: (metatype) => add({ useClass: metatype }), + }; + } + createModule(metadata) { + class TestModule { + } + common_1.Module(metadata)(TestModule); + return TestModule; + } +} +exports.TestingModuleBuilder = TestingModuleBuilder; diff --git a/lib/testing/testing-module.d.ts b/lib/testing/testing-module.d.ts new file mode 100644 index 00000000000..0738e6e39f0 --- /dev/null +++ b/lib/testing/testing-module.d.ts @@ -0,0 +1,10 @@ +import { NestContainer } from '@nestjs/core/injector/container'; +import { NestModuleMetatype } from '@nestjs/common/interfaces/modules/module-metatype.interface'; +import { NestApplicationContext } from '@nestjs/core'; +import { INestApplication, INestMicroservice } from '@nestjs/common'; +import { MicroserviceConfiguration } from '@nestjs/common/interfaces/microservices/microservice-configuration.interface'; +export declare class TestingModule extends NestApplicationContext { + constructor(container: NestContainer, scope: NestModuleMetatype[], contextModule: any); + createNestApplication(express?: any): INestApplication; + createNestMicroservice(config: MicroserviceConfiguration): INestMicroservice; +} diff --git a/lib/testing/testing-module.js b/lib/testing/testing-module.js new file mode 100644 index 00000000000..4a3d50d969c --- /dev/null +++ b/lib/testing/testing-module.js @@ -0,0 +1,21 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const optional = require("optional"); +const core_1 = require("@nestjs/core"); +const microservices_package_not_found_exception_1 = require("@nestjs/core/errors/exceptions/microservices-package-not-found.exception"); +const { NestMicroservice } = optional('@nestjs/microservices/nest-microservice') || {}; +class TestingModule extends core_1.NestApplicationContext { + constructor(container, scope, contextModule) { + super(container, scope, contextModule); + } + createNestApplication(express) { + return new core_1.NestApplication(this.container, express); + } + createNestMicroservice(config) { + if (!NestMicroservice) { + throw new microservices_package_not_found_exception_1.MicroservicesPackageNotFoundException(); + } + return new NestMicroservice(this.container, config); + } +} +exports.TestingModule = TestingModule; diff --git a/lib/websockets/LICENSE b/lib/websockets/LICENSE new file mode 100644 index 00000000000..be7581ff84f --- /dev/null +++ b/lib/websockets/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2017 Kamil Myƛliwiec + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/websockets/Readme.md b/lib/websockets/Readme.md new file mode 100644 index 00000000000..280bd354356 --- /dev/null +++ b/lib/websockets/Readme.md @@ -0,0 +1,125 @@ +

    + Nest Logo +

    + +[travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master +[travis-url]: https://travis-ci.org/nestjs/nest +[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux +[linux-url]: https://travis-ci.org/nestjs/nest + +

    A progressive Node.js framework for building efficient and scalable web applications. :cat:

    +

    +NPM Version +Package License +NPM Downloads +Travis +Linux +Coverage +Gitter +Backers on Open Collective +Sponsors on Open Collective +

    + + +## Description + +

    Nest is a framework for building efficient, scalable Node.js web applications. It uses modern JavaScript, is built with TypeScript (preserves compatibility with pure JavaScript) and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reactive Programming).

    +

    Under the hood, Nest makes use of Express, allowing for easy use of the myriad third-party plugins which are available.

    + +## Philosophy + +

    In recent years, thanks to Node.js, JavaScript has become the “lingua franca” of the web for both front and backend applications, giving rise to awesome projects like Angular, React and Vue which improve developer productivity and enable the construction of fast, testable, extensible frontend applications. However, on the server-side, while there are a lot of superb libraries, helpers and tools for Node, none of them effectively solve the main problem - the architecture.

    +

    Nest aims to provide an application architecture out of the box which allows for effortless creation of highly testable, scalable, loosely coupled and easily maintainable applications.

    + +## Features + +
      +
    • Built with TypeScript (compatible with pure JavaScript + Babel)
    • +
    • Easy to learn - syntax similar to Angular
    • +
    • Familiar - based on well-known libraries (Express / socket.io)
    • +
    • Dependency Injection - built-in asynchronous IoC container with a hierarchical injector
    • +
    • WebSockets module (based on socket.io, but you can bring your own library, by making use of WsAdapter)
    • +
    • Modular - defines an easy to follow module definition pattern so you can split your system into reusable modules
    • +
    • Reactive microservice support with message patterns (built-in transport via TCP / Redis, but other communication schemes can be implemented with CustomTransportStrategy)
    • +
    • Exception layer - throwable web exceptions with status codes, exception filters
    • +
    • Pipes - synchronous & asynchronous (e.g. validation purposes)
    • +
    • Guards - attach additional logic in a declarative manner (e.g. role-based access control)
    • +
    • Interceptors - built on top of RxJS
    • +
    • Testing utilities (both e2e & unit tests)
    • +
    + +## Installation + +**Install the TypeScript Starter Project with Git:** +```bash +$ git clone https://github.com/nestjs/typescript-starter.git project +$ cd project +$ npm install +$ npm run start +``` + +**Install the JavaScript (Babel) Starter Project with Git:** +```bash +$ git clone https://github.com/nestjs/javascript-starter.git project +$ cd project +$ npm install +$ npm run start +``` + +**Start a New Project from Scratch with NPM:** +```bash +$ npm i --save @nestjs/core @nestjs/common @nestjs/microservices @nestjs/websockets @nestjs/testing reflect-metadata rxjs +``` + +## Documentation & Quick Start + +:books: [Documentation & Tutorial](https://docs.nestjs.com) + +## Sponsors + + + +## Backers + +I am on a mission to provide an architecture to create truly flexible, scalable and loosely coupled systems using the Node.js platform. It takes a lot of time, so if you want to support me, please [become a backer / sponsor]((https://opencollective.com/nest#backer)). I appreciate your help. Thanks! :heart_eyes: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## People + +- Author - [Kamil Myƛliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) + +## License + + [MIT](LICENSE) diff --git a/lib/websockets/adapters/io-adapter.d.ts b/lib/websockets/adapters/io-adapter.d.ts new file mode 100644 index 00000000000..23bf24a62cb --- /dev/null +++ b/lib/websockets/adapters/io-adapter.d.ts @@ -0,0 +1,21 @@ +/// +/// +import { Server } from 'http'; +import { MessageMappingProperties } from '../gateway-metadata-explorer'; +import { WebSocketAdapter } from '@nestjs/common'; +import { Observable } from 'rxjs/Observable'; +import 'rxjs/add/observable/fromEvent'; +import 'rxjs/add/operator/switchMap'; +import 'rxjs/add/operator/filter'; +import 'rxjs/add/operator/do'; +export declare class IoAdapter implements WebSocketAdapter { + private readonly httpServer; + constructor(httpServer?: Server | null); + create(port: number): SocketIO.Server; + createWithNamespace(port: number, namespace: string): SocketIO.Namespace; + createIOServer(port: number): SocketIO.Server; + bindClientConnect(server: any, callback: (...args) => void): void; + bindClientDisconnect(client: any, callback: (...args) => void): void; + bindMessageHandlers(client: any, handlers: MessageMappingProperties[], process: (data: any) => Observable): void; + bindMiddleware(server: any, middleware: (socket, next) => void): void; +} diff --git a/lib/websockets/adapters/io-adapter.js b/lib/websockets/adapters/io-adapter.js new file mode 100644 index 00000000000..749e2712d2a --- /dev/null +++ b/lib/websockets/adapters/io-adapter.js @@ -0,0 +1,42 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const io = require("socket.io"); +const constants_1 = require("../constants"); +const Observable_1 = require("rxjs/Observable"); +require("rxjs/add/observable/fromEvent"); +require("rxjs/add/operator/switchMap"); +require("rxjs/add/operator/filter"); +require("rxjs/add/operator/do"); +class IoAdapter { + constructor(httpServer = null) { + this.httpServer = httpServer; + } + create(port) { + return this.createIOServer(port); + } + createWithNamespace(port, namespace) { + return this.createIOServer(port).of(namespace); + } + createIOServer(port) { + if (this.httpServer && port === 0) { + return io.listen(this.httpServer); + } + return io(port); + } + bindClientConnect(server, callback) { + server.on(constants_1.CONNECTION_EVENT, callback); + } + bindClientDisconnect(client, callback) { + client.on(constants_1.DISCONNECT_EVENT, callback); + } + bindMessageHandlers(client, handlers, process) { + handlers.forEach(({ message, callback }) => Observable_1.Observable.fromEvent(client, message) + .switchMap((data) => process(callback(data))) + .filter((result) => !!result && result.event) + .subscribe(({ event, data }) => client.emit(event, data))); + } + bindMiddleware(server, middleware) { + server.use(middleware); + } +} +exports.IoAdapter = IoAdapter; diff --git a/lib/websockets/constants.d.ts b/lib/websockets/constants.d.ts new file mode 100644 index 00000000000..04528be1a90 --- /dev/null +++ b/lib/websockets/constants.d.ts @@ -0,0 +1,9 @@ +export declare const MESSAGE_MAPPING_METADATA = "__isMessageMapping"; +export declare const MESSAGE_METADATA = "message"; +export declare const GATEWAY_SERVER_METADATA = "__isSocketServer"; +export declare const GATEWAY_METADATA = "__isGateway"; +export declare const NAMESPACE_METADATA = "namespace"; +export declare const PORT_METADATA = "port"; +export declare const GATEWAY_MIDDLEWARES = "__gatewayMiddlewares"; +export declare const CONNECTION_EVENT = "connection"; +export declare const DISCONNECT_EVENT = "disconnect"; diff --git a/lib/websockets/constants.js b/lib/websockets/constants.js new file mode 100644 index 00000000000..41cc1f0572a --- /dev/null +++ b/lib/websockets/constants.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MESSAGE_MAPPING_METADATA = '__isMessageMapping'; +exports.MESSAGE_METADATA = 'message'; +exports.GATEWAY_SERVER_METADATA = '__isSocketServer'; +exports.GATEWAY_METADATA = '__isGateway'; +exports.NAMESPACE_METADATA = 'namespace'; +exports.PORT_METADATA = 'port'; +exports.GATEWAY_MIDDLEWARES = '__gatewayMiddlewares'; +exports.CONNECTION_EVENT = 'connection'; +exports.DISCONNECT_EVENT = 'disconnect'; diff --git a/lib/websockets/container.d.ts b/lib/websockets/container.d.ts new file mode 100644 index 00000000000..c357ee8f2e3 --- /dev/null +++ b/lib/websockets/container.d.ts @@ -0,0 +1,8 @@ +import { ObservableSocketServer } from './interfaces'; +export declare class SocketsContainer { + private readonly observableServers; + getAllServers(): Map; + getServer(namespace: string, port: number): ObservableSocketServer; + addServer(namespace: string, port: number, server: ObservableSocketServer): void; + clear(): void; +} diff --git a/lib/websockets/container.js b/lib/websockets/container.js new file mode 100644 index 00000000000..1411d655bf1 --- /dev/null +++ b/lib/websockets/container.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class SocketsContainer { + constructor() { + this.observableServers = new Map(); + } + getAllServers() { + return this.observableServers; + } + getServer(namespace, port) { + return this.observableServers.get(`${namespace}:${port}`); + } + addServer(namespace, port, server) { + this.observableServers.set(`${namespace}:${port}`, server); + } + clear() { + this.observableServers.clear(); + } +} +exports.SocketsContainer = SocketsContainer; diff --git a/lib/websockets/context/exception-filters-context.d.ts b/lib/websockets/context/exception-filters-context.d.ts new file mode 100644 index 00000000000..77683487b9f --- /dev/null +++ b/lib/websockets/context/exception-filters-context.d.ts @@ -0,0 +1,8 @@ +import 'reflect-metadata'; +import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface'; +import { BaseExceptionFilterContext } from '@nestjs/core/exceptions/base-exception-filter-context'; +import { WsExceptionsHandler } from '../exceptions/ws-exceptions-handler'; +export declare class ExceptionFiltersContext extends BaseExceptionFilterContext { + create(instance: Controller, callback: (client, data) => any): WsExceptionsHandler; + getGlobalMetadata(): T; +} diff --git a/lib/websockets/context/exception-filters-context.js b/lib/websockets/context/exception-filters-context.js new file mode 100644 index 00000000000..67214a932b3 --- /dev/null +++ b/lib/websockets/context/exception-filters-context.js @@ -0,0 +1,22 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("@nestjs/common/constants"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const base_exception_filter_context_1 = require("@nestjs/core/exceptions/base-exception-filter-context"); +const ws_exceptions_handler_1 = require("../exceptions/ws-exceptions-handler"); +class ExceptionFiltersContext extends base_exception_filter_context_1.BaseExceptionFilterContext { + create(instance, callback) { + const exceptionHandler = new ws_exceptions_handler_1.WsExceptionsHandler(); + const filters = this.createContext(instance, callback, constants_1.EXCEPTION_FILTERS_METADATA); + if (shared_utils_1.isEmpty(filters)) { + return exceptionHandler; + } + exceptionHandler.setCustomFilters(filters); + return exceptionHandler; + } + getGlobalMetadata() { + return []; + } +} +exports.ExceptionFiltersContext = ExceptionFiltersContext; diff --git a/lib/websockets/context/ws-context-creator.d.ts b/lib/websockets/context/ws-context-creator.d.ts new file mode 100644 index 00000000000..f1737bcd975 --- /dev/null +++ b/lib/websockets/context/ws-context-creator.d.ts @@ -0,0 +1,23 @@ +import { WsProxy } from './ws-proxy'; +import { ExceptionFiltersContext } from './exception-filters-context'; +import { Controller } from '@nestjs/common/interfaces'; +import { PipesContextCreator } from '@nestjs/core/pipes/pipes-context-creator'; +import { PipesConsumer } from '@nestjs/core/pipes/pipes-consumer'; +import { GuardsContextCreator } from '@nestjs/core/guards/guards-context-creator'; +import { GuardsConsumer } from '@nestjs/core/guards/guards-consumer'; +import { InterceptorsConsumer } from '@nestjs/core/interceptors/interceptors-consumer'; +import { InterceptorsContextCreator } from '@nestjs/core/interceptors/interceptors-context-creator'; +export declare class WsContextCreator { + private readonly wsProxy; + private readonly exceptionFiltersContext; + private readonly pipesCreator; + private readonly pipesConsumer; + private readonly guardsContextCreator; + private readonly guardsConsumer; + private readonly interceptorsContextCreator; + private readonly interceptorsConsumer; + constructor(wsProxy: WsProxy, exceptionFiltersContext: ExceptionFiltersContext, pipesCreator: PipesContextCreator, pipesConsumer: PipesConsumer, guardsContextCreator: GuardsContextCreator, guardsConsumer: GuardsConsumer, interceptorsContextCreator: InterceptorsContextCreator, interceptorsConsumer: InterceptorsConsumer); + create(instance: Controller, callback: (client, data) => void, module: any): (client, data) => Promise; + reflectCallbackParamtypes(instance: Controller, callback: (...args) => any): any[]; + getDataMetatype(instance: any, callback: any): any; +} diff --git a/lib/websockets/context/ws-context-creator.js b/lib/websockets/context/ws-context-creator.js new file mode 100644 index 00000000000..b718b9fd50c --- /dev/null +++ b/lib/websockets/context/ws-context-creator.js @@ -0,0 +1,49 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const constants_1 = require("@nestjs/common/constants"); +const constants_2 = require("@nestjs/core/guards/constants"); +const ws_exception_1 = require("../exceptions/ws-exception"); +class WsContextCreator { + constructor(wsProxy, exceptionFiltersContext, pipesCreator, pipesConsumer, guardsContextCreator, guardsConsumer, interceptorsContextCreator, interceptorsConsumer) { + this.wsProxy = wsProxy; + this.exceptionFiltersContext = exceptionFiltersContext; + this.pipesCreator = pipesCreator; + this.pipesConsumer = pipesConsumer; + this.guardsContextCreator = guardsContextCreator; + this.guardsConsumer = guardsConsumer; + this.interceptorsContextCreator = interceptorsContextCreator; + this.interceptorsConsumer = interceptorsConsumer; + } + create(instance, callback, module) { + const exceptionHandler = this.exceptionFiltersContext.create(instance, callback); + const pipes = this.pipesCreator.create(instance, callback); + const guards = this.guardsContextCreator.create(instance, callback, module); + const metatype = this.getDataMetatype(instance, callback); + const interceptors = this.interceptorsContextCreator.create(instance, callback, module); + return this.wsProxy.create((client, data) => __awaiter(this, void 0, void 0, function* () { + const canActivate = yield this.guardsConsumer.tryActivate(guards, data, instance, callback); + if (!canActivate) { + throw new ws_exception_1.WsException(constants_2.FORBIDDEN_MESSAGE); + } + const result = yield this.pipesConsumer.applyPipes(data, { metatype }, pipes); + const handler = () => callback.call(instance, client, data); + return yield this.interceptorsConsumer.intercept(interceptors, result, instance, callback, handler); + }), exceptionHandler); + } + reflectCallbackParamtypes(instance, callback) { + return Reflect.getMetadata(constants_1.PARAMTYPES_METADATA, instance, callback.name); + } + getDataMetatype(instance, callback) { + const paramtypes = this.reflectCallbackParamtypes(instance, callback); + return paramtypes && paramtypes.length ? paramtypes[1] : null; + } +} +exports.WsContextCreator = WsContextCreator; diff --git a/lib/websockets/context/ws-proxy.d.ts b/lib/websockets/context/ws-proxy.d.ts new file mode 100644 index 00000000000..1b1a63e6cb1 --- /dev/null +++ b/lib/websockets/context/ws-proxy.d.ts @@ -0,0 +1,4 @@ +import { WsExceptionsHandler } from './../exceptions/ws-exceptions-handler'; +export declare class WsProxy { + create(targetCallback: (client, data) => Promise, exceptionsHandler: WsExceptionsHandler): (client, data) => Promise; +} diff --git a/lib/websockets/context/ws-proxy.js b/lib/websockets/context/ws-proxy.js new file mode 100644 index 00000000000..2bbaf7235c2 --- /dev/null +++ b/lib/websockets/context/ws-proxy.js @@ -0,0 +1,23 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +class WsProxy { + create(targetCallback, exceptionsHandler) { + return (client, data) => __awaiter(this, void 0, void 0, function* () { + try { + return yield targetCallback(client, data); + } + catch (e) { + exceptionsHandler.handle(e, client); + } + }); + } +} +exports.WsProxy = WsProxy; diff --git a/lib/websockets/exceptions/invalid-socket-port.exception.d.ts b/lib/websockets/exceptions/invalid-socket-port.exception.d.ts new file mode 100644 index 00000000000..0bccb046771 --- /dev/null +++ b/lib/websockets/exceptions/invalid-socket-port.exception.d.ts @@ -0,0 +1,4 @@ +import { RuntimeException } from '@nestjs/core/errors/exceptions/runtime.exception'; +export declare class InvalidSocketPortException extends RuntimeException { + constructor(port: any, type: any); +} diff --git a/lib/websockets/exceptions/invalid-socket-port.exception.js b/lib/websockets/exceptions/invalid-socket-port.exception.js new file mode 100644 index 00000000000..13652864056 --- /dev/null +++ b/lib/websockets/exceptions/invalid-socket-port.exception.js @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const runtime_exception_1 = require("@nestjs/core/errors/exceptions/runtime.exception"); +class InvalidSocketPortException extends runtime_exception_1.RuntimeException { + constructor(port, type) { + super(`Invalid port (${port}) in Gateway ${type}!`); + } +} +exports.InvalidSocketPortException = InvalidSocketPortException; diff --git a/lib/websockets/exceptions/ws-exception.d.ts b/lib/websockets/exceptions/ws-exception.d.ts new file mode 100644 index 00000000000..a5a5071d768 --- /dev/null +++ b/lib/websockets/exceptions/ws-exception.d.ts @@ -0,0 +1,5 @@ +export declare class WsException { + private readonly error; + constructor(error: string | object); + getError(): string | object; +} diff --git a/lib/websockets/exceptions/ws-exception.js b/lib/websockets/exceptions/ws-exception.js new file mode 100644 index 00000000000..a2e85259449 --- /dev/null +++ b/lib/websockets/exceptions/ws-exception.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class WsException { + constructor(error) { + this.error = error; + } + getError() { + return this.error; + } +} +exports.WsException = WsException; diff --git a/lib/websockets/exceptions/ws-exceptions-handler.d.ts b/lib/websockets/exceptions/ws-exceptions-handler.d.ts new file mode 100644 index 00000000000..fc5ed7416fb --- /dev/null +++ b/lib/websockets/exceptions/ws-exceptions-handler.d.ts @@ -0,0 +1,8 @@ +import { ExceptionFilterMetadata } from '@nestjs/common/interfaces/exceptions/exception-filter-metadata.interface'; +import { WsException } from '../exceptions/ws-exception'; +export declare class WsExceptionsHandler { + private filters; + handle(exception: Error | WsException | any, client: any): any; + setCustomFilters(filters: ExceptionFilterMetadata[]): void; + invokeCustomFilters(exception: any, client: any): boolean; +} diff --git a/lib/websockets/exceptions/ws-exceptions-handler.js b/lib/websockets/exceptions/ws-exceptions-handler.js new file mode 100644 index 00000000000..c91fd51b92f --- /dev/null +++ b/lib/websockets/exceptions/ws-exceptions-handler.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const constants_1 = require("@nestjs/core/constants"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const invalid_exception_filter_exception_1 = require("@nestjs/core/errors/exceptions/invalid-exception-filter.exception"); +const ws_exception_1 = require("../exceptions/ws-exception"); +class WsExceptionsHandler { + constructor() { + this.filters = []; + } + handle(exception, client) { + if (this.invokeCustomFilters(exception, client) || !client.emit) + return; + const status = 'error'; + if (!(exception instanceof ws_exception_1.WsException)) { + const message = constants_1.messages.UNKNOWN_EXCEPTION_MESSAGE; + return client.emit('exception', { status, message }); + } + const result = exception.getError(); + const message = shared_utils_1.isObject(result) ? result : ({ + status, + message: result, + }); + client.emit('exception', message); + } + setCustomFilters(filters) { + if (!Array.isArray(filters)) { + throw new invalid_exception_filter_exception_1.InvalidExceptionFilterException(); + } + this.filters = filters; + } + invokeCustomFilters(exception, client) { + if (shared_utils_1.isEmpty(this.filters)) + return false; + const filter = this.filters.find(({ exceptionMetatypes, func }) => { + const hasMetatype = !!exceptionMetatypes.find(ExceptionMetatype => exception instanceof ExceptionMetatype); + return hasMetatype; + }); + filter && filter.func(exception, client); + return !!filter; + } +} +exports.WsExceptionsHandler = WsExceptionsHandler; diff --git a/lib/websockets/gateway-metadata-explorer.d.ts b/lib/websockets/gateway-metadata-explorer.d.ts new file mode 100644 index 00000000000..f3fbfe5d98f --- /dev/null +++ b/lib/websockets/gateway-metadata-explorer.d.ts @@ -0,0 +1,14 @@ +import { NestGateway } from './interfaces/nest-gateway.interface'; +import { MetadataScanner } from '@nestjs/core/metadata-scanner'; +import { Observable } from 'rxjs/Observable'; +export declare class GatewayMetadataExplorer { + private readonly metadataScanner; + constructor(metadataScanner: MetadataScanner); + explore(instance: NestGateway): MessageMappingProperties[]; + exploreMethodMetadata(instancePrototype: any, methodName: string): MessageMappingProperties; + scanForServerHooks(instance: NestGateway): IterableIterator; +} +export interface MessageMappingProperties { + message: string; + callback: (...args) => Observable | Promise | void; +} diff --git a/lib/websockets/gateway-metadata-explorer.js b/lib/websockets/gateway-metadata-explorer.js new file mode 100644 index 00000000000..a5372904f0b --- /dev/null +++ b/lib/websockets/gateway-metadata-explorer.js @@ -0,0 +1,37 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +const constants_1 = require("./constants"); +class GatewayMetadataExplorer { + constructor(metadataScanner) { + this.metadataScanner = metadataScanner; + } + explore(instance) { + const instancePrototype = Object.getPrototypeOf(instance); + return this.metadataScanner.scanFromPrototype(instance, instancePrototype, (method) => this.exploreMethodMetadata(instancePrototype, method)); + } + exploreMethodMetadata(instancePrototype, methodName) { + const callback = instancePrototype[methodName]; + const isMessageMapping = Reflect.getMetadata(constants_1.MESSAGE_MAPPING_METADATA, callback); + if (shared_utils_1.isUndefined(isMessageMapping)) { + return null; + } + const message = Reflect.getMetadata(constants_1.MESSAGE_METADATA, callback); + return { + callback, + message, + }; + } + *scanForServerHooks(instance) { + for (const propertyKey in instance) { + if (shared_utils_1.isFunction(propertyKey)) + continue; + const property = String(propertyKey); + const isServer = Reflect.getMetadata(constants_1.GATEWAY_SERVER_METADATA, instance, property); + if (shared_utils_1.isUndefined(isServer)) + continue; + yield property; + } + } +} +exports.GatewayMetadataExplorer = GatewayMetadataExplorer; diff --git a/lib/websockets/index.d.ts b/lib/websockets/index.d.ts new file mode 100644 index 00000000000..5af7fe70176 --- /dev/null +++ b/lib/websockets/index.d.ts @@ -0,0 +1,5 @@ +export * from './adapters/io-adapter'; +export * from './interfaces'; +export * from './exceptions/ws-exception'; +export * from './utils'; +export { MessageMappingProperties } from './gateway-metadata-explorer'; diff --git a/lib/websockets/index.js b/lib/websockets/index.js new file mode 100644 index 00000000000..792736f3703 --- /dev/null +++ b/lib/websockets/index.js @@ -0,0 +1,14 @@ +"use strict"; +/* + * Nest @websockets + * Copyright(c) 2017-... Kamil Mysliwiec + * www.nestjs.com || www.kamilmysliwiec.com + * MIT Licensed + */ +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./adapters/io-adapter")); +__export(require("./exceptions/ws-exception")); +__export(require("./utils")); diff --git a/lib/websockets/interfaces/gateway-metadata.interface.d.ts b/lib/websockets/interfaces/gateway-metadata.interface.d.ts new file mode 100644 index 00000000000..dca57bb6116 --- /dev/null +++ b/lib/websockets/interfaces/gateway-metadata.interface.d.ts @@ -0,0 +1,7 @@ +import { Metatype } from '@nestjs/common/interfaces/metatype.interface'; +import { GatewayMiddleware } from './gateway-middleware.interface'; +export interface GatewayMetadata { + port?: number; + namespace?: string; + middlewares?: Metatype[]; +} diff --git a/lib/websockets/interfaces/gateway-metadata.interface.js b/lib/websockets/interfaces/gateway-metadata.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/websockets/interfaces/gateway-metadata.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/websockets/interfaces/gateway-middleware.interface.d.ts b/lib/websockets/interfaces/gateway-middleware.interface.d.ts new file mode 100644 index 00000000000..e3cea273e1e --- /dev/null +++ b/lib/websockets/interfaces/gateway-middleware.interface.d.ts @@ -0,0 +1,3 @@ +export interface GatewayMiddleware { + resolve(): (socket, next) => void; +} diff --git a/lib/websockets/interfaces/gateway-middleware.interface.js b/lib/websockets/interfaces/gateway-middleware.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/websockets/interfaces/gateway-middleware.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/websockets/interfaces/index.d.ts b/lib/websockets/interfaces/index.d.ts new file mode 100644 index 00000000000..93616cd3c5e --- /dev/null +++ b/lib/websockets/interfaces/index.d.ts @@ -0,0 +1,9 @@ +export * from './gateway-metadata.interface'; +export * from './nest-gateway.interface'; +export * from './observable-socket-server.interface'; +export * from './web-socket-server.interface'; +export * from './on-gateway-init.interface'; +export * from './on-gateway-connection.interface'; +export * from './on-gateway-disconnect.interface'; +export * from './gateway-middleware.interface'; +export * from './ws-response.interface'; diff --git a/lib/websockets/interfaces/index.js b/lib/websockets/interfaces/index.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/websockets/interfaces/index.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/websockets/interfaces/nest-gateway.interface.d.ts b/lib/websockets/interfaces/nest-gateway.interface.d.ts new file mode 100644 index 00000000000..51b96ee1671 --- /dev/null +++ b/lib/websockets/interfaces/nest-gateway.interface.d.ts @@ -0,0 +1,5 @@ +export interface NestGateway { + afterInit?: (server: any) => void; + handleConnection?: (client: any) => void; + handleDisconnect?: (client: any) => void; +} diff --git a/lib/websockets/interfaces/nest-gateway.interface.js b/lib/websockets/interfaces/nest-gateway.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/websockets/interfaces/nest-gateway.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/websockets/interfaces/observable-socket-server.interface.d.ts b/lib/websockets/interfaces/observable-socket-server.interface.d.ts new file mode 100644 index 00000000000..4ee67465647 --- /dev/null +++ b/lib/websockets/interfaces/observable-socket-server.interface.d.ts @@ -0,0 +1,8 @@ +import { ReplaySubject } from 'rxjs/ReplaySubject'; +import { Subject } from 'rxjs/Subject'; +export interface ObservableSocketServer { + server: any; + init: ReplaySubject; + connection: Subject; + disconnect: Subject; +} diff --git a/lib/websockets/interfaces/observable-socket-server.interface.js b/lib/websockets/interfaces/observable-socket-server.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/websockets/interfaces/observable-socket-server.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/websockets/interfaces/on-gateway-connection.interface.d.ts b/lib/websockets/interfaces/on-gateway-connection.interface.d.ts new file mode 100644 index 00000000000..a7daeb395a5 --- /dev/null +++ b/lib/websockets/interfaces/on-gateway-connection.interface.d.ts @@ -0,0 +1,3 @@ +export interface OnGatewayConnection { + handleConnection(client: any): any; +} diff --git a/lib/websockets/interfaces/on-gateway-connection.interface.js b/lib/websockets/interfaces/on-gateway-connection.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/websockets/interfaces/on-gateway-connection.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/websockets/interfaces/on-gateway-disconnect.interface.d.ts b/lib/websockets/interfaces/on-gateway-disconnect.interface.d.ts new file mode 100644 index 00000000000..f71c0cfae93 --- /dev/null +++ b/lib/websockets/interfaces/on-gateway-disconnect.interface.d.ts @@ -0,0 +1,3 @@ +export interface OnGatewayDisconnect { + handleDisconnect(client: any): any; +} diff --git a/lib/websockets/interfaces/on-gateway-disconnect.interface.js b/lib/websockets/interfaces/on-gateway-disconnect.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/websockets/interfaces/on-gateway-disconnect.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/websockets/interfaces/on-gateway-init.interface.d.ts b/lib/websockets/interfaces/on-gateway-init.interface.d.ts new file mode 100644 index 00000000000..0e4521cddb8 --- /dev/null +++ b/lib/websockets/interfaces/on-gateway-init.interface.d.ts @@ -0,0 +1,3 @@ +export interface OnGatewayInit { + afterInit(server: any): any; +} diff --git a/lib/websockets/interfaces/on-gateway-init.interface.js b/lib/websockets/interfaces/on-gateway-init.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/websockets/interfaces/on-gateway-init.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/websockets/interfaces/web-socket-server.interface.d.ts b/lib/websockets/interfaces/web-socket-server.interface.d.ts new file mode 100644 index 00000000000..cfaa6414cbb --- /dev/null +++ b/lib/websockets/interfaces/web-socket-server.interface.d.ts @@ -0,0 +1,4 @@ +export interface WebSocketServerData { + port: number; + namespace: string; +} diff --git a/lib/websockets/interfaces/web-socket-server.interface.js b/lib/websockets/interfaces/web-socket-server.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/websockets/interfaces/web-socket-server.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/websockets/interfaces/ws-response.interface.d.ts b/lib/websockets/interfaces/ws-response.interface.d.ts new file mode 100644 index 00000000000..5c7710b08c2 --- /dev/null +++ b/lib/websockets/interfaces/ws-response.interface.d.ts @@ -0,0 +1,4 @@ +export interface WsResponse { + event: string; + data: T; +} diff --git a/lib/websockets/interfaces/ws-response.interface.js b/lib/websockets/interfaces/ws-response.interface.js new file mode 100644 index 00000000000..c8ad2e549bd --- /dev/null +++ b/lib/websockets/interfaces/ws-response.interface.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/lib/websockets/middlewares-injector.d.ts b/lib/websockets/middlewares-injector.d.ts new file mode 100644 index 00000000000..e6b4f369300 --- /dev/null +++ b/lib/websockets/middlewares-injector.d.ts @@ -0,0 +1,16 @@ +import 'reflect-metadata'; +import { NestContainer, InstanceWrapper } from '@nestjs/core/injector/container'; +import { NestGateway } from './index'; +import { Injectable } from '@nestjs/common/interfaces/injectable.interface'; +import { GatewayMiddleware } from './interfaces/gateway-middleware.interface'; +import { ApplicationConfig } from '@nestjs/core/application-config'; +export declare class MiddlewaresInjector { + private readonly container; + private readonly config; + constructor(container: NestContainer, config: ApplicationConfig); + inject(server: any, instance: NestGateway, module: string): void; + reflectMiddlewaresTokens(instance: NestGateway): any[]; + applyMiddlewares(server: any, components: Map>, tokens: any[]): void; + bindMiddleware(token: string, components: Map>): any; + isGatewayMiddleware(middleware: object): middleware is GatewayMiddleware; +} diff --git a/lib/websockets/middlewares-injector.js b/lib/websockets/middlewares-injector.js new file mode 100644 index 00000000000..2d966eae21c --- /dev/null +++ b/lib/websockets/middlewares-injector.js @@ -0,0 +1,51 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const iterare_1 = require("iterare"); +const constants_1 = require("./constants"); +const unknown_module_exception_1 = require("@nestjs/core/errors/exceptions/unknown-module.exception"); +const runtime_exception_1 = require("@nestjs/core/errors/exceptions/runtime.exception"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +class MiddlewaresInjector { + constructor(container, config) { + this.container = container; + this.config = config; + } + inject(server, instance, module) { + const adapter = this.config.getIoAdapter(); + if (!adapter.bindMiddleware) { + return; + } + const opaqueTokens = this.reflectMiddlewaresTokens(instance); + const modules = this.container.getModules(); + if (!modules.has(module)) { + throw new unknown_module_exception_1.UnknownModuleException(); + } + const { components } = modules.get(module); + this.applyMiddlewares(server, components, opaqueTokens); + } + reflectMiddlewaresTokens(instance) { + const prototype = Object.getPrototypeOf(instance); + return Reflect.getMetadata(constants_1.GATEWAY_MIDDLEWARES, prototype.constructor) || []; + } + applyMiddlewares(server, components, tokens) { + const adapter = this.config.getIoAdapter(); + iterare_1.default(tokens).map(token => this.bindMiddleware(token.name, components)) + .filter(middleware => !shared_utils_1.isNil(middleware)) + .forEach(middleware => adapter.bindMiddleware(server, middleware)); + } + bindMiddleware(token, components) { + if (!components.has(token)) { + throw new runtime_exception_1.RuntimeException(); + } + const { instance } = components.get(token); + if (!this.isGatewayMiddleware(instance)) + return null; + const middleware = instance.resolve(); + return shared_utils_1.isFunction(middleware) ? middleware.bind(instance) : null; + } + isGatewayMiddleware(middleware) { + return !shared_utils_1.isUndefined(middleware.resolve); + } +} +exports.MiddlewaresInjector = MiddlewaresInjector; diff --git a/lib/websockets/observable-socket.d.ts b/lib/websockets/observable-socket.d.ts new file mode 100644 index 00000000000..a0f335c39e6 --- /dev/null +++ b/lib/websockets/observable-socket.d.ts @@ -0,0 +1,4 @@ +import { ObservableSocketServer } from './interfaces/observable-socket-server.interface'; +export declare class ObservableSocket { + static create(server: any): ObservableSocketServer; +} diff --git a/lib/websockets/observable-socket.js b/lib/websockets/observable-socket.js new file mode 100644 index 00000000000..0c340ade6b9 --- /dev/null +++ b/lib/websockets/observable-socket.js @@ -0,0 +1,15 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Subject_1 = require("rxjs/Subject"); +const ReplaySubject_1 = require("rxjs/ReplaySubject"); +class ObservableSocket { + static create(server) { + return { + init: new ReplaySubject_1.ReplaySubject(), + connection: new Subject_1.Subject(), + disconnect: new Subject_1.Subject(), + server, + }; + } +} +exports.ObservableSocket = ObservableSocket; diff --git a/lib/websockets/socket-module.d.ts b/lib/websockets/socket-module.d.ts new file mode 100644 index 00000000000..6b30183e066 --- /dev/null +++ b/lib/websockets/socket-module.d.ts @@ -0,0 +1,12 @@ +import 'reflect-metadata'; +import { InstanceWrapper } from '@nestjs/core/injector/container'; +import { Injectable } from '@nestjs/common/interfaces/injectable.interface'; +export declare class SocketModule { + private socketsContainer; + private webSocketsController; + setup(container: any, config: any): void; + hookGatewaysIntoServers(components: Map>, moduleName: string): void; + hookGatewayIntoServer(wrapper: InstanceWrapper, moduleName: string): void; + close(): void; + private getContextCreator(container); +} diff --git a/lib/websockets/socket-module.js b/lib/websockets/socket-module.js new file mode 100644 index 00000000000..5892fc538fe --- /dev/null +++ b/lib/websockets/socket-module.js @@ -0,0 +1,49 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const container_1 = require("./container"); +const web_sockets_controller_1 = require("./web-sockets-controller"); +const socket_server_provider_1 = require("./socket-server-provider"); +const constants_1 = require("./constants"); +const ws_context_creator_1 = require("./context/ws-context-creator"); +const ws_proxy_1 = require("./context/ws-proxy"); +const exception_filters_context_1 = require("./context/exception-filters-context"); +const pipes_consumer_1 = require("@nestjs/core/pipes/pipes-consumer"); +const pipes_context_creator_1 = require("@nestjs/core/pipes/pipes-context-creator"); +const guards_context_creator_1 = require("@nestjs/core/guards/guards-context-creator"); +const guards_consumer_1 = require("@nestjs/core/guards/guards-consumer"); +const interceptors_context_creator_1 = require("@nestjs/core/interceptors/interceptors-context-creator"); +const interceptors_consumer_1 = require("@nestjs/core/interceptors/interceptors-consumer"); +class SocketModule { + constructor() { + this.socketsContainer = new container_1.SocketsContainer(); + } + setup(container, config) { + this.webSocketsController = new web_sockets_controller_1.WebSocketsController(new socket_server_provider_1.SocketServerProvider(this.socketsContainer, config), container, config, this.getContextCreator(container)); + const modules = container.getModules(); + modules.forEach(({ components }, moduleName) => this.hookGatewaysIntoServers(components, moduleName)); + } + hookGatewaysIntoServers(components, moduleName) { + components.forEach((wrapper) => this.hookGatewayIntoServer(wrapper, moduleName)); + } + hookGatewayIntoServer(wrapper, moduleName) { + const { instance, metatype, isNotMetatype } = wrapper; + if (isNotMetatype) { + return; + } + const metadataKeys = Reflect.getMetadataKeys(metatype); + if (metadataKeys.indexOf(constants_1.GATEWAY_METADATA) < 0) { + return; + } + this.webSocketsController.hookGatewayIntoServer(instance, metatype, moduleName); + } + close() { + const servers = this.socketsContainer.getAllServers(); + servers.forEach(({ server }) => server.close()); + this.socketsContainer.clear(); + } + getContextCreator(container) { + return new ws_context_creator_1.WsContextCreator(new ws_proxy_1.WsProxy(), new exception_filters_context_1.ExceptionFiltersContext(), new pipes_context_creator_1.PipesContextCreator(), new pipes_consumer_1.PipesConsumer(), new guards_context_creator_1.GuardsContextCreator(container), new guards_consumer_1.GuardsConsumer(), new interceptors_context_creator_1.InterceptorsContextCreator(container), new interceptors_consumer_1.InterceptorsConsumer()); + } +} +exports.SocketModule = SocketModule; diff --git a/lib/websockets/socket-server-provider.d.ts b/lib/websockets/socket-server-provider.d.ts new file mode 100644 index 00000000000..75e9fe0bff8 --- /dev/null +++ b/lib/websockets/socket-server-provider.d.ts @@ -0,0 +1,12 @@ +import { SocketsContainer } from './container'; +import { ObservableSocketServer } from './interfaces/observable-socket-server.interface'; +import { ApplicationConfig } from '@nestjs/core/application-config'; +export declare class SocketServerProvider { + private readonly socketsContainer; + private readonly applicationConfig; + constructor(socketsContainer: SocketsContainer, applicationConfig: ApplicationConfig); + scanForSocketServer(namespace: string, port: number): ObservableSocketServer; + private createSocketServer(namespace, port); + private getServerOfNamespace(namespace, port); + private validateNamespace(namespace); +} diff --git a/lib/websockets/socket-server-provider.js b/lib/websockets/socket-server-provider.js new file mode 100644 index 00000000000..7aa142b07d9 --- /dev/null +++ b/lib/websockets/socket-server-provider.js @@ -0,0 +1,31 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const observable_socket_1 = require("./observable-socket"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +class SocketServerProvider { + constructor(socketsContainer, applicationConfig) { + this.socketsContainer = socketsContainer; + this.applicationConfig = applicationConfig; + } + scanForSocketServer(namespace, port) { + const observableServer = this.socketsContainer.getServer(namespace, port); + return observableServer ? observableServer : this.createSocketServer(namespace, port); + } + createSocketServer(namespace, port) { + const server = this.getServerOfNamespace(namespace, port); + const observableSocket = observable_socket_1.ObservableSocket.create(server); + this.socketsContainer.addServer(namespace, port, observableSocket); + return observableSocket; + } + getServerOfNamespace(namespace, port) { + const adapter = this.applicationConfig.getIoAdapter(); + if (namespace && adapter.createWithNamespace) { + return adapter.createWithNamespace(port, this.validateNamespace(namespace)); + } + return adapter.create(port); + } + validateNamespace(namespace) { + return shared_utils_1.validatePath(namespace); + } +} +exports.SocketServerProvider = SocketServerProvider; diff --git a/lib/websockets/utils/gateway-server.decorator.d.ts b/lib/websockets/utils/gateway-server.decorator.d.ts new file mode 100644 index 00000000000..e0163c8fbe3 --- /dev/null +++ b/lib/websockets/utils/gateway-server.decorator.d.ts @@ -0,0 +1,5 @@ +import 'reflect-metadata'; +/** + * Attaches the native Web Socket Server to the given property. + */ +export declare const WebSocketServer: () => PropertyDecorator; diff --git a/lib/websockets/utils/gateway-server.decorator.js b/lib/websockets/utils/gateway-server.decorator.js new file mode 100644 index 00000000000..71a5e8ef894 --- /dev/null +++ b/lib/websockets/utils/gateway-server.decorator.js @@ -0,0 +1,13 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("../constants"); +/** + * Attaches the native Web Socket Server to the given property. + */ +exports.WebSocketServer = () => { + return (target, propertyKey) => { + Reflect.set(target, propertyKey, null); + Reflect.defineMetadata(constants_1.GATEWAY_SERVER_METADATA, true, target, propertyKey); + }; +}; diff --git a/lib/websockets/utils/index.d.ts b/lib/websockets/utils/index.d.ts new file mode 100644 index 00000000000..367ddd05d76 --- /dev/null +++ b/lib/websockets/utils/index.d.ts @@ -0,0 +1,3 @@ +export * from './socket-gateway.decorator'; +export * from './subscribe-message.decorator'; +export * from './gateway-server.decorator'; diff --git a/lib/websockets/utils/index.js b/lib/websockets/utils/index.js new file mode 100644 index 00000000000..e7c7fede13d --- /dev/null +++ b/lib/websockets/utils/index.js @@ -0,0 +1,8 @@ +"use strict"; +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +__export(require("./socket-gateway.decorator")); +__export(require("./subscribe-message.decorator")); +__export(require("./gateway-server.decorator")); diff --git a/lib/websockets/utils/socket-gateway.decorator.d.ts b/lib/websockets/utils/socket-gateway.decorator.d.ts new file mode 100644 index 00000000000..5141700f35f --- /dev/null +++ b/lib/websockets/utils/socket-gateway.decorator.d.ts @@ -0,0 +1,7 @@ +import 'reflect-metadata'; +import { GatewayMetadata } from '../interfaces'; +/** + * Defines the Gateway. The gateway can inject dependencies through constructor. + * Those dependencies should belongs to the same module. Gateway is listening on the specified port. + */ +export declare const WebSocketGateway: (metadataOrPort?: number | GatewayMetadata) => ClassDecorator; diff --git a/lib/websockets/utils/socket-gateway.decorator.js b/lib/websockets/utils/socket-gateway.decorator.js new file mode 100644 index 00000000000..3b54230638a --- /dev/null +++ b/lib/websockets/utils/socket-gateway.decorator.js @@ -0,0 +1,20 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("../constants"); +/** + * Defines the Gateway. The gateway can inject dependencies through constructor. + * Those dependencies should belongs to the same module. Gateway is listening on the specified port. + */ +exports.WebSocketGateway = (metadataOrPort) => { + if (Number.isInteger(metadataOrPort)) { + metadataOrPort = { port: metadataOrPort }; + } + const metadata = metadataOrPort || {}; + return (target) => { + Reflect.defineMetadata(constants_1.GATEWAY_METADATA, true, target); + Reflect.defineMetadata(constants_1.NAMESPACE_METADATA, metadata.namespace, target); + Reflect.defineMetadata(constants_1.PORT_METADATA, metadata.port, target); + Reflect.defineMetadata(constants_1.GATEWAY_MIDDLEWARES, metadata.middlewares, target); + }; +}; diff --git a/lib/websockets/utils/subscribe-message.decorator.d.ts b/lib/websockets/utils/subscribe-message.decorator.d.ts new file mode 100644 index 00000000000..fae2e1f519d --- /dev/null +++ b/lib/websockets/utils/subscribe-message.decorator.d.ts @@ -0,0 +1,7 @@ +import 'reflect-metadata'; +/** + * Subscribes to the messages, which fulfils chosen pattern. + */ +export declare const SubscribeMessage: (message?: string | { + value: string; +}) => MethodDecorator; diff --git a/lib/websockets/utils/subscribe-message.decorator.js b/lib/websockets/utils/subscribe-message.decorator.js new file mode 100644 index 00000000000..d305e35afe9 --- /dev/null +++ b/lib/websockets/utils/subscribe-message.decorator.js @@ -0,0 +1,17 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const constants_1 = require("../constants"); +const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); +/** + * Subscribes to the messages, which fulfils chosen pattern. + */ +exports.SubscribeMessage = (message) => { + let metadata = shared_utils_1.isObject(message) ? message.value : message; + metadata = shared_utils_1.isUndefined(metadata) ? '' : metadata; + return (target, key, descriptor) => { + Reflect.defineMetadata(constants_1.MESSAGE_MAPPING_METADATA, true, descriptor.value); + Reflect.defineMetadata(constants_1.MESSAGE_METADATA, metadata, descriptor.value); + return descriptor; + }; +}; diff --git a/lib/websockets/web-sockets-controller.d.ts b/lib/websockets/web-sockets-controller.d.ts new file mode 100644 index 00000000000..f283f43b028 --- /dev/null +++ b/lib/websockets/web-sockets-controller.d.ts @@ -0,0 +1,37 @@ +import 'reflect-metadata'; +import { NestGateway } from './interfaces/nest-gateway.interface'; +import { Injectable } from '@nestjs/common/interfaces/injectable.interface'; +import { ObservableSocketServer } from './interfaces/observable-socket-server.interface'; +import { MessageMappingProperties } from './gateway-metadata-explorer'; +import { Subject } from 'rxjs/Subject'; +import { SocketServerProvider } from './socket-server-provider'; +import { Metatype } from '@nestjs/common/interfaces/metatype.interface'; +import { NestContainer } from '@nestjs/core/injector/container'; +import { ApplicationConfig } from '@nestjs/core/application-config'; +import { WsContextCreator } from './context/ws-context-creator'; +import { Observable } from 'rxjs/Observable'; +import 'rxjs/add/observable/fromPromise'; +import 'rxjs/add/observable/of'; +import 'rxjs/add/operator/switchMap'; +export declare class WebSocketsController { + private readonly socketServerProvider; + private readonly container; + private readonly config; + private readonly contextCreator; + private readonly metadataExplorer; + private readonly middlewaresInjector; + constructor(socketServerProvider: SocketServerProvider, container: NestContainer, config: ApplicationConfig, contextCreator: WsContextCreator); + hookGatewayIntoServer(instance: NestGateway, metatype: Metatype, module: string): void; + subscribeObservableServer(instance: NestGateway, namespace: string, port: number, module: string): void; + injectMiddlewares({server}: { + server: any; + }, instance: NestGateway, module: string): void; + subscribeEvents(instance: NestGateway, messageHandlers: MessageMappingProperties[], observableServer: ObservableSocketServer): void; + getConnectionHandler(context: WebSocketsController, instance: NestGateway, messageHandlers: MessageMappingProperties[], disconnect: Subject, connection: Subject): (client: any) => void; + subscribeInitEvent(instance: NestGateway, event: Subject): void; + subscribeConnectionEvent(instance: NestGateway, event: Subject): void; + subscribeDisconnectEvent(instance: NestGateway, event: Subject): void; + subscribeMessages(messageHandlers: MessageMappingProperties[], client: any, instance: NestGateway): void; + pickResult(defferedResult: Promise): Promise>; + private hookServerToProperties(instance, server); +} diff --git a/lib/websockets/web-sockets-controller.js b/lib/websockets/web-sockets-controller.js new file mode 100644 index 00000000000..3ccdc05c310 --- /dev/null +++ b/lib/websockets/web-sockets-controller.js @@ -0,0 +1,113 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +require("reflect-metadata"); +const invalid_socket_port_exception_1 = require("./exceptions/invalid-socket-port.exception"); +const gateway_metadata_explorer_1 = require("./gateway-metadata-explorer"); +const constants_1 = require("./constants"); +const metadata_scanner_1 = require("@nestjs/core/metadata-scanner"); +const middlewares_injector_1 = require("./middlewares-injector"); +const Observable_1 = require("rxjs/Observable"); +require("rxjs/add/observable/fromPromise"); +require("rxjs/add/observable/of"); +require("rxjs/add/operator/switchMap"); +class WebSocketsController { + constructor(socketServerProvider, container, config, contextCreator) { + this.socketServerProvider = socketServerProvider; + this.container = container; + this.config = config; + this.contextCreator = contextCreator; + this.metadataExplorer = new gateway_metadata_explorer_1.GatewayMetadataExplorer(new metadata_scanner_1.MetadataScanner()); + this.middlewaresInjector = new middlewares_injector_1.MiddlewaresInjector(container, config); + } + hookGatewayIntoServer(instance, metatype, module) { + const namespace = Reflect.getMetadata(constants_1.NAMESPACE_METADATA, metatype) || ''; + const port = Reflect.getMetadata(constants_1.PORT_METADATA, metatype) || 0; + if (!Number.isInteger(port)) { + throw new invalid_socket_port_exception_1.InvalidSocketPortException(port, metatype); + } + this.subscribeObservableServer(instance, namespace, port, module); + } + subscribeObservableServer(instance, namespace, port, module) { + const plainMessageHandlers = this.metadataExplorer.explore(instance); + const messageHandlers = plainMessageHandlers.map(({ callback, message }) => ({ + message, + callback: this.contextCreator.create(instance, callback, module), + })); + const observableServer = this.socketServerProvider.scanForSocketServer(namespace, port); + this.injectMiddlewares(observableServer, instance, module); + this.hookServerToProperties(instance, observableServer.server); + this.subscribeEvents(instance, messageHandlers, observableServer); + } + injectMiddlewares({ server }, instance, module) { + this.middlewaresInjector.inject(server, instance, module); + } + subscribeEvents(instance, messageHandlers, observableServer) { + const { init, disconnect, connection, server } = observableServer; + const adapter = this.config.getIoAdapter(); + this.subscribeInitEvent(instance, init); + this.subscribeConnectionEvent(instance, connection); + this.subscribeDisconnectEvent(instance, disconnect); + init.next(server); + const handler = this.getConnectionHandler(this, instance, messageHandlers, disconnect, connection); + adapter.bindClientConnect(server, handler); + } + getConnectionHandler(context, instance, messageHandlers, disconnect, connection) { + const adapter = this.config.getIoAdapter(); + return (client) => { + connection.next(client); + context.subscribeMessages(messageHandlers, client, instance); + const disconnectHook = adapter.bindClientDisconnect; + disconnectHook && disconnectHook.call(adapter, client, socket => disconnect.next(client)); + }; + } + subscribeInitEvent(instance, event) { + if (instance.afterInit) { + event.subscribe(instance.afterInit.bind(instance)); + } + } + subscribeConnectionEvent(instance, event) { + if (instance.handleConnection) { + event.subscribe(instance.handleConnection.bind(instance)); + } + } + subscribeDisconnectEvent(instance, event) { + if (instance.handleDisconnect) { + event.subscribe(instance.handleDisconnect.bind(instance)); + } + } + subscribeMessages(messageHandlers, client, instance) { + const adapter = this.config.getIoAdapter(); + const handlers = messageHandlers.map(({ callback, message }) => ({ + message, + callback: callback.bind(instance, client), + })); + adapter.bindMessageHandlers(client, handlers, (data) => Observable_1.Observable.fromPromise(this.pickResult(data)) + .switchMap((stream) => stream)); + } + pickResult(defferedResult) { + return __awaiter(this, void 0, void 0, function* () { + const result = yield defferedResult; + if (result instanceof Observable_1.Observable) { + return result; + } + if (result instanceof Promise) { + return Observable_1.Observable.fromPromise(result); + } + return Observable_1.Observable.of(result); + }); + } + hookServerToProperties(instance, server) { + for (const propertyKey of this.metadataExplorer.scanForServerHooks(instance)) { + Reflect.set(instance, propertyKey, server); + } + } +} +exports.WebSocketsController = WebSocketsController; diff --git a/package.json b/package.json index 9e2d6149ab2..bf0bba798cb 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build": "gulp build && gulp move", "build:lib": "gulp build --dist lib", "prepublish": "npm run build:lib", - "publish": "./node_modules/.bin/lerna publish --skip-git" + "publish": "./node_modules/.bin/lerna publish -m \"chore(release) publish %s\"" }, "engines": { "node": ">=6.11.0" From 832eb517df4eaaf3a3cbd59f5f69c57e30bc715a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20My=C5=9Bliwiec?= Date: Fri, 24 Nov 2017 15:15:42 +0100 Subject: [PATCH 34/34] chore(release) publish v4.4.1 --- lerna.json | 2 +- lib/common/package.json | 2 +- lib/core/package.json | 2 +- lib/microservices/package.json | 2 +- lib/testing/package.json | 2 +- lib/websockets/package.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lerna.json b/lerna.json index fa806d7cee1..6135669cc52 100644 --- a/lerna.json +++ b/lerna.json @@ -3,5 +3,5 @@ "packages": [ "lib/*" ], - "version": "4.4.0" + "version": "4.4.1" } diff --git a/lib/common/package.json b/lib/common/package.json index fed0d9c1847..330d3ec5e52 100644 --- a/lib/common/package.json +++ b/lib/common/package.json @@ -1,6 +1,6 @@ { "name": "@nestjs/common", - "version": "4.4.0", + "version": "4.4.1", "description": "Nest - modern, fast, powerful node.js web framework (@common)", "author": "Kamil Mysliwiec", "license": "MIT", diff --git a/lib/core/package.json b/lib/core/package.json index b6f67327946..60951eca0e2 100644 --- a/lib/core/package.json +++ b/lib/core/package.json @@ -1,6 +1,6 @@ { "name": "@nestjs/core", - "version": "4.4.0", + "version": "4.4.1", "description": "Nest - modern, fast, powerful node.js web framework (@core)", "author": "Kamil Mysliwiec", "license": "MIT", diff --git a/lib/microservices/package.json b/lib/microservices/package.json index 3d5fccd7927..9ed9007c509 100644 --- a/lib/microservices/package.json +++ b/lib/microservices/package.json @@ -1,6 +1,6 @@ { "name": "@nestjs/microservices", - "version": "4.4.0", + "version": "4.4.1", "description": "Nest - modern, fast, powerful node.js web framework (@microservices)", "author": "Kamil Mysliwiec", "license": "MIT", diff --git a/lib/testing/package.json b/lib/testing/package.json index 1c2ed35cefe..29cfe2c943a 100644 --- a/lib/testing/package.json +++ b/lib/testing/package.json @@ -1,6 +1,6 @@ { "name": "@nestjs/testing", - "version": "4.4.0", + "version": "4.4.1", "description": "Nest - modern, fast, powerful node.js web framework (@testing)", "author": "Kamil Mysliwiec", "license": "MIT", diff --git a/lib/websockets/package.json b/lib/websockets/package.json index b8796ffe0e9..f293d70d89c 100644 --- a/lib/websockets/package.json +++ b/lib/websockets/package.json @@ -1,6 +1,6 @@ { "name": "@nestjs/websockets", - "version": "4.4.0", + "version": "4.4.1", "description": "Nest - modern, fast, powerful node.js web framework (@websockets)", "author": "Kamil Mysliwiec", "license": "MIT",