chore(release) publish v4.6.0

This commit is contained in:
Kamil Myśliwiec
2018-02-11 23:44:11 +01:00
parent 5fe79633bf
commit a2a00ad31a
104 changed files with 1466 additions and 189 deletions

View File

@@ -1,16 +1,23 @@
## 4.6.0
- **common**: [feature] `ValidationPipe` improvements #388
- **common**: [feature] `ParseIntPipe` improvements #85
- **core***: [feature] add `app.disable()` and `app.enable()` wrappers around `express` app
- **common**: [feature] add `FileInterceptor`, `FilesInterceptor`, `@UploadedFile()` and `@UploadedFiles()` (`multer` integration)
- **common**: [feature] add `HttpModule` that exposes `HttpService` (`axios` integration)
- **core**: [feature] add `app.disable()` and `app.enable()` wrappers around `express` app
- **core**: [feature] add ability to inject `express` reference (`EXPRESS_REF` token)
- **core**: [feature] enable possibility to extend metadata (inheritance support) #228
- **core**: [feature] `NestFactory.create()` now accepts third argument `HttpsOptions`
- **core**: [feature] add `app.enableCors()` to `INestApplication` (`cors` integration)
- **core**: [feature] add `@Render()` decorator (MVC applications)
- **core**: [feature] provide `Logger.overrideLogger()` #247
- **core**: [improvement] simplify HTTPS usage
- **core**: [bugfix] custom transport strategy - thrown exceptions issue #290
- **core**: [bugfix] injector fails silently #287
- **core**: [bugfix] secure websockets (`wss://`) #384
- **core**: [bugfix] can't select/get from context when using `NestFactory.createMicroservice()` #398
- **core**: [bugfix] interceptor `$stream` observable returns another observable instead of the response object #376
- **core**: [bugfix] `Observable.throw` from controller results in unhandled rejection promise #373
- **microservices**: [feature]: add `listenAsync()` to `INestMicroservice` instance
## 4.5.10
- **core**: [bugfix] #343

View File

@@ -3,12 +3,16 @@ import { Transport } from '@nestjs/microservices';
import { ApplicationModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.createMicroservice(ApplicationModule);
await app.listenAsync();
/** Hybrid application (HTTP + (n)Microservices)
const app = await NestFactory.create(ApplicationModule);
app.connectMicroservice({
transport: Transport.TCP,
});
await app.startAllMicroservicesAsync();
await app.listen(3001);
await app.listen(3001); */
}
bootstrap();

View File

@@ -1,9 +1,10 @@
import { Get, Controller, Res } from '@nestjs/common';
import { Get, Controller, Render } from '@nestjs/common';
@Controller()
export class AppController {
@Get()
root(@Res() res) {
res.render('index', { message: 'Hello world!' });
@Get()
@Render('index')
root() {
return { message: 'Hello world!' };
}
}

View File

@@ -2,7 +2,7 @@ import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
@Module({
modules: [],
imports: [],
controllers: [AppController],
components: [],
})

View File

@@ -59,5 +59,7 @@ gulp.task('move', function() {
gulp.dest('examples/11-swagger/node_modules/@nestjs')
).pipe(
gulp.dest('examples/12-graphql-apollo/node_modules/@nestjs')
).pipe(
gulp.dest('examples/15-mvc/node_modules/@nestjs')
);
});

View File

@@ -3,5 +3,5 @@
"packages": [
"lib/*"
],
"version": "4.6.0"
"version": "4.5.9"
}

View File

@@ -17,6 +17,7 @@ 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 RENDER_METADATA = "__renderTemplate__";
export declare const INTERCEPTORS_METADATA = "__interceptors__";
export declare const HTTP_CODE_METADATA = "__httpCode__";
export declare const GATEWAY_MIDDLEWARES = "__gatewayMiddlewares";

View File

@@ -19,6 +19,7 @@ exports.EXCEPTION_FILTERS_METADATA = '__exceptionFilters__';
exports.FILTER_CATCH_EXCEPTIONS = '__filterCatchExceptions__';
exports.PIPES_METADATA = '__pipes__';
exports.GUARDS_METADATA = '__guards__';
exports.RENDER_METADATA = '__renderTemplate__';
exports.INTERCEPTORS_METADATA = '__interceptors__';
exports.HTTP_CODE_METADATA = '__httpCode__';
exports.GATEWAY_MIDDLEWARES = '__gatewayMiddlewares';

View File

@@ -2,3 +2,4 @@ export * from './request-mapping.decorator';
export * from './route-params.decorator';
export * from './http-code.decorator';
export * from './create-route-param-metadata.decorator';
export * from './render.decorator';

View File

@@ -7,3 +7,4 @@ __export(require("./request-mapping.decorator"));
__export(require("./route-params.decorator"));
__export(require("./http-code.decorator"));
__export(require("./create-route-param-metadata.decorator"));
__export(require("./render.decorator"));

View File

@@ -0,0 +1,5 @@
import 'reflect-metadata';
/**
* Defines a template that should be rendered by a controller.
*/
export declare function Render(template: string): MethodDecorator;

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("reflect-metadata");
const constants_1 = require("../../constants");
/**
* Defines a template that should be rendered by a controller.
*/
function Render(template) {
return (target, key, descriptor) => {
Reflect.defineMetadata(constants_1.RENDER_METADATA, template, descriptor.value);
return descriptor;
};
}
exports.Render = Render;

View File

@@ -11,6 +11,8 @@ export declare const Request: () => ParameterDecorator;
export declare const Response: () => ParameterDecorator;
export declare const Next: () => ParameterDecorator;
export declare const Session: () => ParameterDecorator;
export declare const UploadedFile: () => ParameterDecorator;
export declare const UploadedFiles: () => ParameterDecorator;
export declare const Headers: (property?: string) => ParameterDecorator;
export declare function Query(): any;
export declare function Query(...pipes: PipeTransform<any>[]): any;

View File

@@ -26,6 +26,8 @@ exports.Request = createRouteParamDecorator(route_paramtypes_enum_1.RouteParamty
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.UploadedFile = createRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.FILE);
exports.UploadedFiles = createRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.FILES);
exports.Headers = createRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.HEADERS);
function Query(property, ...pipes) {
return createPipesRouteParamDecorator(route_paramtypes_enum_1.RouteParamtypes.QUERY)(property, ...pipes);

View File

@@ -34,6 +34,7 @@ export declare enum HttpStatus {
UNSUPPORTED_MEDIA_TYPE = 415,
REQUESTED_RANGE_NOT_SATISFIABLE = 416,
EXPECTATION_FAILED = 417,
I_AM_A_TEAPOT = 418,
UNPROCESSABLE_ENTITY = 422,
TOO_MANY_REQUESTS = 429,
INTERNAL_SERVER_ERROR = 500,

View File

@@ -37,6 +37,7 @@ var HttpStatus;
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["I_AM_A_TEAPOT"] = 418] = "I_AM_A_TEAPOT";
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";

View File

@@ -7,4 +7,6 @@ export declare enum RouteParamtypes {
PARAM = 5,
HEADERS = 6,
SESSION = 7,
FILE = 8,
FILES = 9,
}

View File

@@ -10,4 +10,6 @@ var RouteParamtypes;
RouteParamtypes[RouteParamtypes["PARAM"] = 5] = "PARAM";
RouteParamtypes[RouteParamtypes["HEADERS"] = 6] = "HEADERS";
RouteParamtypes[RouteParamtypes["SESSION"] = 7] = "SESSION";
RouteParamtypes[RouteParamtypes["FILE"] = 8] = "FILE";
RouteParamtypes[RouteParamtypes["FILES"] = 9] = "FILES";
})(RouteParamtypes = exports.RouteParamtypes || (exports.RouteParamtypes = {}));

2
lib/common/http/http.module.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
export declare class HttpModule {
}

View File

@@ -0,0 +1,19 @@
"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;
};
Object.defineProperty(exports, "__esModule", { value: true });
const module_decorator_1 = require("../decorators/modules/module.decorator");
const http_service_1 = require("./http.service");
let HttpModule = class HttpModule {
};
HttpModule = __decorate([
module_decorator_1.Module({
components: [http_service_1.HttpService],
exports: [http_service_1.HttpService],
})
], HttpModule);
exports.HttpModule = HttpModule;

12
lib/common/http/http.service.d.ts vendored Normal file
View File

@@ -0,0 +1,12 @@
import { Observable } from 'rxjs/Observable';
import { AxiosRequestConfig, AxiosResponse } from './interfaces/axios.interfaces';
import 'rxjs/add/observable/fromPromise';
export declare class HttpService {
request<T = any>(config: AxiosRequestConfig): Observable<AxiosResponse<T>>;
get<T = any>(url: string, config?: AxiosRequestConfig): Observable<AxiosResponse<T>>;
delete(url: string, config?: AxiosRequestConfig): Observable<AxiosResponse<any>>;
head(url: string, config?: AxiosRequestConfig): Observable<AxiosResponse<any>>;
post(url: string, data?: any, config?: AxiosRequestConfig): Observable<AxiosResponse<any>>;
put(url: string, data?: any, config?: AxiosRequestConfig): Observable<AxiosResponse<any>>;
patch(url: string, data?: any, config?: AxiosRequestConfig): Observable<AxiosResponse<any>>;
}

View File

@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const Observable_1 = require("rxjs/Observable");
require("rxjs/add/observable/fromPromise");
class HttpService {
request(config) {
return Observable_1.Observable.fromPromise(axios_1.default.request(config));
}
get(url, config) {
return Observable_1.Observable.fromPromise(axios_1.default.get(url, config));
}
delete(url, config) {
return Observable_1.Observable.fromPromise(axios_1.default.delete(url, config));
}
head(url, config) {
return Observable_1.Observable.fromPromise(axios_1.default.head(url, config));
}
post(url, data, config) {
return Observable_1.Observable.fromPromise(axios_1.default.post(url, data, config));
}
put(url, data, config) {
return Observable_1.Observable.fromPromise(axios_1.default.post(url, data, config));
}
patch(url, data, config) {
return Observable_1.Observable.fromPromise(axios_1.default.post(url, data, config));
}
}
exports.HttpService = HttpService;

2
lib/common/http/index.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
export * from './http.module';
export * from './http.service';

7
lib/common/http/index.js Normal file
View File

@@ -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("./http.module"));
__export(require("./http.service"));

View File

@@ -0,0 +1,109 @@
export interface AxiosTransformer {
(data: any, headers?: any): any;
}
export interface AxiosAdapter {
(config: AxiosRequestConfig): AxiosPromise<any>;
}
export interface AxiosBasicCredentials {
username: string;
password: string;
}
export interface AxiosProxyConfig {
host: string;
port: number;
}
export interface AxiosRequestConfig {
url?: string;
method?: string;
baseURL?: string;
transformRequest?: AxiosTransformer | AxiosTransformer[];
transformResponse?: AxiosTransformer | AxiosTransformer[];
headers?: any;
params?: any;
paramsSerializer?: (params: any) => string;
data?: any;
timeout?: number;
withCredentials?: boolean;
adapter?: AxiosAdapter;
auth?: AxiosBasicCredentials;
responseType?: string;
xsrfCookieName?: string;
xsrfHeaderName?: string;
onUploadProgress?: (progressEvent: any) => void;
onDownloadProgress?: (progressEvent: any) => void;
maxContentLength?: number;
validateStatus?: (status: number) => boolean;
maxRedirects?: number;
httpAgent?: any;
httpsAgent?: any;
proxy?: AxiosProxyConfig;
cancelToken?: CancelToken;
}
export interface AxiosResponse<T = any> {
data: T;
status: number;
statusText: string;
headers: any;
config: AxiosRequestConfig;
request?: any;
}
export interface AxiosError extends Error {
config: AxiosRequestConfig;
code?: string;
request?: any;
response?: AxiosResponse;
}
export interface AxiosPromise<T = any> extends Promise<AxiosResponse<T>> {
}
export interface CancelStatic {
new (message?: string): Cancel;
}
export interface Cancel {
message: string;
}
export interface Canceler {
(message?: string): void;
}
export interface CancelTokenStatic {
new (executor: (cancel: Canceler) => void): CancelToken;
source(): CancelTokenSource;
}
export interface CancelToken {
promise: Promise<Cancel>;
reason?: Cancel;
throwIfRequested(): void;
}
export interface CancelTokenSource {
token: CancelToken;
cancel: Canceler;
}
export interface AxiosInterceptorManager<V> {
use(onFulfilled?: (value: V) => V | Promise<V>, onRejected?: (error: any) => any): number;
eject(id: number): void;
}
export interface AxiosInstance {
defaults: AxiosRequestConfig;
interceptors: {
request: AxiosInterceptorManager<AxiosRequestConfig>;
response: AxiosInterceptorManager<AxiosResponse>;
};
request<T = any>(config: AxiosRequestConfig): AxiosPromise<T>;
get<T = any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>;
delete(url: string, config?: AxiosRequestConfig): AxiosPromise;
head(url: string, config?: AxiosRequestConfig): AxiosPromise;
post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>;
put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>;
patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>;
}
export interface AxiosStatic extends AxiosInstance {
(config: AxiosRequestConfig): AxiosPromise;
(url: string, config?: AxiosRequestConfig): AxiosPromise;
create(config?: AxiosRequestConfig): AxiosInstance;
Cancel: CancelStatic;
CancelToken: CancelTokenStatic;
isCancel(value: any): boolean;
all<T>(values: (T | Promise<T>)[]): Promise<T[]>;
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
}
declare const Axios: AxiosStatic;
export default Axios;

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = Axios;

View File

@@ -1,6 +1,7 @@
export * from './decorators';
export * from './enums';
export { NestModule, INestApplication, INestMicroservice, MiddlewareConfigProxy, MiddlewareConfiguration, NestMiddleware, ExpressMiddleware, MiddlewaresConsumer, OnModuleInit, ExceptionFilter, WebSocketAdapter, PipeTransform, Paramtype, ArgumentMetadata, OnModuleDestroy, ExecutionContext, CanActivate, RpcExceptionFilter, WsExceptionFilter, NestInterceptor, DynamicModule, INestApplicationContext } from './interfaces';
export * from './interceptors';
export * from './services/logger.service';
export * from './pipes';
export * from './utils';

View File

@@ -11,6 +11,7 @@ function __export(m) {
Object.defineProperty(exports, "__esModule", { value: true });
__export(require("./decorators"));
__export(require("./enums"));
__export(require("./interceptors"));
__export(require("./services/logger.service"));
__export(require("./pipes"));
__export(require("./utils"));

View File

@@ -0,0 +1,8 @@
import { Observable } from 'rxjs/Observable';
import { MulterOptions } from '../interfaces/external/multer-options.interface';
export declare function FileInterceptor(fieldName: string, options?: MulterOptions): {
new (): {
readonly upload: any;
intercept(request: any, context: any, stream$: Observable<any>): Promise<Observable<any>>;
};
};

View File

@@ -0,0 +1,26 @@
"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 multer = require("multer");
function FileInterceptor(fieldName, options) {
const Interceptor = class {
constructor() {
this.upload = multer(options);
}
intercept(request, context, stream$) {
return __awaiter(this, void 0, void 0, function* () {
yield new Promise((resolve, reject) => this.upload.single(fieldName)(request, request.res, resolve));
return stream$;
});
}
};
return Interceptor;
}
exports.FileInterceptor = FileInterceptor;

View File

@@ -0,0 +1,8 @@
import { Observable } from 'rxjs/Observable';
import { MulterOptions } from '../interfaces/external/multer-options.interface';
export declare function FilesInterceptor(fieldName: string, maxCount?: number, options?: MulterOptions): {
new (): {
readonly upload: any;
intercept(request: any, context: any, stream$: Observable<any>): Promise<Observable<any>>;
};
};

View File

@@ -0,0 +1,26 @@
"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 multer = require("multer");
function FilesInterceptor(fieldName, maxCount, options) {
const Interceptor = class {
constructor() {
this.upload = multer(options);
}
intercept(request, context, stream$) {
return __awaiter(this, void 0, void 0, function* () {
yield new Promise((resolve, reject) => this.upload.array(fieldName, maxCount)(request, request.res, resolve));
return stream$;
});
}
};
return Interceptor;
}
exports.FilesInterceptor = FilesInterceptor;

2
lib/common/interceptors/index.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
export * from './file.interceptor';
export * from './files.interceptor';

View File

@@ -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("./file.interceptor"));
__export(require("./files.interceptor"));

View File

@@ -0,0 +1,48 @@
/// <reference types="node" />
export interface MulterOptions {
dest?: string;
/** The storage engine to use for uploaded files. */
storage?: any;
/**
* An object specifying the size limits of the following optional properties. This object is passed to busboy
* directly, and the details of properties can be found on https://github.com/mscdex/busboy#busboy-methods
*/
limits?: {
/** Max field name size (Default: 100 bytes) */
fieldNameSize?: number;
/** Max field value size (Default: 1MB) */
fieldSize?: number;
/** Max number of non- file fields (Default: Infinity) */
fields?: number;
/** For multipart forms, the max file size (in bytes)(Default: Infinity) */
fileSize?: number;
/** For multipart forms, the max number of file fields (Default: Infinity) */
files?: number;
/** For multipart forms, the max number of parts (fields + files)(Default: Infinity) */
parts?: number;
/** For multipart forms, the max number of header key=> value pairs to parse Default: 2000(same as node's http). */
headerPairs?: number;
/** Keep the full path of files instead of just the base name (Default: false) */
preservePath?: boolean;
};
fileFilter?(req: any, file: {
/** Field name specified in the form */
fieldname: string;
/** Name of the file on the user's computer */
originalname: string;
/** Encoding type of the file */
encoding: string;
/** Mime type of the file */
mimetype: string;
/** Size of the file in bytes */
size: number;
/** The folder to which the file has been saved (DiskStorage) */
destination: string;
/** The name of the file within the destination (DiskStorage) */
filename: string;
/** Location of the uploaded file (DiskStorage) */
path: string;
/** A Buffer of the entire file (MemoryStorage) */
buffer: Buffer;
}, callback: (error: Error | null, acceptFile: boolean) => void): void;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,14 @@
export interface HttpsOptions {
pfx?: any;
key?: any;
passphrase?: string;
cert?: any;
ca?: any;
crl?: any;
ciphers?: string;
honorCipherOrder?: boolean;
requestCert?: boolean;
rejectUnauthorized?: boolean;
NPNProtocols?: any;
SNICallback?: (servername: string, cb: (err: Error, ctx: any) => any) => any;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -31,6 +31,26 @@ export interface INestApplication extends INestApplicationContext {
* @returns void
*/
engine(...args: any[]): void;
/**
* A wrapper function around native `express.enable()` method.
* Example `app.enable('x-powered-by')`
*
* @returns void
*/
enable(...args: any[]): void;
/**
* Enables CORS (Cross-Origin Resource Sharing)
*
* @returns void
*/
enableCors(): void;
/**
* A wrapper function around native `express.disable()` method.
* Example `app.disable('x-powered-by')`
*
* @returns void
*/
disable(...args: any[]): void;
/**
* Starts the application.
*
@@ -39,8 +59,8 @@ export interface INestApplication extends INestApplicationContext {
* @param {Function} callback Optional callback
* @returns Promise
*/
listen(port: number, callback?: () => void): Promise<any>;
listen(port: number, hostname: string, callback?: () => void): Promise<any>;
listen(port: number | string, callback?: () => void): Promise<any>;
listen(port: number | string, hostname: string, callback?: () => void): Promise<any>;
/**
* Starts the application and can be awaited.
*
@@ -48,7 +68,7 @@ export interface INestApplication extends INestApplicationContext {
* @param {string} hostname (optional)
* @returns Promise
*/
listenAsync(port: number, hostname?: string): Promise<any>;
listenAsync(port: number | string, hostname?: string): Promise<any>;
/**
* Setups the prefix for the every HTTP route path
*

View File

@@ -3,7 +3,8 @@ 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 {
import { INestApplicationContext } from './nest-application-context.interface';
export interface INestMicroservice extends INestApplicationContext {
/**
* Starts the microservice.
*
@@ -11,6 +12,12 @@ export interface INestMicroservice {
* @returns Promise
*/
listen(callback: () => void): any;
/**
* Starts the microservice and can be awaited.
*
* @returns Promise
*/
listenAsync(): Promise<any>;
/**
* Setup Web Sockets Adapter, which will be used inside Gateways.
* Use, when you want to override default `socket.io` library.

View File

@@ -19,11 +19,13 @@ 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');
const isNumeric = 'string' === typeof value &&
!isNaN(parseFloat(value)) &&
isFinite(value);
if (!isNumeric) {
throw new bad_request_exception_1.BadRequestException('Numeric string is expected');
}
return val;
return parseInt(value, 10);
});
}
};

View File

@@ -1,6 +1,13 @@
import { ValidatorOptions } from 'class-validator';
import { PipeTransform } from '../interfaces/pipe-transform.interface';
import { ArgumentMetadata } from '../index';
export declare class ValidationPipe implements PipeTransform<any> {
transform(value: any, metadata: ArgumentMetadata): Promise<any>;
private toValidate(metatype);
export interface ValidationPipeOptions extends ValidatorOptions {
transform?: boolean;
}
export declare class ValidationPipe implements PipeTransform<any> {
private isTransformEnabled;
private validatorOptions;
constructor(options?: ValidationPipeOptions);
transform(value: any, metadata: ArgumentMetadata): Promise<any>;
private toValidate(metadata);
}

View File

@@ -5,6 +5,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
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 __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
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); } }
@@ -13,6 +16,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
const class_validator_1 = require("class-validator");
const class_transformer_1 = require("class-transformer");
@@ -20,26 +32,39 @@ const index_1 = require("../index");
const shared_utils_1 = require("../utils/shared.utils");
const component_decorator_1 = require("./../decorators/core/component.decorator");
let ValidationPipe = class ValidationPipe {
constructor(options) {
options = options || {};
const { transform } = options, validatorOptions = __rest(options, ["transform"]);
this.isTransformEnabled = !!transform;
this.validatorOptions = validatorOptions;
}
transform(value, metadata) {
return __awaiter(this, void 0, void 0, function* () {
const { metatype } = metadata;
if (!metatype || !this.toValidate(metatype)) {
if (!metatype || !this.toValidate(metadata)) {
return value;
}
const entity = class_transformer_1.plainToClass(metatype, value);
const errors = yield class_validator_1.validate(entity);
const errors = yield class_validator_1.validate(entity, this.validatorOptions);
if (errors.length > 0) {
throw new index_1.BadRequestException(errors);
}
return value;
return this.isTransformEnabled
? entity
: Object.keys(this.validatorOptions).length > 0 ? class_transformer_1.classToPlain(entity) : value;
});
}
toValidate(metatype) {
toValidate(metadata) {
const { metatype, type } = metadata;
if (type === 'custom') {
return false;
}
const types = [String, Boolean, Number, Array, Object];
return !types.find(type => metatype === type) && !shared_utils_1.isNil(metatype);
}
};
ValidationPipe = __decorate([
component_decorator_1.Pipe()
component_decorator_1.Pipe(),
__metadata("design:paramtypes", [Object])
], ValidationPipe);
exports.ValidationPipe = ValidationPipe;

View File

@@ -1,16 +1,26 @@
import { NestEnvironment } from '../enums/nest-environment.enum';
export declare class Logger {
export interface LoggerService {
log(message: string): void;
error(message: string, trace: string): void;
warn(message: string): void;
}
export declare class Logger implements LoggerService {
private readonly context;
private readonly printTimestamps;
private static lastTimestamp;
private readonly isTimeDiffEnabled;
private static prevTimestamp;
private static contextEnv;
private readonly yellow;
constructor(context: string, printTimestamps?: boolean);
static setMode(mode: NestEnvironment): void;
private static logger;
private static readonly yellow;
constructor(context: string, isTimeDiffEnabled?: boolean);
log(message: string): void;
error(message: string, trace?: string): void;
warn(message: string): void;
private printMessage(message, color);
private printTimestamp();
private printStackTrace(trace);
static overrideLogger(logger: LoggerService): void;
static setMode(mode: NestEnvironment): void;
static log(message: string, context?: string, isTimeDiffEnabled?: boolean): void;
static error(message: string, trace?: string, context?: string, isTimeDiffEnabled?: boolean): void;
static warn(message: string, context?: string, isTimeDiffEnabled?: boolean): void;
private static printMessage(message, color, context?, isTimeDiffEnabled?);
private static printTimestamp(isTimeDiffEnabled?);
private static printStackTrace(trace);
}

View File

@@ -3,48 +3,64 @@ 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) {
constructor(context, isTimeDiffEnabled = false) {
this.context = context;
this.printTimestamps = printTimestamps;
this.yellow = clc.xterm(3);
this.isTimeDiffEnabled = isTimeDiffEnabled;
}
log(message) {
const { logger } = Logger;
logger.log(message, this.context, this.isTimeDiffEnabled);
}
error(message, trace = '') {
const { logger } = Logger;
logger.error(message, trace, this.context, this.isTimeDiffEnabled);
}
warn(message) {
const { logger } = Logger;
logger.warn(message, this.context, this.isTimeDiffEnabled);
}
static overrideLogger(logger) {
this.logger = logger;
}
static setMode(mode) {
this.contextEnv = mode;
}
log(message) {
this.printMessage(message, clc.green);
static log(message, context = '', isTimeDiffEnabled = true) {
this.printMessage(message, clc.green, context, isTimeDiffEnabled);
}
error(message, trace = '') {
this.printMessage(message, clc.red);
static error(message, trace = '', context = '', isTimeDiffEnabled = true) {
this.printMessage(message, clc.red, context, isTimeDiffEnabled);
this.printStackTrace(trace);
}
warn(message) {
this.printMessage(message, clc.yellow);
static warn(message, context = '', isTimeDiffEnabled = true) {
this.printMessage(message, clc.yellow, context, isTimeDiffEnabled);
}
printMessage(message, color) {
static printMessage(message, color, context = '', isTimeDiffEnabled) {
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(this.yellow(`[${context}] `));
process.stdout.write(color(message));
this.printTimestamp();
this.printTimestamp(isTimeDiffEnabled);
process.stdout.write(`\n`);
}
printTimestamp() {
const includeTimestamp = Logger.lastTimestamp && this.printTimestamps;
static printTimestamp(isTimeDiffEnabled) {
const includeTimestamp = Logger.prevTimestamp && isTimeDiffEnabled;
if (includeTimestamp) {
process.stdout.write(this.yellow(` +${Date.now() - Logger.lastTimestamp}ms`));
process.stdout.write(this.yellow(` +${Date.now() - Logger.prevTimestamp}ms`));
}
Logger.lastTimestamp = Date.now();
Logger.prevTimestamp = Date.now();
}
printStackTrace(trace) {
if (Logger.contextEnv === nest_environment_enum_1.NestEnvironment.TEST || !trace)
static printStackTrace(trace) {
if (this.contextEnv === nest_environment_enum_1.NestEnvironment.TEST || !trace)
return;
process.stdout.write(trace);
process.stdout.write(`\n`);
}
}
Logger.lastTimestamp = null;
Logger.prevTimestamp = null;
Logger.contextEnv = nest_environment_enum_1.NestEnvironment.RUN;
Logger.logger = Logger;
Logger.yellow = clc.xterm(3);
exports.Logger = Logger;

View File

@@ -2,8 +2,8 @@ export declare const UnknownDependenciesMessage: (type: string, index: number, l
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;
export declare const INVALID_MIDDLEWARE_CONFIGURATION = "Invalid middleware configuration passed inside the module 'configure()' method.";
export declare const UNKNOWN_REQUEST_MAPPING = "Request mapping properties not defined in the @RequestMapping() annotation!";
export declare const UNHANDLED_RUNTIME_EXCEPTION = "Unhandled Runtime Exception.";
export declare const INVALID_EXCEPTION_FILTER = "Invalid exception filters (@UseFilters()).";
export declare const MICROSERVICES_PACKAGE_NOT_FOUND_EXCEPTION = "Unable to load @nestjs/microservices packages (please, make sure whether it's installed already).";

View File

@@ -10,6 +10,9 @@ export declare class NestContainer {
private readonly modules;
private readonly dynamicModulesMetadata;
private readonly moduleTokenFactory;
private applicationRef;
setApplicationRef(applicationRef: any): void;
getApplicationRef(): any;
addModule(metatype: NestModuleMetatype | DynamicModule, scope: NestModuleMetatype[]): void;
extractMetadata(metatype: NestModuleMetatype | DynamicModule): {
type: NestModuleMetatype;

View File

@@ -23,6 +23,12 @@ class NestContainer {
this.dynamicModulesMetadata = new Map();
this.moduleTokenFactory = new module_token_factory_1.ModuleTokenFactory();
}
setApplicationRef(applicationRef) {
this.applicationRef = applicationRef;
}
getApplicationRef() {
return this.applicationRef;
}
addModule(metatype, scope) {
if (!metatype) {
throw new invalid_module_exception_1.InvalidModuleException(scope);
@@ -60,7 +66,7 @@ class NestContainer {
if (!modules) {
return;
}
modules.map((module) => this.addModule(module, scope));
modules.map(module => this.addModule(module, scope));
}
isGlobalModule(metatype) {
return !!Reflect.getMetadata(constants_1.GLOBAL_MODULE_METADATA, metatype);

View File

@@ -1 +1,2 @@
export * from './modules-container';
export * from './tokens';

View File

@@ -4,3 +4,4 @@ function __export(m) {
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(require("./modules-container"));
__export(require("./tokens"));

View File

@@ -183,10 +183,10 @@ class Injector {
return component;
}
catch (e) {
if (e instanceof undefined_dependency_exception_1.UndefinedDependencyException) {
throw e;
if (e instanceof runtime_exception_1.RuntimeException) {
return null;
}
return null;
throw e;
}
});
}

View File

@@ -39,6 +39,7 @@ export declare class Module {
addModuleRef(): void;
addModuleAsComponent(): void;
addReflector(): void;
addApplicationRef(applicationRef: any): void;
addExternalContextCreator(container: NestContainer): void;
addModulesContainer(container: NestContainer): void;
addInjectable(injectable: Metatype<Injectable>): void;

View File

@@ -3,13 +3,14 @@ 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");
const external_context_creator_1 = require("./../helpers/external-context-creator");
const guards_context_creator_1 = require("./../guards/guards-context-creator");
const interceptors_context_creator_1 = require("./../interceptors/interceptors-context-creator");
const interceptors_consumer_1 = require("./../interceptors/interceptors-consumer");
const guards_consumer_1 = require("./../guards/guards-consumer");
const modules_container_1 = require("./modules-container");
const reflector_service_1 = require("../services/reflector.service");
const tokens_1 = require("./tokens");
class Module {
constructor(_metatype, _scope, container) {
this._metatype = _metatype;
@@ -53,6 +54,7 @@ class Module {
this.addModuleRef();
this.addModuleAsComponent();
this.addReflector();
this.addApplicationRef(container.getApplicationRef());
this.addExternalContextCreator(container);
this.addModulesContainer(container);
}
@@ -81,6 +83,14 @@ class Module {
instance: null,
});
}
addApplicationRef(applicationRef) {
this._components.set(tokens_1.EXPRESS_REF, {
name: tokens_1.EXPRESS_REF,
metatype: {},
isResolved: true,
instance: applicationRef,
});
}
addExternalContextCreator(container) {
this._components.set(external_context_creator_1.ExternalContextCreator.name, {
name: external_context_creator_1.ExternalContextCreator.name,

1
lib/core/injector/tokens.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
export declare const EXPRESS_REF = "EXPRESS_REF";

View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EXPRESS_REF = 'EXPRESS_REF';

View File

@@ -1,10 +1,13 @@
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/observable/fromPromise';
import 'rxjs/add/operator/take';
import 'rxjs/add/operator/switchMap';
export declare class InterceptorsConsumer {
intercept(interceptors: NestInterceptor[], dataOrRequest: any, instance: Controller, callback: (...args) => any, next: () => Promise<any>): Promise<any>;
createContext(instance: Controller, callback: (...args) => any): ExecutionContext;
transformDeffered(next: () => any): Promise<any>;
transformDeffered(next: () => Promise<any>): Observable<any>;
}

View File

@@ -12,7 +12,9 @@ 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/observable/fromPromise");
require("rxjs/add/operator/take");
require("rxjs/add/operator/switchMap");
class InterceptorsConsumer {
intercept(interceptors, dataOrRequest, instance, callback, next) {
return __awaiter(this, void 0, void 0, function* () {
@@ -20,7 +22,7 @@ class InterceptorsConsumer {
return yield (yield next());
}
const context = this.createContext(instance, callback);
const start$ = Observable_1.Observable.defer(() => __awaiter(this, void 0, void 0, function* () { return yield this.transformDeffered(next); }));
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();
});
@@ -32,8 +34,8 @@ class InterceptorsConsumer {
};
}
transformDeffered(next) {
return __awaiter(this, void 0, void 0, function* () {
const res = yield next();
return Observable_1.Observable.fromPromise(next())
.switchMap((res) => {
const isDeffered = res instanceof Promise || res instanceof Observable_1.Observable;
return isDeffered ? res : Promise.resolve(res);
});

View File

@@ -1,4 +1,5 @@
import { Injectable } from '@nestjs/common/interfaces/injectable.interface';
export declare class MetadataScanner {
scanFromPrototype<T extends Injectable, R>(instance: T, prototype: any, callback: (name: string) => R): R[];
getAllFilteredMethodNames(prototype: any): IterableIterator<string>;
}

View File

@@ -4,17 +4,24 @@ 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]);
})
return iterare_1.default([...this.getAllFilteredMethodNames(prototype)])
.map(callback)
.filter(metadata => !shared_utils_1.isNil(metadata))
.toArray();
}
*getAllFilteredMethodNames(prototype) {
do {
yield* iterare_1.default(Object.getOwnPropertyNames(prototype))
.filter(prop => {
const descriptor = Object.getOwnPropertyDescriptor(prototype, prop);
if (descriptor.set || descriptor.get) {
return false;
}
return !shared_utils_1.isConstructor(prop) && shared_utils_1.isFunction(prototype[prop]);
})
.toArray();
} while ((prototype = Reflect.getPrototypeOf(prototype)) &&
prototype != Object.prototype);
}
}
exports.MetadataScanner = MetadataScanner;

View File

@@ -5,8 +5,10 @@ import { INestApplication, INestMicroservice } from '@nestjs/common';
import { MicroserviceConfiguration } from '@nestjs/common/interfaces/microservices/microservice-configuration.interface';
import { NestContainer } from './injector/container';
import { NestApplicationContext } from './nest-application-context';
import { HttpsOptions } from '@nestjs/common/interfaces/https-options.interface';
export declare class NestApplication extends NestApplicationContext implements INestApplication {
private readonly express;
private readonly httpsOptions;
private readonly logger;
private readonly middlewaresModule;
private readonly middlewaresContainer;
@@ -17,9 +19,13 @@ export declare class NestApplication extends NestApplicationContext implements I
private readonly config;
private readonly microservices;
private isInitialized;
constructor(container: NestContainer, express: any);
constructor(container: NestContainer, express: any, httpsOptions?: HttpsOptions);
selectContextModule(): void;
createServer(): any;
setupModules(): Promise<void>;
init(): Promise<void>;
init(options?: {
bodyParser?: boolean;
}): Promise<void>;
setupParserMiddlewares(): void;
isMiddlewareApplied(app: any, name: string): boolean;
setupRouter(): Promise<void>;
@@ -32,9 +38,11 @@ export declare class NestApplication extends NestApplicationContext implements I
engine(...args: any[]): void;
set(...args: any[]): void;
disable(...args: any[]): void;
listen(port: number, callback?: () => void): any;
listen(port: number, hostname: string, callback?: () => void): any;
listenAsync(port: number, hostname?: string): Promise<any>;
enable(...args: any[]): void;
enableCors(): void;
listen(port: number | string, callback?: () => void): any;
listen(port: number | string, hostname: string, callback?: () => void): any;
listenAsync(port: number | string, hostname?: string): Promise<any>;
close(): void;
setGlobalPrefix(prefix: string): void;
useWebSocketAdapter(adapter: WebSocketAdapter): void;

View File

@@ -8,7 +8,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const cors = require("cors");
const http = require("http");
const https = require("https");
const optional = require("optional");
const bodyParser = require("body-parser");
const iterare_1 = require("iterare");
@@ -27,9 +29,10 @@ const { MicroservicesModule } = optional('@nestjs/microservices/microservices-mo
const { NestMicroservice } = optional('@nestjs/microservices/nest-microservice') || {};
const { IoAdapter } = optional('@nestjs/websockets/adapters/io-adapter') || {};
class NestApplication extends nest_application_context_1.NestApplicationContext {
constructor(container, express) {
constructor(container, express, httpsOptions = null) {
super(container, [], null);
this.express = express;
this.httpsOptions = httpsOptions;
this.logger = new logger_service_1.Logger(NestApplication.name, true);
this.middlewaresModule = new middlewares_module_1.MiddlewaresModule();
this.middlewaresContainer = new container_1.MiddlewaresContainer();
@@ -41,13 +44,22 @@ class NestApplication extends nest_application_context_1.NestApplicationContext
this.routesResolver = null;
this.microservices = [];
this.isInitialized = false;
const modules = this.container.getModules().values();
this.contextModule = modules.next().value;
this.httpServer = http.createServer(express);
this.selectContextModule();
this.httpServer = this.createServer();
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);
}
selectContextModule() {
const modules = this.container.getModules().values();
this.contextModule = modules.next().value;
}
createServer() {
if (!this.httpsOptions) {
return http.createServer(this.express);
}
return https.createServer(this.httpsOptions, this.express);
}
setupModules() {
return __awaiter(this, void 0, void 0, function* () {
this.socketModule && this.socketModule.setup(this.container, this.config);
@@ -58,9 +70,9 @@ class NestApplication extends nest_application_context_1.NestApplicationContext
yield this.middlewaresModule.setup(this.middlewaresContainer, this.container, this.config);
});
}
init() {
init(options = { bodyParser: true }) {
return __awaiter(this, void 0, void 0, function* () {
this.setupParserMiddlewares();
!!options.bodyParser && this.setupParserMiddlewares();
yield this.setupModules();
yield this.setupRouter();
this.callInitHook();
@@ -121,6 +133,15 @@ class NestApplication extends nest_application_context_1.NestApplicationContext
set(...args) {
this.express.set(...args);
}
disable(...args) {
this.express.disable(...args);
}
enable(...args) {
this.express.enable(...args);
}
enableCors() {
this.express.use(cors());
}
listen(port, ...args) {
return __awaiter(this, void 0, void 0, function* () {
!this.isInitialized && (yield this.init());

View File

@@ -1,5 +1,6 @@
import { MicroserviceConfiguration } from '@nestjs/common/interfaces/microservices/microservice-configuration.interface';
import { INestApplication, INestMicroservice, INestApplicationContext } from '@nestjs/common';
import { HttpsOptions } from '@nestjs/common/interfaces/https-options.interface';
export declare class NestFactoryStatic {
private container;
private instanceLoader;
@@ -12,7 +13,7 @@ export declare class NestFactoryStatic {
* @param {} express Optional express() server instance
* @returns an `Promise` of the INestApplication instance
*/
create(module: any, express?: any): Promise<INestApplication>;
create(module: any, express?: any, httpsOptions?: HttpsOptions): Promise<INestApplication>;
/**
* Creates an instance of the NestMicroservice (returns Promise)
*
@@ -29,7 +30,7 @@ export declare class NestFactoryStatic {
*/
createApplicationContext(module: any): Promise<INestApplicationContext>;
private createNestInstance<T>(instance);
private initialize(module);
private initialize(module, express?);
private createProxy(target);
private createExceptionProxy();
}

View File

@@ -36,10 +36,10 @@ class NestFactoryStatic {
* @param {} express Optional express() server instance
* @returns an `Promise` of the INestApplication instance
*/
create(module, express = express_adapter_1.ExpressAdapter.create()) {
create(module, express = express_adapter_1.ExpressAdapter.create(), httpsOptions = null) {
return __awaiter(this, void 0, void 0, function* () {
yield this.initialize(module);
return this.createNestInstance(new nest_application_1.NestApplication(this.container, express));
yield this.initialize(module, express);
return this.createNestInstance(new nest_application_1.NestApplication(this.container, express, httpsOptions));
});
}
/**
@@ -75,8 +75,9 @@ class NestFactoryStatic {
createNestInstance(instance) {
return this.createProxy(instance);
}
initialize(module) {
initialize(module, express = null) {
return __awaiter(this, void 0, void 0, function* () {
this.container.setApplicationRef(express);
try {
this.logger.log(constants_1.messages.APPLICATION_START);
yield exceptions_zone_1.ExceptionsZone.asyncRun(() => __awaiter(this, void 0, void 0, function* () {

View File

@@ -20,6 +20,10 @@ class RouteParamsFactory {
return data ? req.headers[data] : req.headers;
case route_paramtypes_enum_1.RouteParamtypes.SESSION:
return req.session;
case route_paramtypes_enum_1.RouteParamtypes.FILE:
return req.file;
case route_paramtypes_enum_1.RouteParamtypes.FILES:
return req.files;
default:
return null;
}

View File

@@ -32,6 +32,7 @@ export declare class RouterExecutionContext {
reflectCallbackMetadata(instance: Controller, methodName: string): RouteParamsMetadata;
reflectCallbackParamtypes(instance: Controller, methodName: string): any[];
reflectHttpStatusCode(callback: (...args) => any): number;
reflectRenderTemplate(callback: any): boolean;
getArgumentsLength(keys: string[], metadata: RouteParamsMetadata): number;
createNullArray(length: number): any[];
exchangeKeysForValues(keys: string[], metadata: RouteParamsMetadata): ParamProperties[];
@@ -48,4 +49,5 @@ export declare class RouterExecutionContext {
createPipesFn(pipes: any[], paramsOptions: (ParamProperties & {
metatype?: any;
})[]): (args: any, req: any, res: any, next: any) => Promise<void>;
createHandleResponseFn(callback: any, isResponseHandled: boolean, httpStatusCode: number): (result: any, res: any) => any;
}

View File

@@ -43,6 +43,7 @@ class RouterExecutionContext {
: this.responseController.getStatusByMethod(requestMethod);
const fnCanActivate = this.createGuardsFn(guards, instance, callback);
const fnApplyPipes = this.createPipesFn(pipes, paramsOptions);
const fnHandleResponse = this.createHandleResponseFn(callback, isResponseHandled, httpStatusCode);
return (req, res, next) => __awaiter(this, void 0, void 0, function* () {
const args = this.createNullArray(argsLength);
fnCanActivate && (yield fnCanActivate(req));
@@ -51,7 +52,7 @@ class RouterExecutionContext {
return callback.apply(instance, args);
});
const result = yield this.interceptorsConsumer.intercept(interceptors, req, instance, callback, handler);
!isResponseHandled && this.responseController.apply(result, res, httpStatusCode);
yield fnHandleResponse(result, res);
});
}
mapParamType(key) {
@@ -67,6 +68,9 @@ class RouterExecutionContext {
reflectHttpStatusCode(callback) {
return Reflect.getMetadata(constants_1.HTTP_CODE_METADATA, callback);
}
reflectRenderTemplate(callback) {
return Reflect.getMetadata(constants_1.RENDER_METADATA, callback);
}
getArgumentsLength(keys, metadata) {
return Math.max(...keys.map(key => metadata[key].index)) + 1;
}
@@ -128,5 +132,15 @@ class RouterExecutionContext {
});
return paramsOptions.length ? pipesFn : null;
}
createHandleResponseFn(callback, isResponseHandled, httpStatusCode) {
const renderTemplate = this.reflectRenderTemplate(callback);
if (!!renderTemplate) {
return (result, res) => res.render(renderTemplate, result);
}
return (result, res) => __awaiter(this, void 0, void 0, function* () {
return !isResponseHandled &&
(yield this.responseController.apply(result, res, httpStatusCode));
});
}
}
exports.RouterExecutionContext = RouterExecutionContext;

View File

@@ -2,6 +2,7 @@ import { RequestMethod } from '@nestjs/common';
import 'rxjs/add/operator/toPromise';
export declare class RouterResponseController {
apply(resultOrDeffered: any, response: any, httpStatusCode: number): Promise<any>;
render(resultOrDeffered: any, response: any, template: string): Promise<void>;
transformToResult(resultOrDeffered: any): Promise<any>;
getStatusByMethod(requestMethod: RequestMethod): number;
}

View File

@@ -22,6 +22,12 @@ class RouterResponseController {
return shared_utils_1.isObject(result) ? res.json(result) : res.send(String(result));
});
}
render(resultOrDeffered, response, template) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield this.transformToResult(resultOrDeffered);
response.render(template, result);
});
}
transformToResult(resultOrDeffered) {
return __awaiter(this, void 0, void 0, function* () {
if (resultOrDeffered instanceof Promise) {

View File

@@ -20,9 +20,11 @@ class RoutesResolver {
}
resolve(express) {
const modules = this.container.getModules();
modules.forEach((module, moduleName) => {
const path = Reflect.getMetadata(constants_1.MODULE_PATH, module.metatype);
this.setupRouters(module.routes, moduleName, path, express);
modules.forEach(({ routes, metatype }, moduleName) => {
const path = metatype
? Reflect.getMetadata(constants_1.MODULE_PATH, metatype)
: undefined;
this.setupRouters(routes, moduleName, path, express);
});
this.setupNotFoundHandler(express);
this.setupExceptionHandler(express);

View File

@@ -2,4 +2,4 @@ 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;
export declare const NO_PATTERN_MESSAGE = "There's no equivalent message pattern.";

View File

@@ -1,8 +1,8 @@
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;
import { NestApplicationContext } from '@nestjs/core/nest-application-context';
export declare class NestMicroservice extends NestApplicationContext implements INestMicroservice {
private readonly logger;
private readonly microservicesModule;
private readonly socketModule;
@@ -21,6 +21,7 @@ export declare class NestMicroservice implements INestMicroservice {
useGlobalInterceptors(...interceptors: NestInterceptor[]): void;
useGlobalGuards(...guards: CanActivate[]): void;
listen(callback: () => void): void;
listenAsync(): Promise<any>;
close(): void;
setIsInitialized(isInitialized: boolean): void;
setIsTerminated(isTerminaed: boolean): void;

View File

@@ -1,4 +1,12 @@
"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 iterare_1 = require("iterare");
@@ -9,11 +17,12 @@ 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 nest_application_context_1 = require("@nestjs/core/nest-application-context");
const { SocketModule } = optional('@nestjs/websockets/socket-module') || {};
const { IoAdapter } = optional('@nestjs/websockets/adapters/io-adapter') || {};
class NestMicroservice {
class NestMicroservice extends nest_application_context_1.NestApplicationContext {
constructor(container, config = {}) {
this.container = container;
super(container, [], null);
this.logger = new logger_service_1.Logger(NestMicroservice.name, true);
this.microservicesModule = new microservices_module_1.MicroservicesModule();
this.socketModule = SocketModule ? new SocketModule() : null;
@@ -59,6 +68,11 @@ class NestMicroservice {
this.logger.log(constants_1.messages.MICROSERVICE_READY);
this.server.listen(callback);
}
listenAsync() {
return __awaiter(this, void 0, void 0, function* () {
return yield new Promise((resolve) => this.listen(resolve));
});
}
close() {
this.server.close();
!this.isTerminated && this.closeApplication();

250
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "nestjs",
"version": "4.5.10",
"version": "4.6.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -76,10 +76,18 @@
"socket.io": "2.0.4"
}
},
"@types/axios": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.0.tgz",
"integrity": "sha1-7CMA++fX3d1+udOr+HmZlkyvzkY=",
"requires": {
"axios": "0.17.1"
}
},
"@types/body-parser": {
"version": "1.16.8",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.16.8.tgz",
"integrity": "sha512-BdN2PXxOFnTXFcyONPW6t0fHjz2fvRZHVMFpaS0wYr+Y8fWEaNOs4V8LEu/fpzQlMx+ahdndgTaGTwPC+J/EeA==",
"integrity": "sha1-aH7DQUBiSjvsKxqOqSaEeK6PO+M=",
"dev": true,
"requires": {
"@types/express": "4.0.39",
@@ -104,7 +112,7 @@
"@types/express": {
"version": "4.0.39",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.0.39.tgz",
"integrity": "sha512-dBUam7jEjyuEofigUXCtublUHknRZvcRgITlGsTbFgPvnTwtQUt2NgLakbsf+PsGo/Nupqr3IXCYsOpBpofyrA==",
"integrity": "sha1-FEHyHVKzO+jU+oqGXBWmqRzQ+gk=",
"dev": true,
"requires": {
"@types/body-parser": "1.16.8",
@@ -124,7 +132,7 @@
"@types/mime": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz",
"integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==",
"integrity": "sha1-WnMG42fFObn2VDSZ3o3VGfrDeos=",
"dev": true
},
"@types/mocha": {
@@ -157,7 +165,7 @@
"@types/serve-static": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.1.tgz",
"integrity": "sha512-jDMH+3BQPtvqZVIcsH700Dfi8Q3MIcEx16g/VdxjoqiGR/NntekB10xdBpirMKnPe9z2C5cBmL0vte0YttOr3Q==",
"integrity": "sha1-HSgB+mNdJ0zZfU7AfiayG0QSdJI=",
"dev": true,
"requires": {
"@types/express-serve-static-core": "4.0.57",
@@ -353,10 +361,15 @@
}
}
},
"append-field": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/append-field/-/append-field-0.1.0.tgz",
"integrity": "sha1-bdxY+gg8e8VF08WZWygwzCNm1Eo="
},
"aproba": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
"integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=",
"dev": true
},
"archy": {
@@ -544,6 +557,15 @@
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=",
"dev": true
},
"axios": {
"version": "0.17.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz",
"integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=",
"requires": {
"follow-redirects": "1.4.1",
"is-buffer": "1.1.6"
}
},
"babel-polyfill": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz",
@@ -772,6 +794,38 @@
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
"dev": true
},
"busboy": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz",
"integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=",
"requires": {
"dicer": "0.2.5",
"readable-stream": "1.1.14"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "0.0.1",
"string_decoder": "0.10.31"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"byline": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz",
@@ -967,7 +1021,7 @@
"class-transformer": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.1.8.tgz",
"integrity": "sha512-qniRyjtvDPEXFspXfjrYerYy75pqwOIN4IUf2/MPHzZ3zVB7Cssq7dKSNZzEp6G1DH8tDk5gKY+KFxtlkf03qQ=="
"integrity": "sha1-vgTdKvt7MB5MjHnFNJ/tqsPVp+E="
},
"class-utils": {
"version": "0.3.5",
@@ -1012,7 +1066,7 @@
},
"class-validator": {
"version": "0.8.1",
"resolved": "http://192.168.228.42:5000/class-validator/-/class-validator-0.8.1.tgz",
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.8.1.tgz",
"integrity": "sha512-sQgc0oEI2VqyARUZdXNWvsopOO12rrE1/3TdGDhn/P0bpAOTnhT2hdkHyVGOpSQKjolLgtWq1EddXhSL/9CgnQ==",
"requires": {
"validator": "9.2.0"
@@ -1020,7 +1074,7 @@
"dependencies": {
"validator": {
"version": "9.2.0",
"resolved": "http://192.168.228.42:5000/validator/-/validator-9.2.0.tgz",
"resolved": "https://registry.npmjs.org/validator/-/validator-9.2.0.tgz",
"integrity": "sha512-6Ij4Eo0KM4LkR0d0IegOwluG5453uqT5QyF5SV5Ezvm8/zmkKI/L4eoraafZGlZPC9guLkwKzgypcw8VGWWnGA=="
}
}
@@ -1244,7 +1298,6 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz",
"integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=",
"dev": true,
"requires": {
"inherits": "2.0.3",
"readable-stream": "2.3.3",
@@ -1587,7 +1640,7 @@
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
"integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=",
"dev": true
}
}
@@ -1662,8 +1715,16 @@
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"cors": {
"version": "2.8.4",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz",
"integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=",
"requires": {
"object-assign": "4.1.1",
"vary": "1.1.2"
}
},
"coveralls": {
"version": "2.13.3",
@@ -1896,6 +1957,38 @@
"integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=",
"dev": true
},
"dicer": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
"integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=",
"requires": {
"readable-stream": "1.1.14",
"streamsearch": "0.1.2"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "0.0.1",
"string_decoder": "0.10.31"
}
},
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
}
}
},
"diff": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
@@ -2064,7 +2157,7 @@
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
"requires": {
"ms": "2.0.0"
}
@@ -2092,7 +2185,7 @@
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
"requires": {
"ms": "2.0.0"
}
@@ -2516,7 +2609,7 @@
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
"requires": {
"ms": "2.0.0"
}
@@ -2524,12 +2617,12 @@
"iconv-lite": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
"integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ=="
"integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs="
},
"qs": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
"integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A=="
"integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg="
},
"raw-body": {
"version": "2.3.2",
@@ -2545,7 +2638,7 @@
"setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
"integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY="
},
"statuses": {
"version": "1.3.1",
@@ -2823,6 +2916,24 @@
"integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=",
"dev": true
},
"follow-redirects": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz",
"integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==",
"requires": {
"debug": "3.1.0"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
}
}
},
"for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -3995,7 +4106,7 @@
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
"integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=",
"dev": true
}
}
@@ -4155,7 +4266,7 @@
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
"dev": true,
"requires": {
"fs.realpath": "1.0.0",
@@ -4169,7 +4280,7 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"dev": true,
"requires": {
"brace-expansion": "1.1.8"
@@ -4933,7 +5044,7 @@
"hosted-git-info": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz",
"integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==",
"integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=",
"dev": true
},
"http-errors": {
@@ -5111,8 +5222,7 @@
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"is-builtin-module": {
"version": "1.0.0",
@@ -5644,7 +5754,7 @@
"lerna": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/lerna/-/lerna-2.5.1.tgz",
"integrity": "sha512-Qz2fajqCPtZf4SFQQpQ2R/Ml/RvGvTNuIHix/vAMMSAdbtnPe2QTw34vLD24Clfsfy8FEojy+tqsjejWKqkDFw==",
"integrity": "sha1-0HCZvTBR7nmfmMdTMovWnpbG+rg=",
"dev": true,
"requires": {
"async": "1.5.2",
@@ -5690,7 +5800,7 @@
"ansi-escapes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz",
"integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==",
"integrity": "sha1-7D6LTp+AZPwCw6ybZfHCdb2o75I=",
"dev": true
},
"ansi-regex": {
@@ -5702,7 +5812,7 @@
"ansi-styles": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
"integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
"integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=",
"dev": true,
"requires": {
"color-convert": "1.9.1"
@@ -5717,7 +5827,7 @@
"chalk": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
"integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
"integrity": "sha1-tepI78nBeT3MybR2fJORTT8tUro=",
"dev": true,
"requires": {
"ansi-styles": "3.2.0",
@@ -5767,7 +5877,7 @@
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
"dev": true,
"requires": {
"fs.realpath": "1.0.0",
@@ -5797,7 +5907,7 @@
"inquirer": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
"integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
"integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=",
"dev": true,
"requires": {
"ansi-escapes": "3.0.0",
@@ -5843,7 +5953,7 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"dev": true,
"requires": {
"brace-expansion": "1.1.8"
@@ -5862,7 +5972,7 @@
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
"integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
"integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=",
"dev": true
},
"strip-ansi": {
@@ -6247,7 +6357,7 @@
"make-dir": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz",
"integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==",
"integrity": "sha1-GbQ2n+SMEW9Twq+VrRAsDjnoXVE=",
"dev": true,
"requires": {
"pify": "3.0.0"
@@ -6441,7 +6551,6 @@
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"dev": true,
"requires": {
"minimist": "0.0.8"
},
@@ -6449,8 +6558,7 @@
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
}
}
},
@@ -6543,6 +6651,28 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"multer": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.3.0.tgz",
"integrity": "sha1-CSsmcPaEb6SRSWXvyM+Uwg/sbNI=",
"requires": {
"append-field": "0.1.0",
"busboy": "0.2.14",
"concat-stream": "1.6.0",
"mkdirp": "0.5.1",
"object-assign": "3.0.0",
"on-finished": "2.3.0",
"type-is": "1.6.15",
"xtend": "4.0.1"
},
"dependencies": {
"object-assign": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
"integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I="
}
}
},
"multipipe": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz",
@@ -6643,7 +6773,7 @@
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
"dev": true,
"requires": {
"ms": "2.0.0"
@@ -6702,7 +6832,7 @@
"npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=",
"dev": true,
"requires": {
"are-we-there-yet": "1.1.4",
@@ -8298,7 +8428,7 @@
"optional": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/optional/-/optional-0.1.4.tgz",
"integrity": "sha512-gtvrrCfkE08wKcgXaVwQVgwEQ8vel2dc5DDBn9RLQZ3YtmtkBss6A2HY6BnJH4N/4Ku97Ri/SF8sNWE2225WJw=="
"integrity": "sha1-zbGpvtxzfSAl9pDO61DgSURP1bM="
},
"optionator": {
"version": "0.8.2",
@@ -8340,7 +8470,7 @@
"os-locale": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
"integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
"integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=",
"dev": true,
"requires": {
"execa": "0.7.0",
@@ -8622,8 +8752,7 @@
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
"dev": true
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"proxy-addr": {
"version": "2.0.2",
@@ -8837,7 +8966,6 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
"integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
"dev": true,
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
@@ -8851,8 +8979,7 @@
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
}
}
},
@@ -9093,7 +9220,7 @@
"rimraf": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
"integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
"integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=",
"dev": true,
"requires": {
"glob": "7.1.2"
@@ -9102,7 +9229,7 @@
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
"dev": true,
"requires": {
"fs.realpath": "1.0.0",
@@ -9116,7 +9243,7 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"dev": true,
"requires": {
"brace-expansion": "1.1.8"
@@ -9610,7 +9737,7 @@
"split2": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz",
"integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==",
"integrity": "sha1-GGsldbz4PoW30YRldWI47k7kJJM=",
"dev": true,
"requires": {
"through2": "2.0.3"
@@ -9737,6 +9864,11 @@
"integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
"dev": true
},
"streamsearch": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
@@ -9765,7 +9897,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"dev": true,
"requires": {
"safe-buffer": "5.1.1"
}
@@ -9946,7 +10077,7 @@
"text-extensions": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.7.0.tgz",
"integrity": "sha512-AKXZeDq230UaSzaO5s3qQUZOaC7iKbzq0jOFL614R7d9R593HLqAOL0cYoqLdkNrjBSOdmoQI06yigq1TSBXAg==",
"integrity": "sha1-+qq6JiXtdG1WiiPk0KrNm/CKizk=",
"dev": true
},
"through": {
@@ -9977,7 +10108,7 @@
"thunks": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/thunks/-/thunks-4.9.0.tgz",
"integrity": "sha512-Bp4sGtcf8/SAgX2XBXYH2Crc7ESL7xuTuQ5kx84Tvz7VSkLFg6bfjFBpRmX2DLAWaLeK6q32ogqAnXcr5NAQtw==",
"integrity": "sha1-RsANuZaFg7OkIeDJKF6si5/dsxo=",
"dev": true
},
"tildify": {
@@ -10277,8 +10408,7 @@
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"typescript": {
"version": "2.6.1",
@@ -10542,8 +10672,7 @@
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"utils-merge": {
"version": "1.0.1",
@@ -10590,7 +10719,7 @@
"validator": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-7.2.0.tgz",
"integrity": "sha512-c8NGTUYeBEcUIGeMppmNVKHE7wwfm3mYbNZxV+c5mlv9fDHI7Ad3p07qfNrn/CvpdkK2k61fOLRO2sTEhgQXmg=="
"integrity": "sha1-pj3Lq6UdQ1C/jfIJiODVpU1xF5E="
},
"vary": {
"version": "1.1.2",
@@ -10786,7 +10915,7 @@
"wide-align": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
"integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
"integrity": "sha1-Vx4PGwYEY268DfwhsDObvjE0FxA=",
"dev": true,
"requires": {
"string-width": "1.0.2"
@@ -10963,8 +11092,7 @@
"xtend": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
"dev": true
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
},
"y18n": {
"version": "3.2.1",

View File

@@ -10,7 +10,8 @@
"build": "gulp build && gulp move",
"build:lib": "gulp build --dist lib",
"prepublish": "npm run build:lib",
"publish": "./node_modules/.bin/lerna publish --npm-tag=next --exact -m \"chore(release) publish %s\""
"publish": "./node_modules/.bin/lerna publish --skip-npm --exact -m \"chore(release) publish %s\"",
"publish:next": "./node_modules/.bin/lerna publish --npm-tag=next --exact --skip-git"
},
"engines": {
"node": ">=6.11.0"
@@ -23,14 +24,18 @@
"@nestjs/microservices": "^4.0.0",
"@nestjs/testing": "^4.0.0",
"@nestjs/websockets": "^4.0.0",
"@types/axios": "^0.14.0",
"axios": "^0.17.1",
"class-transformer": "^0.1.8",
"class-validator": "^0.8.1",
"cli-color": "^1.1.0",
"cors": "^2.8.4",
"engine.io-client": "^3.1.1",
"express": "^4.16.2",
"fast-safe-stringify": "^1.2.0",
"iterare": "0.0.8",
"json-socket": "^0.2.1",
"multer": "^1.3.0",
"opencollective": "^1.0.3",
"optional": "^0.1.4",
"redis": "^2.7.1",
@@ -91,6 +96,7 @@
"src/**/nest-*.ts",
"src/core/errors/**/*",
"src/common/exceptions/*.ts",
"src/common/http/*.ts",
"src/microservices/exceptions/",
"src/microservices/microservices-module.ts",
"src/core/middlewares/middlewares-module.ts",

View File

@@ -18,6 +18,7 @@ export const EXCEPTION_FILTERS_METADATA = '__exceptionFilters__';
export const FILTER_CATCH_EXCEPTIONS = '__filterCatchExceptions__';
export const PIPES_METADATA = '__pipes__';
export const GUARDS_METADATA = '__guards__';
export const RENDER_METADATA = '__renderTemplate__';
export const INTERCEPTORS_METADATA = '__interceptors__';
export const HTTP_CODE_METADATA = '__httpCode__';
export const GATEWAY_MIDDLEWARES = '__gatewayMiddlewares';

View File

@@ -2,3 +2,4 @@ export * from './request-mapping.decorator';
export * from './route-params.decorator';
export * from './http-code.decorator';
export * from './create-route-param-metadata.decorator';
export * from './render.decorator';

View File

@@ -0,0 +1,12 @@
import 'reflect-metadata';
import { RENDER_METADATA } from '../../constants';
/**
* Defines a template that should be rendered by a controller.
*/
export function Render(template: string): MethodDecorator {
return (target: object, key, descriptor) => {
Reflect.defineMetadata(RENDER_METADATA, template, descriptor.value);
return descriptor;
};
}

View File

@@ -68,6 +68,12 @@ export const Next: () => ParameterDecorator = createRouteParamDecorator(
export const Session: () => ParameterDecorator = createRouteParamDecorator(
RouteParamtypes.SESSION,
);
export const UploadedFile: () => ParameterDecorator = createRouteParamDecorator(
RouteParamtypes.FILE,
);
export const UploadedFiles: () => ParameterDecorator = createRouteParamDecorator(
RouteParamtypes.FILES,
);
export const Headers: (
property?: string,
) => ParameterDecorator = createRouteParamDecorator(RouteParamtypes.HEADERS);

View File

@@ -7,4 +7,6 @@ export enum RouteParamtypes {
PARAM,
HEADERS,
SESSION,
FILE,
FILES
}

View File

@@ -0,0 +1,8 @@
import { Module } from '../decorators/modules/module.decorator';
import { HttpService } from './http.service';
@Module({
components: [HttpService],
exports: [HttpService],
})
export class HttpModule {}

View File

@@ -0,0 +1,58 @@
import axios from 'axios';
import { Observable } from 'rxjs/Observable';
import {
AxiosRequestConfig,
AxiosResponse,
} from './interfaces/axios.interfaces';
import 'rxjs/add/observable/fromPromise';
export class HttpService {
request<T = any>(config: AxiosRequestConfig): Observable<AxiosResponse<T>> {
return Observable.fromPromise(axios.request<T>(config));
}
get<T = any>(
url: string,
config?: AxiosRequestConfig,
): Observable<AxiosResponse<T>> {
return Observable.fromPromise(axios.get<T>(url, config));
}
delete(
url: string,
config?: AxiosRequestConfig,
): Observable<AxiosResponse<any>> {
return Observable.fromPromise(axios.delete(url, config));
}
head(
url: string,
config?: AxiosRequestConfig,
): Observable<AxiosResponse<any>> {
return Observable.fromPromise(axios.head(url, config));
}
post(
url: string,
data?,
config?: AxiosRequestConfig,
): Observable<AxiosResponse<any>> {
return Observable.fromPromise(axios.post(url, data, config));
}
put(
url: string,
data?,
config?: AxiosRequestConfig,
): Observable<AxiosResponse<any>> {
return Observable.fromPromise(axios.post(url, data, config));
}
patch(
url: string,
data?,
config?: AxiosRequestConfig,
): Observable<AxiosResponse<any>> {
return Observable.fromPromise(axios.post(url, data, config));
}
}

2
src/common/http/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export * from './http.module';
export * from './http.service';

View File

@@ -0,0 +1,127 @@
export interface AxiosTransformer {
(data: any, headers?: any): any;
}
export interface AxiosAdapter {
(config: AxiosRequestConfig): AxiosPromise<any>;
}
export interface AxiosBasicCredentials {
username: string;
password: string;
}
export interface AxiosProxyConfig {
host: string;
port: number;
}
export interface AxiosRequestConfig {
url?: string;
method?: string;
baseURL?: string;
transformRequest?: AxiosTransformer | AxiosTransformer[];
transformResponse?: AxiosTransformer | AxiosTransformer[];
headers?: any;
params?: any;
paramsSerializer?: (params: any) => string;
data?: any;
timeout?: number;
withCredentials?: boolean;
adapter?: AxiosAdapter;
auth?: AxiosBasicCredentials;
responseType?: string;
xsrfCookieName?: string;
xsrfHeaderName?: string;
onUploadProgress?: (progressEvent: any) => void;
onDownloadProgress?: (progressEvent: any) => void;
maxContentLength?: number;
validateStatus?: (status: number) => boolean;
maxRedirects?: number;
httpAgent?: any;
httpsAgent?: any;
proxy?: AxiosProxyConfig;
cancelToken?: CancelToken;
}
export interface AxiosResponse<T = any> {
data: T;
status: number;
statusText: string;
headers: any;
config: AxiosRequestConfig;
request?: any;
}
export interface AxiosError extends Error {
config: AxiosRequestConfig;
code?: string;
request?: any;
response?: AxiosResponse;
}
export interface AxiosPromise<T = any> extends Promise<AxiosResponse<T>> {
}
export interface CancelStatic {
new (message?: string): Cancel;
}
export interface Cancel {
message: string;
}
export interface Canceler {
(message?: string): void;
}
export interface CancelTokenStatic {
new (executor: (cancel: Canceler) => void): CancelToken;
source(): CancelTokenSource;
}
export interface CancelToken {
promise: Promise<Cancel>;
reason?: Cancel;
throwIfRequested(): void;
}
export interface CancelTokenSource {
token: CancelToken;
cancel: Canceler;
}
export interface AxiosInterceptorManager<V> {
use(onFulfilled?: (value: V) => V | Promise<V>, onRejected?: (error: any) => any): number;
eject(id: number): void;
}
export interface AxiosInstance {
defaults: AxiosRequestConfig;
interceptors: {
request: AxiosInterceptorManager<AxiosRequestConfig>;
response: AxiosInterceptorManager<AxiosResponse>;
};
request<T = any>(config: AxiosRequestConfig): AxiosPromise<T>;
get<T = any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>;
delete(url: string, config?: AxiosRequestConfig): AxiosPromise;
head(url: string, config?: AxiosRequestConfig): AxiosPromise;
post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>;
put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>;
patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>;
}
export interface AxiosStatic extends AxiosInstance {
(config: AxiosRequestConfig): AxiosPromise;
(url: string, config?: AxiosRequestConfig): AxiosPromise;
create(config?: AxiosRequestConfig): AxiosInstance;
Cancel: CancelStatic;
CancelToken: CancelTokenStatic;
isCancel(value: any): boolean;
all<T>(values: (T | Promise<T>)[]): Promise<T[]>;
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
}
declare const Axios: AxiosStatic;
export default Axios;

View File

@@ -31,6 +31,7 @@ export {
DynamicModule,
INestApplicationContext,
} from './interfaces';
export * from './interceptors';
export * from './services/logger.service';
export * from './pipes';
export * from './utils';

View File

@@ -0,0 +1,22 @@
import * as multer from 'multer';
import { NestInterceptor } from './../interfaces/nest-interceptor.interface';
import { Observable } from 'rxjs/Observable';
import { MulterOptions } from '../interfaces/external/multer-options.interface';
export function FileInterceptor(fieldName: string, options?: MulterOptions) {
const Interceptor = class implements NestInterceptor {
readonly upload = multer(options);
async intercept(
request,
context,
stream$: Observable<any>,
): Promise<Observable<any>> {
await new Promise((resolve, reject) =>
this.upload.single(fieldName)(request, request.res, resolve),
);
return stream$;
}
};
return Interceptor;
}

View File

@@ -0,0 +1,22 @@
import * as multer from 'multer';
import { NestInterceptor } from './../interfaces/nest-interceptor.interface';
import { Observable } from 'rxjs/Observable';
import { MulterOptions } from '../interfaces/external/multer-options.interface';
export function FilesInterceptor(fieldName: string, maxCount?: number, options?: MulterOptions) {
const Interceptor = class implements NestInterceptor {
readonly upload = multer(options);
async intercept(
request,
context,
stream$: Observable<any>,
): Promise<Observable<any>> {
await new Promise((resolve, reject) =>
this.upload.array(fieldName, maxCount)(request, request.res, resolve),
);
return stream$;
}
};
return Interceptor;
}

View File

@@ -0,0 +1,2 @@
export * from './file.interceptor';
export * from './files.interceptor';

View File

@@ -0,0 +1,51 @@
export interface MulterOptions {
dest?: string;
/** The storage engine to use for uploaded files. */
storage?: any;
/**
* An object specifying the size limits of the following optional properties. This object is passed to busboy
* directly, and the details of properties can be found on https://github.com/mscdex/busboy#busboy-methods
*/
limits?: {
/** Max field name size (Default: 100 bytes) */
fieldNameSize?: number;
/** Max field value size (Default: 1MB) */
fieldSize?: number;
/** Max number of non- file fields (Default: Infinity) */
fields?: number;
/** For multipart forms, the max file size (in bytes)(Default: Infinity) */
fileSize?: number;
/** For multipart forms, the max number of file fields (Default: Infinity) */
files?: number;
/** For multipart forms, the max number of parts (fields + files)(Default: Infinity) */
parts?: number;
/** For multipart forms, the max number of header key=> value pairs to parse Default: 2000(same as node's http). */
headerPairs?: number;
/** Keep the full path of files instead of just the base name (Default: false) */
preservePath?: boolean;
};
fileFilter?(
req,
file: {
/** Field name specified in the form */
fieldname: string;
/** Name of the file on the user's computer */
originalname: string;
/** Encoding type of the file */
encoding: string;
/** Mime type of the file */
mimetype: string;
/** Size of the file in bytes */
size: number;
/** The folder to which the file has been saved (DiskStorage) */
destination: string;
/** The name of the file within the destination (DiskStorage) */
filename: string;
/** Location of the uploaded file (DiskStorage) */
path: string;
/** A Buffer of the entire file (MemoryStorage) */
buffer: Buffer;
},
callback: (error: Error | null, acceptFile: boolean) => void,
): void;
}

View File

@@ -1,4 +1,5 @@
import { Metatype } from './metatype.interface';
import { LoggerService } from '../services/logger.service';
export interface INestApplicationContext {
/**

View File

@@ -44,6 +44,13 @@ export interface INestApplication extends INestApplicationContext {
*/
enable(...args): void;
/**
* Enables CORS (Cross-Origin Resource Sharing)
*
* @returns void
*/
enableCors(): void;
/**
* A wrapper function around native `express.disable()` method.
* Example `app.disable('x-powered-by')`

View File

@@ -14,6 +14,13 @@ export interface INestMicroservice extends INestApplicationContext {
*/
listen(callback: () => void);
/**
* Starts the microservice and can be awaited.
*
* @returns Promise
*/
listenAsync(): Promise<any>;
/**
* Setup Web Sockets Adapter, which will be used inside Gateways.
* Use, when you want to override default `socket.io` library.

View File

@@ -23,7 +23,7 @@ export class ValidationPipe implements PipeTransform<any> {
public async transform(value, metadata: ArgumentMetadata) {
const { metatype } = metadata;
if (!metatype || !this.toValidate(metatype)) {
if (!metatype || !this.toValidate(metadata)) {
return value;
}
const entity = plainToClass(metatype, value);
@@ -33,10 +33,14 @@ export class ValidationPipe implements PipeTransform<any> {
}
return this.isTransformEnabled
? entity
: Object.keys(this.validatorOptions) ? classToPlain(entity) : value;
: Object.keys(this.validatorOptions).length > 0 ? classToPlain(entity) : value;
}
private toValidate(metatype): boolean {
private toValidate(metadata: ArgumentMetadata): boolean {
const { metatype, type } = metadata;
if (type === 'custom') {
return false;
}
const types = [String, Boolean, Number, Array, Object];
return !types.find(type => metatype === type) && !isNil(metatype);
}

View File

@@ -1,59 +1,110 @@
import * as clc from 'cli-color';
import { NestEnvironment } from '../enums/nest-environment.enum';
import { Constructor } from '../utils/merge-with-values.util';
declare const process;
export class Logger {
private static lastTimestamp = null;
export interface LoggerService {
log(message: string): void;
error(message: string, trace: string): void;
warn(message: string): void;
}
export class Logger implements LoggerService {
private static prevTimestamp = null;
private static contextEnv = NestEnvironment.RUN;
private readonly yellow = clc.xterm(3);
private static logger: typeof Logger | LoggerService = Logger;
private static readonly yellow = clc.xterm(3);
constructor(
private readonly context: string,
private readonly printTimestamps = false,
private readonly isTimeDiffEnabled = false,
) {}
public static setMode(mode: NestEnvironment) {
log(message: string) {
const { logger } = Logger;
(logger as typeof Logger).log(
message,
this.context,
this.isTimeDiffEnabled,
);
}
error(message: string, trace = '') {
const { logger } = Logger;
(logger as typeof Logger).error(
message,
trace,
this.context,
this.isTimeDiffEnabled,
);
}
warn(message: string) {
const { logger } = Logger;
(logger as typeof Logger).warn(
message,
this.context,
this.isTimeDiffEnabled,
);
}
static overrideLogger(logger: LoggerService) {
this.logger = logger;
}
static setMode(mode: NestEnvironment) {
this.contextEnv = mode;
}
public log(message: string) {
this.printMessage(message, clc.green);
static log(message: string, context = '', isTimeDiffEnabled = true) {
this.printMessage(message, clc.green, context, isTimeDiffEnabled);
}
public error(message: string, trace = '') {
this.printMessage(message, clc.red);
static error(
message: string,
trace = '',
context = '',
isTimeDiffEnabled = true,
) {
this.printMessage(message, clc.red, context, isTimeDiffEnabled);
this.printStackTrace(trace);
}
public warn(message: string) {
this.printMessage(message, clc.yellow);
static warn(message: string, context = '', isTimeDiffEnabled = true) {
this.printMessage(message, clc.yellow, context, isTimeDiffEnabled);
}
private printMessage(message: string, color: (msg: string) => string) {
private static printMessage(
message: string,
color: (msg: string) => string,
context: string = '',
isTimeDiffEnabled?: boolean,
) {
if (Logger.contextEnv === 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(this.yellow(`[${context}] `));
process.stdout.write(color(message));
this.printTimestamp();
this.printTimestamp(isTimeDiffEnabled);
process.stdout.write(`\n`);
}
private printTimestamp() {
const includeTimestamp = Logger.lastTimestamp && this.printTimestamps;
private static printTimestamp(isTimeDiffEnabled?: boolean) {
const includeTimestamp = Logger.prevTimestamp && isTimeDiffEnabled;
if (includeTimestamp) {
process.stdout.write(
this.yellow(` +${Date.now() - Logger.lastTimestamp}ms`),
this.yellow(` +${Date.now() - Logger.prevTimestamp}ms`),
);
}
Logger.lastTimestamp = Date.now();
Logger.prevTimestamp = Date.now();
}
private printStackTrace(trace: string) {
if (Logger.contextEnv === NestEnvironment.TEST || !trace) return;
private static printStackTrace(trace: string) {
if (this.contextEnv === NestEnvironment.TEST || !trace) return;
process.stdout.write(trace);
process.stdout.write(`\n`);

View File

@@ -0,0 +1,18 @@
import 'reflect-metadata';
import { expect } from 'chai';
import { Render } from '../../decorators/http/render.decorator';
import { RENDER_METADATA } from '../../constants';
describe('@Render', () => {
const template = 'template';
class Test {
@Render('template')
public static test() {}
}
it('should enhance method with expected template string', () => {
const metadata = Reflect.getMetadata(RENDER_METADATA, Test.test);
expect(metadata).to.be.eql(template);
});
});

View File

@@ -0,0 +1,30 @@
import * as sinon from 'sinon';
import { expect } from 'chai';
import { FileInterceptor } from './../../interceptors/file.interceptor';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
describe('FileInterceptor', () => {
it('should return metatype with expected structure', async () => {
const targetClass = FileInterceptor('file');
expect(targetClass.prototype.intercept).to.not.be.undefined;
});
describe('intercept', () => {
let stream$;
beforeEach(() => {
stream$ = Observable.of('test');
});
it('should call single() with expected params', async () => {
const fieldName = 'file';
const target = new (FileInterceptor(fieldName));
const callback = (req, res, next) => next();
const singleSpy = sinon.stub((target as any).upload, 'single').returns(callback);
const req = {};
await target.intercept(req, null, stream$);
expect(singleSpy.called).to.be.true;
expect(singleSpy.calledWith(fieldName)).to.be.true;
});
});
});

View File

@@ -0,0 +1,31 @@
import * as sinon from 'sinon';
import { expect } from 'chai';
import { FilesInterceptor } from './../../interceptors/files.interceptor';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
describe('FilesInterceptor', () => {
it('should return metatype with expected structure', async () => {
const targetClass = FilesInterceptor('file');
expect(targetClass.prototype.intercept).to.not.be.undefined;
});
describe('intercept', () => {
let stream$;
beforeEach(() => {
stream$ = Observable.of('test');
});
it('should call array() with expected params', async () => {
const fieldName = 'file';
const maxCount = 10;
const target = new (FilesInterceptor(fieldName, maxCount));
const callback = (req, res, next) => next();
const arraySpy = sinon.stub((target as any).upload, 'array').returns(callback);
await target.intercept({}, null, stream$);
expect(arraySpy.called).to.be.true;
expect(arraySpy.calledWith(fieldName, maxCount)).to.be.true;
});
});
});

View File

@@ -1,3 +1,4 @@
import * as cors from 'cors';
import * as http from 'http';
import * as https from 'https';
import * as optional from 'optional';
@@ -198,7 +199,11 @@ export class NestApplication extends NestApplicationContext
}
public enable(...args) {
this.express.disable(...args);
this.express.enable(...args);
}
public enableCors() {
this.express.use(cors());
}
public async listen(port: number | string, callback?: () => void);

View File

@@ -24,6 +24,10 @@ export class RouteParamsFactory implements IRouteParamsFactory {
return data ? req.headers[data] : req.headers;
case RouteParamtypes.SESSION:
return req.session;
case RouteParamtypes.FILE:
return req.file;
case RouteParamtypes.FILES:
return req.files;
default:
return null;
}

View File

@@ -4,6 +4,7 @@ import {
PARAMTYPES_METADATA,
HTTP_CODE_METADATA,
CUSTOM_ROUTE_AGRS_METADATA,
RENDER_METADATA,
} from '@nestjs/common/constants';
import {
isUndefined,
@@ -81,13 +82,18 @@ export class RouterExecutionContext {
const fnCanActivate = this.createGuardsFn(guards, instance, callback);
const fnApplyPipes = this.createPipesFn(pipes, paramsOptions);
const fnHandleResponse = this.createHandleResponseFn(
callback,
isResponseHandled,
httpStatusCode,
);
return async (req, res, next) => {
const args = this.createNullArray(argsLength);
fnCanActivate && await fnCanActivate(req);
fnCanActivate && (await fnCanActivate(req));
const handler = async () => {
fnApplyPipes && await fnApplyPipes(args, req, res, next);
fnApplyPipes && (await fnApplyPipes(args, req, res, next));
return callback.apply(instance, args);
};
const result = await this.interceptorsConsumer.intercept(
@@ -97,7 +103,7 @@ export class RouterExecutionContext {
callback,
handler,
);
!isResponseHandled && await this.responseController.apply(result, res, httpStatusCode)
await fnHandleResponse(result, res);
};
}
@@ -124,6 +130,10 @@ export class RouterExecutionContext {
return Reflect.getMetadata(HTTP_CODE_METADATA, callback);
}
public reflectRenderTemplate(callback): boolean {
return Reflect.getMetadata(RENDER_METADATA, callback);
}
public getArgumentsLength(
keys: string[],
metadata: RouteParamsMetadata,
@@ -242,4 +252,18 @@ export class RouterExecutionContext {
};
return paramsOptions.length ? pipesFn : null;
}
public createHandleResponseFn(
callback,
isResponseHandled: boolean,
httpStatusCode: number,
) {
const renderTemplate = this.reflectRenderTemplate(callback);
if (!!renderTemplate) {
return (result, res) => res.render(renderTemplate, result);
}
return async (result, res) =>
!isResponseHandled &&
(await this.responseController.apply(result, res, httpStatusCode));
}
}

View File

@@ -12,6 +12,11 @@ export class RouterResponseController {
return isObject(result) ? res.json(result) : res.send(String(result));
}
public async render(resultOrDeffered, response, template: string) {
const result = await this.transformToResult(resultOrDeffered);
response.render(template, result);
}
public async transformToResult(resultOrDeffered) {
if (resultOrDeffered instanceof Promise) {
return await resultOrDeffered;

Some files were not shown because too many files have changed in this diff Show More