chore() resolve conflicts (merge)

This commit is contained in:
Kamil Myśliwiec
2018-12-21 10:19:24 +01:00
129 changed files with 1615 additions and 1083 deletions

View File

@@ -12,6 +12,16 @@ const packages = {
microservices: ts.createProject('packages/microservices/tsconfig.json'),
websockets: ts.createProject('packages/websockets/tsconfig.json'),
testing: ts.createProject('packages/testing/tsconfig.json'),
'platform-express': ts.createProject(
'packages/platform-express/tsconfig.json',
),
'platform-fastify': ts.createProject(
'packages/platform-fastify/tsconfig.json',
),
'platform-socket.io': ts.createProject(
'packages/platform-socket.io/tsconfig.json',
),
'platform-ws': ts.createProject('packages/platform-ws/tsconfig.json'),
};
const modules = Object.keys(packages);
const source = 'packages';
@@ -34,7 +44,11 @@ gulp.task('copy-misc', function() {
.pipe(gulp.dest(`${source}/core`))
.pipe(gulp.dest(`${source}/microservices`))
.pipe(gulp.dest(`${source}/websockets`))
.pipe(gulp.dest(`${source}/testing`));
.pipe(gulp.dest(`${source}/testing`))
.pipe(gulp.dest(`${source}/platform-fastify`))
.pipe(gulp.dest(`${source}/platform-express`))
.pipe(gulp.dest(`${source}/platform-ws`))
.pipe(gulp.dest(`${source}/platform-socket.io`));
});
gulp.task('clean:output', function() {

View File

@@ -1,7 +1,8 @@
import { INestApplication } from '@nestjs/common';
import { ExpressAdapter } from '@nestjs/platform-express';
import { Test } from '@nestjs/testing';
import * as express from 'express';
import * as request from 'supertest';
import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { ApplicationModule } from '../src/app.module';
describe('Hello world (express instance)', () => {
@@ -11,10 +12,9 @@ describe('Hello world (express instance)', () => {
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [ApplicationModule],
})
.compile();
}).compile();
app = module.createNestApplication(express());
app = module.createNestApplication(new ExpressAdapter(express()));
server = app.getHttpServer();
await app.init();
});

View File

@@ -1,19 +1,22 @@
import { INestApplication } from '@nestjs/common';
import { INestFastifyApplication } from '@nestjs/common/interfaces/nest-fastify-application.interface';
import { FastifyAdapter } from '@nestjs/core/adapters/fastify-adapter';
import {
FastifyAdapter,
INestFastifyApplication,
} from '@nestjs/platform-fastify';
import { Test } from '@nestjs/testing';
import { expect } from 'chai';
import { ApplicationModule } from '../src/app.module';
describe('Hello world (fastify adapter)', () => {
let app: INestApplication & INestFastifyApplication;
let app: INestFastifyApplication;
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [ApplicationModule],
}).compile();
app = module.createNestApplication(new FastifyAdapter());
app = module.createNestApplication<INestFastifyApplication>(
new FastifyAdapter(),
);
await app.init();
});

View File

@@ -1,24 +1,30 @@
import * as request from 'supertest';
import { Test } from '@nestjs/testing';
import { INestApplication, Injectable } from '@nestjs/common';
import { ApplicationModule } from '../src/app.module';
import {
CallHandler,
ExecutionContext,
INestApplication,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { Test } from '@nestjs/testing';
import { of } from 'rxjs';
import { map } from 'rxjs/operators';
import * as request from 'supertest';
import { ApplicationModule } from '../src/app.module';
const RETURN_VALUE = 'test';
@Injectable()
export class OverrideInterceptor {
intercept(context, stream) {
export class OverrideInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler) {
return of(RETURN_VALUE);
}
}
@Injectable()
export class TransformInterceptor {
intercept(context, stream) {
return stream.pipe(map(data => ({ data })));
intercept(context: ExecutionContext, next: CallHandler) {
return next.handle().pipe(map(data => ({ data })));
}
}
@@ -41,7 +47,7 @@ describe('Interceptors', () => {
app = (await createTestModule(
new OverrideInterceptor(),
)).createNestApplication();
await app.init();
return request(app.getHttpServer())
.get('/hello')
@@ -52,7 +58,7 @@ describe('Interceptors', () => {
app = (await createTestModule(
new TransformInterceptor(),
)).createNestApplication();
await app.init();
return request(app.getHttpServer())
.get('/hello')
@@ -63,7 +69,7 @@ describe('Interceptors', () => {
app = (await createTestModule(
new TransformInterceptor(),
)).createNestApplication();
await app.init();
return request(app.getHttpServer())
.get('/hello/stream')
@@ -74,7 +80,7 @@ describe('Interceptors', () => {
app = (await createTestModule(
new TransformInterceptor(),
)).createNestApplication();
await app.init();
return request(app.getHttpServer())
.get('/hello/async')

View File

@@ -1,4 +1,4 @@
import { Get, BadRequestException, Controller } from '@nestjs/common';
import { BadRequestException, Controller, Get } from '@nestjs/common';
@Controller()
export class ErrorsController {
@@ -13,6 +13,10 @@ export class ErrorsController {
}
throwError() {
throw new BadRequestException('Integration test');
throw new BadRequestException({
statusCode: 400,
error: 'Bad Request',
message: 'Integration test',
});
}
}

View File

@@ -1,8 +1,7 @@
import * as express from 'express';
import * as request from 'supertest';
import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { Transport } from '@nestjs/microservices';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { MqttBroadcastController } from '../src/mqtt/mqtt-broadcast.controller';
describe('MQTT transport', () => {
@@ -14,8 +13,9 @@ describe('MQTT transport', () => {
controllers: [MqttBroadcastController],
}).compile();
server = express();
app = module.createNestApplication(server);
app = module.createNestApplication();
server = app.getHttpAdapter().getInstance();
app.connectMicroservice({
transport: Transport.MQTT,
});

View File

@@ -1,8 +1,7 @@
import * as express from 'express';
import * as request from 'supertest';
import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { Transport } from '@nestjs/microservices';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { NatsBroadcastController } from '../src/nats/nats-broadcast.controller';
describe('NATS transport', () => {
@@ -14,8 +13,9 @@ describe('NATS transport', () => {
controllers: [NatsBroadcastController],
}).compile();
server = express();
app = module.createNestApplication(server);
app = module.createNestApplication();
server = app.getHttpAdapter().getInstance();
app.connectMicroservice({
transport: Transport.NATS,
});

View File

@@ -1,9 +1,7 @@
import * as express from 'express';
import * as request from 'supertest';
import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { Transport } from '@nestjs/microservices';
import { RedisController } from '../src/redis/redis.controller';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { RedisBroadcastController } from '../src/redis/redis-broadcast.controller';
describe('REDIS transport', () => {
@@ -15,8 +13,9 @@ describe('REDIS transport', () => {
controllers: [RedisBroadcastController],
}).compile();
server = express();
app = module.createNestApplication(server);
app = module.createNestApplication();
server = app.getHttpAdapter().getInstance();
app.connectMicroservice({
transport: Transport.REDIS,
});

View File

@@ -1,7 +1,6 @@
import { INestApplication } from '@nestjs/common';
import { Transport } from '@nestjs/microservices';
import { Test } from '@nestjs/testing';
import * as express from 'express';
import * as request from 'supertest';
import { DisconnectedClientController } from '../src/disconnected.controller';
@@ -14,8 +13,9 @@ describe('Disconnected client', () => {
controllers: [DisconnectedClientController],
}).compile();
server = express();
app = module.createNestApplication(server);
app = module.createNestApplication();
server = app.getHttpAdapter().getInstance();
await app.init();
});

View File

@@ -1,7 +1,6 @@
import { INestApplication } from '@nestjs/common';
import { Transport } from '@nestjs/microservices';
import { Test } from '@nestjs/testing';
import * as express from 'express';
import { join } from 'path';
import * as request from 'supertest';
import { GrpcController } from '../src/grpc/grpc.controller';
@@ -15,8 +14,9 @@ describe('GRPC transport', () => {
controllers: [GrpcController],
}).compile();
server = express();
app = module.createNestApplication(server);
app = module.createNestApplication();
server = app.getHttpAdapter().getInstance();
app.connectMicroservice({
transport: Transport.GRPC,
options: {

View File

@@ -1,7 +1,6 @@
import { INestApplication } from '@nestjs/common';
import { Transport } from '@nestjs/microservices';
import { Test } from '@nestjs/testing';
import * as express from 'express';
import * as request from 'supertest';
import { MqttController } from '../src/mqtt/mqtt.controller';
@@ -14,8 +13,9 @@ describe('MQTT transport', () => {
controllers: [MqttController],
}).compile();
server = express();
app = module.createNestApplication(server);
app = module.createNestApplication();
server = app.getHttpAdapter().getInstance();
app.connectMicroservice({
transport: Transport.MQTT,
});

View File

@@ -1,7 +1,6 @@
import { INestApplication } from '@nestjs/common';
import { Transport } from '@nestjs/microservices';
import { Test } from '@nestjs/testing';
import * as express from 'express';
import * as request from 'supertest';
import { NatsController } from '../src/nats/nats.controller';
@@ -14,8 +13,9 @@ describe('NATS transport', () => {
controllers: [NatsController],
}).compile();
server = express();
app = module.createNestApplication(server);
app = module.createNestApplication();
server = app.getHttpAdapter().getInstance();
app.connectMicroservice({
transport: Transport.NATS,
options: {

View File

@@ -1,7 +1,6 @@
import { INestApplication } from '@nestjs/common';
import { Transport } from '@nestjs/microservices';
import { Test } from '@nestjs/testing';
import * as express from 'express';
import * as request from 'supertest';
import { RedisController } from '../src/redis/redis.controller';
@@ -14,8 +13,9 @@ describe('REDIS transport', () => {
controllers: [RedisController],
}).compile();
server = express();
app = module.createNestApplication(server);
app = module.createNestApplication();
server = app.getHttpAdapter().getInstance();
app.connectMicroservice({
transport: Transport.REDIS,
});

View File

@@ -1,7 +1,6 @@
import { INestApplication } from '@nestjs/common';
import { Transport } from '@nestjs/microservices';
import { Test } from '@nestjs/testing';
import * as express from 'express';
import * as request from 'supertest';
import { RMQController } from '../src/rmq/rmq.controller';
@@ -14,8 +13,9 @@ describe('RabbitMQ transport', () => {
controllers: [RMQController],
}).compile();
server = express();
app = module.createNestApplication(server);
app = module.createNestApplication();
server = app.getHttpAdapter().getInstance();
app.connectMicroservice({
transport: Transport.RMQ,
options: {

View File

@@ -1,7 +1,6 @@
import { INestApplication } from '@nestjs/common';
import { Transport } from '@nestjs/microservices';
import { Test } from '@nestjs/testing';
import * as express from 'express';
import * as request from 'supertest';
import { ApplicationModule } from '../src/app.module';
@@ -14,8 +13,9 @@ describe('RPC transport', () => {
imports: [ApplicationModule],
}).compile();
server = express();
app = module.createNestApplication(server);
app = module.createNestApplication();
server = app.getHttpAdapter().getInstance();
app.connectMicroservice({
transport: Transport.TCP,
});

View File

@@ -15,7 +15,6 @@ async function createNestApp(...gateways): Promise<INestApplication> {
}
describe('WebSocketGateway', () => {
const event = 'push';
let ws, app;
it(`should handle message (2nd port)`, async () => {

View File

@@ -1,6 +1,6 @@
import { INestApplication } from '@nestjs/common';
import { WsAdapter } from '@nestjs/platform-ws';
import { Test } from '@nestjs/testing';
import { WsAdapter } from '@nestjs/websockets/adapters/ws-adapter';
import { expect } from 'chai';
import * as WebSocket from 'ws';
import { ApplicationGateway } from '../src/app.gateway';

104
package-lock.json generated
View File

@@ -1698,9 +1698,9 @@
"dev": true
},
"buffer-from": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz",
"integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true
},
"buffer-more-ints": {
@@ -4984,6 +4984,30 @@
}
}
},
"fastify-cors": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/fastify-cors/-/fastify-cors-0.2.0.tgz",
"integrity": "sha512-bw14FmjHm8oF4TDLkwj2TpssH6O2gE0NpsRqLe7F1Gh9Jf30Lx9ZzIznhqaAKOYS+LJqLIt5snurv7urgqYntA==",
"requires": {
"fastify-plugin": "^1.2.0",
"vary": "^1.1.2"
},
"dependencies": {
"fastify-plugin": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-1.4.0.tgz",
"integrity": "sha512-l6uqDyBp3gBjLQRAi3j2NwSvlbe9LuqULZugnO9iRFfYHWd2SpsZBLI1l4Jakk0VMGfYlB322JPIPYh/2qSHig==",
"requires": {
"semver": "^5.5.0"
}
},
"semver": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
}
}
},
"fastify-formbody": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fastify-formbody/-/fastify-formbody-2.0.0.tgz",
@@ -8479,6 +8503,11 @@
"sshpk": "^1.7.0"
}
},
"http2": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/http2/-/http2-3.3.7.tgz",
"integrity": "sha512-puSi8M8WNlFJm9Pk4c/Mbz9Gwparuj3gO9/RRO5zv6piQ0FY+9Qywp0PdWshYgsMJSalixFY7eC6oPu0zRxLAQ=="
},
"husky": {
"version": "0.14.3",
"resolved": "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz",
@@ -10475,9 +10504,9 @@
}
},
"make-error": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz",
"integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==",
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz",
"integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==",
"dev": true
},
"make-iterator": {
@@ -13432,9 +13461,9 @@
"dev": true
},
"prettier": {
"version": "1.10.2",
"resolved": "http://192.168.228.42:5000/prettier/-/prettier-1.10.2.tgz",
"integrity": "sha512-TcdNoQIWFoHblurqqU6d1ysopjq7UX0oRcT/hJ8qvBAELiYWn+Ugf0AXdnzISEJ7vuhNnQ98N8jR8Sh53x4IZg==",
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.15.3.tgz",
"integrity": "sha512-gAU9AGAPMaKb3NNSUUuhhFAS7SCO4ALTN4nRIn6PJ075Qd28Yn2Ig2ahEJWdJwJmlEBTUfC7mMUSFy8MwsOCfg==",
"dev": true
},
"pretty-format": {
@@ -15431,47 +15460,21 @@
}
},
"ts-node": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-6.0.1.tgz",
"integrity": "sha512-LDS8WJRTEztvQEXbRK/0l/apWE0BNR/USGUhVcJDe2/hbNiB/v/lCqk6YJzgwKjScgdWOAhPQsfur7hmQ1Y1jA==",
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz",
"integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==",
"dev": true,
"requires": {
"arrify": "^1.0.0",
"chalk": "^2.3.0",
"buffer-from": "^1.1.0",
"diff": "^3.1.0",
"make-error": "^1.1.1",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"source-map-support": "^0.5.3",
"source-map-support": "^0.5.6",
"yn": "^2.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"chalk": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -15479,23 +15482,14 @@
"dev": true
},
"source-map-support": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.5.tgz",
"integrity": "sha512-mR7/Nd5l1z6g99010shcXJiNEaf3fEtmLhRB/sBcQVJGodcHCULPp2y4Sfa43Kv2zq7T+Izmfp/WHCR6dYkQCA==",
"version": "0.5.9",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz",
"integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==",
"dev": true,
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"supports-color": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
@@ -15716,9 +15710,9 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"typescript": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.1.tgz",
"integrity": "sha512-jw7P2z/h6aPT4AENXDGjcfHTu5CSqzsbZc6YlUIebTyBAq8XaKp78x7VcSh30xwSCcsu5irZkYZUSFP1MrAMbg==",
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz",
"integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==",
"dev": true
},
"uglify-js": {

View File

@@ -52,9 +52,11 @@
"fast-json-stringify": "^1.5.4",
"fast-safe-stringify": "^1.2.0",
"fastify": "^1.1.1",
"fastify-cors": "^0.2.0",
"fastify-formbody": "^2.0.0",
"fastify-multipart": "^0.4.1",
"grpc": "^1.14.1",
"http2": "^3.3.7",
"iterare": "0.0.8",
"json-socket": "^0.2.1",
"mqtt": "^2.16.0",
@@ -114,14 +116,14 @@
"mocha": "^3.2.0",
"nodemon": "^1.18.4",
"nyc": "^10.1.2",
"prettier": "^1.9.2",
"prettier": "^1.15.3",
"sinon": "^2.1.0",
"sinon-chai": "^2.8.0",
"socket.io-client": "^2.0.4",
"supertest": "^3.0.0",
"ts-node": "^6.0.0",
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"typescript": "^3.1.6"
"typescript": "^3.2.2"
},
"collective": {
"type": "opencollective",
@@ -137,8 +139,7 @@
"exclude": [
"node_modules/",
"packages/**/*.spec.ts",
"packages/core/adapters/*.ts",
"packages/websockets/adapters/*.ts",
"packages/**/adapters/*.ts",
"packages/**/nest-*.ts",
"packages/core/errors/**/*",
"packages/common/exceptions/*.ts",

View File

@@ -1,4 +0,0 @@
export enum NestEnvironment {
RUN,
TEST,
}

View File

@@ -10,7 +10,6 @@ export * from './cache';
export * from './decorators';
export * from './enums';
export * from './exceptions';
export * from './files';
export * from './http';
export {
ArgumentMetadata,
@@ -24,8 +23,6 @@ export {
HttpServer,
INestApplication,
INestApplicationContext,
INestExpressApplication,
INestFastifyApplication,
INestMicroservice,
MiddlewareConsumer,
MiddlewareFunction,
@@ -44,8 +41,9 @@ export {
ValidationError,
WebSocketAdapter,
WsExceptionFilter,
WsMessageHandler,
} from './interfaces';
export * from './pipes';
export * from './serializer';
export * from './services/logger.service';
export * from './services';
export * from './utils';

View File

@@ -1,4 +1,6 @@
import { RequestMethod } from '../../enums';
import { CorsOptions } from './../../interfaces/external/cors-options.interface';
import { NestApplicationOptions } from './../../interfaces/nest-application-options.interface';
export type ErrorHandler<TRequest = any, TResponse = any> = (
error: any,
@@ -54,6 +56,9 @@ export interface HttpServer<TRequest = any, TResponse = any> {
getRequestMethod?(request: TRequest): string;
getRequestUrl?(request: TResponse): string;
getInstance(): any;
registerParserMiddleware(): any;
enableCors(options: CorsOptions): any;
getHttpServer(): any;
initHttpServer(options: NestApplicationOptions): void;
close(): any;
}

View File

@@ -24,8 +24,6 @@ export * from './modules/on-init.interface';
export * from './modules/provider.interface';
export * from './nest-application-context.interface';
export * from './nest-application.interface';
export * from './nest-express-application.interface';
export * from './nest-fastify-application.interface';
export * from './nest-microservice.interface';
export * from './on-application-bootstrap.interface';
export * from './request-mapping-metadata.interface';

View File

@@ -1,16 +1,21 @@
import { Observable } from 'rxjs';
export interface WebSocketAdapter<T = any> {
create(port: number, options?: T): any;
bindClientConnect(server: any, callback: (...args: any[]) => void): any;
bindClientDisconnect?(client: any, callback: (...args: any[]) => void): any;
export interface WsMessageHandler<T = string> {
message: T;
callback: (...args: any[]) => Observable<any> | Promise<any>;
}
export interface WebSocketAdapter<
TServer = any,
TClient = any,
TOptions = any
> {
create(port: number, options?: TOptions): TServer;
bindClientConnect(server: TServer, callback: Function): any;
bindClientDisconnect?(client: TClient, callback: Function): any;
bindMessageHandlers(
client: any,
handlers: Array<{
message: any;
callback: (...args: any[]) => Observable<any> | Promise<any> | any;
}>,
client: TClient,
handlers: WsMessageHandler[],
transform: (data: any) => Observable<any>,
): any;
close(server: any): any;
close(server: TServer): any;
}

View File

@@ -11,7 +11,6 @@
"dependencies": {
"axios": "0.18.0",
"cli-color": "1.2.0",
"multer": "1.3.0",
"uuid": "3.3.2"
},
"peerDependencies": {

View File

@@ -0,0 +1 @@
export * from './logger.service';

View File

@@ -1,62 +1,50 @@
import * as clc from 'cli-color';
import { Injectable, Optional } from '../decorators';
import { NestEnvironment } from '../enums/nest-environment.enum';
import { isObject } from '../utils/shared.utils';
declare const process: any;
const yellow = clc.xterm(3);
export interface LoggerService {
log(message: any, context?: string): any;
error(message: any, trace?: string, context?: string): any;
warn(message: any, context?: string): any;
log(message: any, context?: string);
error(message: any, trace?: string, context?: string);
warn(message: any, context?: string);
}
@Injectable()
export class Logger implements LoggerService {
private static prevTimestamp?: number;
private static contextEnvironment = NestEnvironment.RUN;
private static logger?: typeof Logger | LoggerService = Logger;
private static readonly yellow = clc.xterm(3);
private static lastTimestamp?: number;
private static instance?: typeof Logger | LoggerService = Logger;
constructor(
@Optional() private readonly context?: string,
@Optional() private readonly isTimeDiffEnabled = false,
@Optional() private readonly isTimestampEnabled = false,
) {}
log(message: any, context?: string) {
const { logger } = Logger;
if (logger === this) {
Logger.log(message, context || this.context, this.isTimeDiffEnabled);
return;
}
logger && logger.log.call(logger, message, context || this.context);
error(message: any, trace = '', context?: string) {
const instance = this.getInstance();
instance &&
instance.error.call(instance, message, trace, context || this.context);
}
error(message: any, trace = '', context?: string) {
const { logger } = Logger;
if (logger === this) {
Logger.error(message, trace, context || this.context);
return;
}
logger &&
logger.error.call(logger, message, trace, context || this.context);
log(message: any, context?: string) {
this.callFunction('log', message, context);
}
warn(message: any, context?: string) {
const { logger } = Logger;
if (logger === this) {
Logger.warn(message, context || this.context, this.isTimeDiffEnabled);
return;
}
logger && logger.warn.call(logger, message, context || this.context);
this.callFunction('warn', message, context);
}
debug(message: any, context?: string) {
this.callFunction('debug', message, context);
}
verbose(message: any, context?: string) {
this.callFunction('verbose', message, context);
}
static overrideLogger(logger: LoggerService | boolean) {
this.logger = logger ? (logger as LoggerService) : undefined;
}
static setMode(mode: NestEnvironment) {
this.contextEnvironment = mode;
this.instance = isObject(logger) ? (logger as LoggerService) : undefined;
}
static log(message: any, context = '', isTimeDiffEnabled = true) {
@@ -77,38 +65,65 @@ export class Logger implements LoggerService {
this.printMessage(message, clc.yellow, context, isTimeDiffEnabled);
}
static debug(message: any, context = '', isTimeDiffEnabled = true) {
this.printMessage(message, clc.magentaBright, context, isTimeDiffEnabled);
}
static verbose(message: any, context = '', isTimeDiffEnabled = true) {
this.printMessage(message, clc.cyanBright, context, isTimeDiffEnabled);
}
private callFunction(
name: 'log' | 'warn' | 'debug' | 'verbose',
message: any,
context?: string,
) {
const instance = this.getInstance();
const func = instance && (instance as typeof Logger)[name];
func &&
func.call(
instance,
message,
context || this.context,
this.isTimestampEnabled,
);
}
private getInstance(): typeof Logger | LoggerService {
const { instance } = Logger;
return instance === this ? Logger : instance;
}
private static printMessage(
message: any,
color: (message: string) => string,
context: string = '',
isTimeDiffEnabled?: boolean,
) {
if (Logger.contextEnvironment === NestEnvironment.TEST) {
return;
}
const output = isObject(message) ? JSON.stringify(message, null, 2) : message;
const output = isObject(message)
? `${color('Object:')}\n${JSON.stringify(message, null, 2)}\n`
: color(message);
process.stdout.write(color(`[Nest] ${process.pid} - `));
process.stdout.write(`${new Date(Date.now()).toLocaleString()} `);
context && process.stdout.write(this.yellow(`[${context}] `));
process.stdout.write(color(output));
context && process.stdout.write(yellow(`[${context}] `));
process.stdout.write(output);
this.printTimestamp(isTimeDiffEnabled);
process.stdout.write(`\n`);
}
private static printTimestamp(isTimeDiffEnabled?: boolean) {
const includeTimestamp = Logger.prevTimestamp && isTimeDiffEnabled;
const includeTimestamp = Logger.lastTimestamp && isTimeDiffEnabled;
if (includeTimestamp) {
process.stdout.write(
this.yellow(` +${Date.now() - Logger.prevTimestamp}ms`),
);
process.stdout.write(yellow(` +${Date.now() - Logger.lastTimestamp}ms`));
}
Logger.prevTimestamp = Date.now();
Logger.lastTimestamp = Date.now();
}
private static printStackTrace(trace: string) {
if (this.contextEnvironment === NestEnvironment.TEST || !trace) {
if (!trace) {
return;
}
process.stdout.write(trace);

View File

@@ -1,152 +0,0 @@
import { RequestMethod } from '@nestjs/common';
import { HttpServer, RequestHandler } from '@nestjs/common/interfaces';
import { ServeStaticOptions } from '@nestjs/common/interfaces/external/serve-static-options.interface';
import { isNil, isObject } from '@nestjs/common/utils/shared.utils';
import * as express from 'express';
import { RouterMethodFactory } from '../helpers/router-method-factory';
export class ExpressAdapter implements HttpServer {
private readonly routerMethodFactory = new RouterMethodFactory();
private httpServer: any = null;
constructor(private readonly instance: any) {}
use(...args: any[]) {
return this.instance.use(...args);
}
get(handler: RequestHandler);
get(path: any, handler: RequestHandler);
get(...args: any[]) {
return this.instance.get(...args);
}
post(handler: RequestHandler);
post(path: any, handler: RequestHandler);
post(...args: any[]) {
return this.instance.post(...args);
}
head(handler: RequestHandler);
head(path: any, handler: RequestHandler);
head(...args: any[]) {
return this.instance.head(...args);
}
delete(handler: RequestHandler);
delete(path: any, handler: RequestHandler);
delete(...args: any[]) {
return this.instance.delete(...args);
}
put(handler: RequestHandler);
put(path: any, handler: RequestHandler);
put(...args: any[]) {
return this.instance.put(...args);
}
patch(handler: RequestHandler);
patch(path: any, handler: RequestHandler);
patch(...args: any[]) {
return this.instance.patch(...args);
}
options(handler: RequestHandler);
options(path: any, handler: RequestHandler);
options(...args: any[]) {
return this.instance.options(...args);
}
listen(port: string | number, callback?: () => void);
listen(port: string | number, hostname: string, callback?: () => void);
listen(port: any, hostname?: any, callback?: any) {
return this.instance.listen(port, hostname, callback);
}
reply(response, body: any, statusCode: number) {
const res = response.status(statusCode);
if (isNil(body)) {
return res.send();
}
return isObject(body) ? res.json(body) : res.send(String(body));
}
render(response, view: string, options: any) {
return response.render(view, options);
}
setErrorHandler(handler: Function) {
return this.use(handler);
}
setNotFoundHandler(handler: Function) {
return this.use(handler);
}
setHeader(response, name: string, value: string) {
return response.set(name, value);
}
getHttpServer<T = any>(): T {
return this.httpServer as T;
}
setHttpServer(httpServer) {
this.httpServer = httpServer;
}
getInstance<T = any>(): T {
return this.instance as T;
}
close() {
return this.instance.close();
}
set(...args: any[]) {
return this.instance.set(...args);
}
enable(...args: any[]) {
return this.instance.enable(...args);
}
disable(...args: any[]) {
return this.instance.disable(...args);
}
engine(...args: any[]) {
return this.instance.engine(...args);
}
useStaticAssets(path: string, options: ServeStaticOptions) {
if (options && options.prefix) {
return this.use(options.prefix, express.static(path, options));
}
return this.use(express.static(path, options));
}
setBaseViewsDir(path: string) {
return this.set('views', path);
}
setViewEngine(engine: string) {
return this.set('view engine', engine);
}
getRequestMethod(request): string {
return request.method;
}
getRequestUrl(request): string {
return request.url;
}
createMiddlewareFactory(
requestMethod: RequestMethod,
): (path: string, callback: Function) => any {
return this.routerMethodFactory
.get(this.instance, requestMethod)
.bind(this.instance);
}
}

View File

@@ -1,8 +0,0 @@
import * as express from 'express';
import { ExpressAdapter } from './express-adapter';
export class ExpressFactory {
public static create(): any {
return new ExpressAdapter(express());
}
}

View File

@@ -1,155 +0,0 @@
import { RequestMethod } from '@nestjs/common';
import { ErrorHandler, RequestHandler } from '@nestjs/common/interfaces';
import { loadPackage } from '@nestjs/common/utils/load-package.util';
import * as pathToRegexp from 'path-to-regexp';
export class FastifyAdapter {
protected readonly instance: any;
constructor(options?: any) {
this.instance = loadPackage('fastify', 'FastifyAdapter')(options);
}
use(handler: RequestHandler | ErrorHandler);
use(path: any, handler: RequestHandler | ErrorHandler);
use(...args: any[]) {
return this.instance.use(...args);
}
get(handler: RequestHandler);
get(path: any, handler: RequestHandler);
get(...args: any[]) {
return this.instance.get(...args);
}
post(handler: RequestHandler);
post(path: any, handler: RequestHandler);
post(...args: any[]) {
return this.instance.post(...args);
}
head(handler: RequestHandler);
head(path: any, handler: RequestHandler);
head(...args: any[]) {
return this.instance.head(...args);
}
delete(handler: RequestHandler);
delete(path: any, handler: RequestHandler);
delete(...args: any[]) {
return this.instance.delete(...args);
}
put(handler: RequestHandler);
put(path: any, handler: RequestHandler);
put(...args: any[]) {
return this.instance.put(...args);
}
patch(handler: RequestHandler);
patch(path: any, handler: RequestHandler);
patch(...args: any[]) {
return this.instance.patch(...args);
}
options(handler: RequestHandler);
options(path: any, handler: RequestHandler);
options(...args: any[]) {
return this.instance.options(...args);
}
listen(port: string | number, callback?: () => void);
listen(port: string | number, hostname: string, callback?: () => void);
listen(port: any, hostname?: any, callback?: any) {
return this.instance.listen(port, hostname, callback);
}
reply(response, body: any, statusCode: number) {
return response.code(statusCode).send(body);
}
render(response, view: string, options: any) {
return response.view(view, options);
}
setErrorHandler(handler: Function) {
return this.instance.setErrorHandler(handler);
}
setNotFoundHandler(handler: Function) {
return this.instance.setNotFoundHandler(handler);
}
getHttpServer<T = any>(): T {
return this.instance.server as T;
}
getInstance<T = any>(): T {
return this.instance as T;
}
register(...args: any[]) {
return this.instance.register(...args);
}
inject(...args: any[]) {
return this.instance.inject(...args);
}
close() {
return this.instance.close();
}
useStaticAssets(options: {
root: string;
prefix?: string;
setHeaders?: Function;
send?: any;
}) {
return this.register(
loadPackage('fastify-static', 'FastifyAdapter.useStaticAssets()'),
options,
);
}
setViewEngine(options: any) {
return this.register(
loadPackage('point-of-view', 'FastifyAdapter.setViewEngine()'),
options,
);
}
setHeader(response, name: string, value: string) {
return response.header(name, value);
}
getRequestMethod(request): string {
return request.raw.method;
}
getRequestUrl(request): string {
return request.raw.url;
}
createMiddlewareFactory(
requestMethod: RequestMethod,
): (path: string, callback: Function) => any {
return (path: string, callback: Function) => {
const re = pathToRegexp(path);
const normalizedPath = path === '/*' ? '' : path;
this.instance.use(normalizedPath, (req, res, next) => {
if (!re.exec(req.originalUrl + '/')) {
return next();
}
if (
requestMethod === RequestMethod.ALL ||
req.method === RequestMethod[requestMethod]
) {
return callback(req, res, next);
}
next();
});
};
}
}

View File

@@ -0,0 +1,95 @@
import { HttpServer, RequestMethod } from '@nestjs/common';
import { RequestHandler } from '@nestjs/common/interfaces';
import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface';
import { NestApplicationOptions } from '@nestjs/common/interfaces/nest-application-options.interface';
export abstract class AbstractHttpAdapter<
TServer = any,
TRequest = any,
TResponse = any
> implements HttpServer<TRequest, TResponse> {
protected httpServer: TServer;
constructor(protected readonly instance: any) {}
public use(...args: any[]) {
return this.instance.use(...args);
}
public get(handler: RequestHandler);
public get(path: any, handler: RequestHandler);
public get(...args: any[]) {
return this.instance.get(...args);
}
public post(handler: RequestHandler);
public post(path: any, handler: RequestHandler);
public post(...args: any[]) {
return this.instance.post(...args);
}
public head(handler: RequestHandler);
public head(path: any, handler: RequestHandler);
public head(...args: any[]) {
return this.instance.head(...args);
}
public delete(handler: RequestHandler);
public delete(path: any, handler: RequestHandler);
public delete(...args: any[]) {
return this.instance.delete(...args);
}
public put(handler: RequestHandler);
public put(path: any, handler: RequestHandler);
public put(...args: any[]) {
return this.instance.put(...args);
}
public patch(handler: RequestHandler);
public patch(path: any, handler: RequestHandler);
public patch(...args: any[]) {
return this.instance.patch(...args);
}
public options(handler: RequestHandler);
public options(path: any, handler: RequestHandler);
public options(...args: any[]) {
return this.instance.options(...args);
}
public listen(port: string | number, callback?: () => void);
public listen(port: string | number, hostname: string, callback?: () => void);
public listen(port: any, hostname?: any, callback?: any) {
return this.instance.listen(port, hostname, callback);
}
public getHttpServer(): TServer {
return this.httpServer as TServer;
}
public setHttpServer(httpServer: TServer) {
this.httpServer = httpServer;
}
public getInstance(): any {
return this.instance;
}
abstract close();
abstract initHttpServer(options: NestApplicationOptions);
abstract useStaticAssets(...args: any[]);
abstract setViewEngine(engine: string);
abstract getRequestMethod(request);
abstract getRequestUrl(request);
abstract reply(response, body: any, statusCode: number);
abstract render(response, view: string, options: any);
abstract setErrorHandler(handler: Function);
abstract setNotFoundHandler(handler: Function);
abstract setHeader(response, name: string, value: string);
abstract registerParserMiddleware();
abstract enableCors(options: CorsOptions);
abstract createMiddlewareFactory(
requestMethod: RequestMethod,
): (path: string, callback: Function) => any;
}

View File

@@ -1 +1 @@
export * from './fastify-adapter';
export * from './http-adapter';

View File

@@ -11,7 +11,7 @@ import { Module } from '../injector/module';
* Returns the name of an instance
* @param instance The instance which should get the name from
*/
const getInstanceName = (instance: any) =>
const getInstanceName = (instance: unknown) =>
instance && (instance as Type<any>).name;
/**

View File

@@ -29,12 +29,12 @@ export class ExceptionsHandler extends BaseExceptionFilter {
if (isEmpty(this.filters)) return false;
const filter = this.filters.find(({ exceptionMetatypes }) => {
const hasMetatype =
const typeExists =
!exceptionMetatypes.length ||
exceptionMetatypes.some(
ExceptionMetatype => exception instanceof ExceptionMetatype,
);
return hasMetatype;
return typeExists;
});
filter && filter.func(exception, ctx);
return !!filter;

View File

@@ -0,0 +1 @@
export * from './base-exception-filter';

View File

@@ -2,7 +2,7 @@ import { CanActivate } from '@nestjs/common';
import { Controller } from '@nestjs/common/interfaces';
import { isEmpty } from '@nestjs/common/utils/shared.utils';
import { Observable } from 'rxjs';
import { ExecutionContextHost } from '../helpers/execution-context.host';
import { ExecutionContextHost } from '../helpers/execution-context-host';
export class GuardsConsumer {
public async tryActivate(

View File

@@ -70,7 +70,8 @@ export class GuardsContextCreator extends ContextCreator {
if (!module) {
return undefined;
}
return module.injectables.get(guard.name);
const injectables = module.injectables;
return injectables.get(guard.name);
}
public getGlobalMetadata<T extends any[]>(): T {

View File

@@ -0,0 +1 @@
export * from './application-ref-host';

View File

@@ -0,0 +1,18 @@
import { Logger } from '@nestjs/common';
const MISSING_REQUIRED_DEPENDENCY = (
defaultPlatform: string,
transport: string,
) =>
`No driver (${transport}) has been selected. In order to take advantage of the default driver, please, ensure to install the "${defaultPlatform}" package ($ npm install ${defaultPlatform}).`;
const logger = new Logger('PackageLoader');
export function loadAdapter(defaultPlatform: string, transport: string) {
try {
return require(defaultPlatform);
} catch (e) {
logger.error(MISSING_REQUIRED_DEPENDENCY(defaultPlatform, transport));
process.exit(1);
}
}

View File

@@ -8,12 +8,11 @@ import 'reflect-metadata';
export * from './adapters';
export { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from './constants';
export { BaseExceptionFilter } from './exceptions/base-exception-filter';
export { ApplicationReferenceHost } from './helpers/application-ref-host';
export * from './exceptions';
export * from './helpers';
export * from './hooks';
export { ModuleRef } from './injector/module-ref';
export { HTTP_SERVER_REF } from './injector/tokens';
export { MiddlewareBuilder } from './middleware/builder';
export * from './injector';
export * from './middleware';
export * from './nest-application';
export * from './nest-application-context';
export { NestFactory } from './nest-factory';

View File

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

View File

@@ -3,7 +3,7 @@ import { CallHandler, Controller } from '@nestjs/common/interfaces';
import { isEmpty } from '@nestjs/common/utils/shared.utils';
import { defer, from as fromPromise, Observable } from 'rxjs';
import { mergeAll, switchMap } from 'rxjs/operators';
import { ExecutionContextHost } from '../helpers/execution-context.host';
import { ExecutionContextHost } from '../helpers/execution-context-host';
export class InterceptorsConsumer {
public async intercept(

View File

@@ -0,0 +1 @@
export * from './builder';

View File

@@ -21,8 +21,8 @@ export class NestApplicationContext implements INestApplicationContext {
constructor(
protected readonly container: NestContainer,
private readonly scope: Type<any>[],
private contextModule: Module,
private readonly scope: Type<any>[] = [],
private contextModule: Module = null,
) {
this.containerScanner = new ContainerScanner(container);
}

View File

@@ -9,28 +9,16 @@ import {
} from '@nestjs/common';
import { HttpServer } from '@nestjs/common/interfaces';
import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface';
import { ServeStaticOptions } from '@nestjs/common/interfaces/external/serve-static-options.interface';
import { MicroserviceOptions } from '@nestjs/common/interfaces/microservices/microservice-configuration.interface';
import { NestApplicationOptions } from '@nestjs/common/interfaces/nest-application-options.interface';
import { INestExpressApplication } from '@nestjs/common/interfaces/nest-express-application.interface';
import { INestFastifyApplication } from '@nestjs/common/interfaces/nest-fastify-application.interface';
import { Logger } from '@nestjs/common/services/logger.service';
import { loadPackage } from '@nestjs/common/utils/load-package.util';
import {
isFunction,
isObject,
validatePath,
} from '@nestjs/common/utils/shared.utils';
import * as bodyParser from 'body-parser';
import * as cors from 'cors';
import * as http from 'http';
import * as https from 'https';
import { isObject, validatePath } from '@nestjs/common/utils/shared.utils';
import iterate from 'iterare';
import * as optional from 'optional';
import { ExpressAdapter } from './adapters/express-adapter';
import { FastifyAdapter } from './adapters/fastify-adapter';
import { ApplicationConfig } from './application-config';
import { MESSAGES } from './constants';
import { loadAdapter } from './helpers/load-adapter';
import { NestContainer } from './injector/container';
import { Injector } from './injector/injector';
import { MiddlewareContainer } from './middleware/container';
@@ -43,13 +31,9 @@ const { SocketModule } =
optional('@nestjs/websockets/socket-module') || ({} as any);
const { MicroservicesModule } =
optional('@nestjs/microservices/microservices-module') || ({} as any);
const { IoAdapter } =
optional('@nestjs/websockets/adapters/io-adapter') || ({} as any);
export class NestApplication extends NestApplicationContext
implements INestApplication,
INestExpressApplication,
INestFastifyApplication {
implements INestApplication {
private readonly logger = new Logger(NestApplication.name, true);
private readonly injector = new Injector();
private readonly middlewareModule = new MiddlewareModule();
@@ -60,7 +44,7 @@ export class NestApplication extends NestApplicationContext
private readonly socketModule = SocketModule ? new SocketModule() : null;
private readonly routesResolver: Resolver;
private readonly microservices: any[] = [];
private httpServer: http.Server;
private httpServer: any;
private isInitialized = false;
constructor(
@@ -69,7 +53,7 @@ export class NestApplication extends NestApplicationContext
private readonly config: ApplicationConfig,
private readonly appOptions: NestApplicationOptions = {},
) {
super(container, [], null);
super(container);
this.applyOptions();
this.selectContextModule();
@@ -89,11 +73,15 @@ export class NestApplication extends NestApplicationContext
public registerHttpServer() {
this.httpServer = this.createServer();
const server = this.getUnderlyingHttpServer();
const ioAdapter = IoAdapter ? new IoAdapter(server) : null;
const { IoAdapter } = optional('@nestjs/platform-socket.io') || ({} as any);
const ioAdapter = IoAdapter ? new IoAdapter(this.httpServer) : null;
this.config.setIoAdapter(ioAdapter);
}
public getUnderlyingHttpServer<T>(): T {
return this.httpAdapter.getHttpServer();
}
public applyOptions() {
if (!this.appOptions || !this.appOptions.cors) {
return undefined;
@@ -105,35 +93,13 @@ export class NestApplication extends NestApplicationContext
this.enableCors(this.appOptions.cors as CorsOptions);
}
public createServer(): any {
const isHttpsEnabled = this.appOptions && this.appOptions.httpsOptions;
const isExpress = this.isExpress();
if (isHttpsEnabled && isExpress) {
const server = https.createServer(
this.appOptions.httpsOptions,
this.httpAdapter.getInstance(),
);
(this.httpAdapter as ExpressAdapter).setHttpServer(server);
return server;
}
if (isExpress) {
const server = http.createServer(this.httpAdapter.getInstance());
(this.httpAdapter as ExpressAdapter).setHttpServer(server);
return server;
}
return this.httpAdapter;
}
public getUnderlyingHttpServer(): any {
return this.isExpress()
? this.httpServer
: this.httpAdapter.getHttpServer();
public createServer<T = any>(): T {
this.httpAdapter.initHttpServer(this.appOptions);
return this.httpAdapter.getHttpServer() as T;
}
public async registerModules() {
this.socketModule &&
this.socketModule.register(this.container, this.config);
this.registerWsModule();
if (this.microservicesModule) {
this.microservicesModule.register(this.container, this.config);
@@ -147,6 +113,17 @@ export class NestApplication extends NestApplicationContext
);
}
public registerWsModule() {
if (!this.socketModule) {
return;
}
const adapter = this.config.getIoAdapter();
if (!adapter) {
return loadAdapter('@nestjs/platform-socket.io', 'WebSockets');
}
this.socketModule.register(this.container, this.config);
}
public async init(): Promise<this> {
const useBodyParser =
this.appOptions && this.appOptions.bodyParser !== false;
@@ -164,37 +141,12 @@ export class NestApplication extends NestApplicationContext
}
public registerParserMiddleware() {
if (this.httpAdapter instanceof FastifyAdapter) {
return this.httpAdapter.register(
this.loadPackage('fastify-formbody', 'FastifyAdapter'),
);
}
if (!this.isExpress()) {
return undefined;
}
const parserMiddleware = {
jsonParser: bodyParser.json(),
urlencodedParser: bodyParser.urlencoded({ extended: true }),
};
Object.keys(parserMiddleware)
.filter(parser => !this.isMiddlewareApplied(this.httpAdapter, parser))
.forEach(parserKey => this.httpAdapter.use(parserMiddleware[parserKey]));
}
public isMiddlewareApplied(httpAdapter: HttpServer, name: string): boolean {
const app = httpAdapter.getInstance();
return (
!!app._router &&
!!app._router.stack &&
isFunction(app._router.stack.filter) &&
app._router.stack.some(
(layer: any) => layer && layer.handle && layer.handle.name === name,
)
);
this.httpAdapter.registerParserMiddleware();
}
public async registerRouter() {
await this.registerMiddleware(this.httpAdapter);
const prefix = this.config.getGlobalPrefix();
const basePath = validatePath(prefix);
this.routesResolver.resolve(this.httpAdapter, basePath);
@@ -206,7 +158,7 @@ export class NestApplication extends NestApplicationContext
}
public connectMicroservice(options: MicroserviceOptions): INestMicroservice {
const { NestMicroservice } = loadPackage(
const { NestMicroservice } = this.loadPackage(
'@nestjs/microservices',
'NestFactory',
);
@@ -244,56 +196,13 @@ export class NestApplication extends NestApplicationContext
return new Promise(resolve => this.startAllMicroservices(resolve));
}
public use(...args: any[]): this {
(this.httpAdapter as any).use(...args);
public use(...args: [any, any?]): this {
this.httpAdapter.use(...args);
return this;
}
public engine(...args: any[]): this {
if (!this.isExpress()) {
return this;
}
(this.httpAdapter as ExpressAdapter).engine(...args);
return this;
}
public set(...args: any[]): this {
if (!this.isExpress()) {
return this;
}
(this.httpAdapter as ExpressAdapter).set(...args);
return this;
}
public disable(...args: any[]): this {
if (!this.isExpress()) {
return this;
}
(this.httpAdapter as ExpressAdapter).disable(...args);
return this;
}
public enable(...args: any[]): this {
if (!this.isExpress()) {
return this;
}
(this.httpAdapter as ExpressAdapter).enable(...args);
return this;
}
public register(...args: any[]): this {
const adapter = this.httpAdapter as FastifyAdapter;
adapter.register && adapter.register(...args);
return this;
}
public inject(...args: any[]) {
const adapter = this.httpAdapter as FastifyAdapter;
return adapter.inject && adapter.inject(...args);
}
public enableCors(options?: CorsOptions): this {
this.httpAdapter.use(cors(options) as any);
this.httpAdapter.enableCors(options);
return this;
}
@@ -363,11 +272,8 @@ export class NestApplication extends NestApplicationContext
}
public useStaticAssets(options: any): this;
public useStaticAssets(path: string, options?: ServeStaticOptions): this;
public useStaticAssets(
pathOrOptions: any,
options?: ServeStaticOptions,
): this {
public useStaticAssets(path: string, options?: any): this;
public useStaticAssets(pathOrOptions: any, options?: any): this {
this.httpAdapter.useStaticAssets &&
this.httpAdapter.useStaticAssets(pathOrOptions, options);
return this;
@@ -384,8 +290,8 @@ export class NestApplication extends NestApplicationContext
return this;
}
private loadPackage(name: string, ctx: string) {
return loadPackage(name, ctx);
private loadPackage<T = any>(name: string, ctx: string): T {
return loadPackage(name, ctx) as T;
}
private async registerMiddleware(instance: any) {
@@ -395,14 +301,6 @@ export class NestApplication extends NestApplicationContext
);
}
private isExpress(): boolean {
const isExpress = !this.httpAdapter.getHttpServer;
if (isExpress) {
return isExpress;
}
return this.httpAdapter instanceof ExpressAdapter;
}
private listenToPromise(microservice: INestMicroservice) {
return new Promise(async (resolve, reject) => {
await microservice.listen(resolve);

View File

@@ -8,17 +8,13 @@ import { MicroserviceOptions } from '@nestjs/common/interfaces/microservices/mic
import { NestMicroserviceOptions } from '@nestjs/common/interfaces/microservices/nest-microservice-options.interface';
import { NestApplicationContextOptions } from '@nestjs/common/interfaces/nest-application-context-options.interface';
import { NestApplicationOptions } from '@nestjs/common/interfaces/nest-application-options.interface';
import { INestExpressApplication } from '@nestjs/common/interfaces/nest-express-application.interface';
import { INestFastifyApplication } from '@nestjs/common/interfaces/nest-fastify-application.interface';
import { Logger } from '@nestjs/common/services/logger.service';
import { loadPackage } from '@nestjs/common/utils/load-package.util';
import { isFunction, isNil } from '@nestjs/common/utils/shared.utils';
import { ExpressAdapter } from './adapters/express-adapter';
import { ExpressFactory } from './adapters/express-factory';
import { FastifyAdapter } from './adapters/fastify-adapter';
import { ApplicationConfig } from './application-config';
import { MESSAGES } from './constants';
import { ExceptionsZone } from './errors/exceptions-zone';
import { loadAdapter } from './helpers/load-adapter';
import { NestContainer } from './injector/container';
import { InstanceLoader } from './injector/instance-loader';
import { MetadataScanner } from './metadata-scanner';
@@ -32,42 +28,39 @@ export class NestFactoryStatic {
* Creates an instance of the NestApplication
* @returns {Promise}
*/
public async create(
public async create<T extends INestApplication = INestApplication>(
module: any,
options?: NestApplicationOptions,
): Promise<INestApplication & INestExpressApplication>;
public async create(
): Promise<T>;
public async create<T extends INestApplication = INestApplication>(
module: any,
httpServer: FastifyAdapter,
httpServer: HttpServer,
options?: NestApplicationOptions,
): Promise<INestApplication & INestFastifyApplication>;
public async create(
): Promise<T>;
public async create<T extends INestApplication = INestApplication>(
module: any,
httpServer: HttpServer | any,
serverOrOptions?: HttpServer | NestApplicationOptions,
options?: NestApplicationOptions,
): Promise<INestApplication & INestExpressApplication>;
public async create(
module: any,
serverOrOptions?: any,
options?: NestApplicationOptions,
): Promise<
INestApplication & (INestExpressApplication | INestFastifyApplication)
> {
const isHttpServer = serverOrOptions && serverOrOptions.patch;
): Promise<T> {
// tslint:disable-next-line:prefer-const
let [httpServer, appOptions] = isHttpServer
let [httpServer, appOptions] = this.isHttpServer(serverOrOptions)
? [serverOrOptions, options]
: [ExpressFactory.create(), serverOrOptions];
: [this.createHttpAdapter(), serverOrOptions];
const applicationConfig = new ApplicationConfig();
const container = new NestContainer(applicationConfig);
httpServer = this.applyExpressAdapter(httpServer);
this.applyLogger(appOptions);
await this.initialize(module, container, applicationConfig, httpServer);
return this.createNestInstance<NestApplication>(
new NestApplication(container, httpServer, applicationConfig, appOptions),
const instance = new NestApplication(
container,
httpServer,
applicationConfig,
appOptions,
);
const target = this.createNestInstance(instance);
return this.createAdapterProxy<T>(target, httpServer);
}
/**
@@ -159,21 +152,29 @@ export class NestFactoryStatic {
private createExceptionProxy() {
return (receiver: Record<string, any>, prop: string) => {
if (!(prop in receiver)) return;
if (!(prop in receiver)) {
return;
}
if (isFunction(receiver[prop])) {
return (...args: any[]) => {
let result;
ExceptionsZone.run(() => {
result = receiver[prop](...args);
});
return result;
};
return this.createExceptionZone(receiver, prop);
}
return receiver[prop];
};
}
private createExceptionZone(
receiver: Record<string, any>,
prop: string,
): Function {
return (...args: unknown[]) => {
let result;
ExceptionsZone.run(() => {
result = receiver[prop](...args);
});
return result;
};
}
private applyLogger(options: NestApplicationContextOptions | undefined) {
if (!options) {
return;
@@ -181,12 +182,26 @@ export class NestFactoryStatic {
!isNil(options.logger) && Logger.overrideLogger(options.logger);
}
private applyExpressAdapter(httpAdapter: HttpServer): HttpServer {
const isAdapter = httpAdapter.getHttpServer;
if (isAdapter) {
return httpAdapter;
}
return new ExpressAdapter(httpAdapter);
private createHttpAdapter<T = any>(httpServer?: T): HttpServer {
const { ExpressAdapter } = loadAdapter('@nestjs/platform-express', 'HTTP');
return new ExpressAdapter(httpServer);
}
private isHttpServer(
serverOrOptions: HttpServer | NestApplicationOptions,
): serverOrOptions is HttpServer {
return !!(serverOrOptions && (serverOrOptions as HttpServer).patch);
}
private createAdapterProxy<T>(app: NestApplication, adapter: HttpServer): T {
return (new Proxy(app, {
get: (receiver: Record<string, any>, prop: string) => {
if (!(prop in receiver) && prop in adapter) {
return this.createExceptionZone(receiver, prop);
}
return receiver[prop];
},
}) as unknown) as T;
}
}

View File

@@ -20,14 +20,10 @@
},
"dependencies": {
"@nuxtjs/opencollective": "0.1.0",
"body-parser": "1.18.3",
"cors": "2.8.4",
"express": "4.16.3",
"fast-safe-stringify": "1.2.0",
"iterare": "0.0.8",
"object-hash": "1.3.0",
"optional": "0.1.4",
"path-to-regexp": "2.2.1",
"uuid": "3.3.2"
},
"peerDependencies": {

View File

@@ -1,5 +1,5 @@
import { ExceptionsHandler } from '../exceptions/exceptions-handler';
import { ExecutionContextHost } from '../helpers/execution-context.host';
import { ExecutionContextHost } from '../helpers/execution-context-host';
export type RouterProxyCallback = <TRequest, TResponse>(
req?: TRequest,

View File

@@ -1,23 +1,23 @@
import { HttpException } from '@nestjs/common';
import { isNil, isObject } from '@nestjs/common/utils/shared.utils';
import { expect } from 'chai';
import * as sinon from 'sinon';
import { NestEnvironment } from '../../../common/enums/nest-environment.enum';
import { Logger } from '../../../common/services/logger.service';
import { ExpressAdapter } from '../../adapters/express-adapter';
import { AbstractHttpAdapter } from '../../adapters';
import { InvalidExceptionFilterException } from '../../errors/exceptions/invalid-exception-filter.exception';
import { ExceptionsHandler } from '../../exceptions/exceptions-handler';
import { ExecutionContextHost } from '../../helpers/execution-context.host';
import { ExecutionContextHost } from '../../helpers/execution-context-host';
import { NoopHttpAdapter } from './../utils/noop-adapter';
describe('ExceptionsHandler', () => {
let adapter: AbstractHttpAdapter;
let handler: ExceptionsHandler;
let statusStub: sinon.SinonStub;
let jsonStub: sinon.SinonStub;
let response;
before(() => Logger.setMode(NestEnvironment.TEST));
beforeEach(() => {
handler = new ExceptionsHandler(new ExpressAdapter({}));
adapter = new NoopHttpAdapter({});
handler = new ExceptionsHandler(adapter);
statusStub = sinon.stub();
jsonStub = sinon.stub();
@@ -30,6 +30,17 @@ describe('ExceptionsHandler', () => {
});
describe('next', () => {
beforeEach(() => {
sinon
.stub(adapter, 'reply')
.callsFake((responseRef: any, body: any, statusCode: number) => {
const res = responseRef.status(statusCode);
if (isNil(body)) {
return res.send();
}
return isObject(body) ? res.json(body) : res.send(String(body));
});
});
it('should method send expected response status code and message when exception is unknown', () => {
handler.next(new Error(), new ExecutionContextHost([0, response]));

View File

@@ -1,6 +1,6 @@
import * as sinon from 'sinon';
import { expect } from 'chai';
import { ExecutionContextHost } from '../../helpers/execution-context.host';
import { ExecutionContextHost } from '../../helpers/execution-context-host';
describe('ExecutionContextHost', () => {
let contextHost: ExecutionContextHost;

View File

@@ -73,7 +73,7 @@ describe('ExternalContextCreator', () => {
describe('when can not activate', () => {
it('should throw exception when "tryActivate" returns false', () => {
sinon.stub(guardsConsumer, 'tryActivate', () => false);
expect(proxyContext(1, 2, 3)).to.eventually.throw;
proxyContext(1, 2, 3).catch(err => expect(err).to.not.be.undefined);
});
});
describe('when can activate', () => {

View File

@@ -2,8 +2,6 @@ import { expect } from 'chai';
import * as sinon from 'sinon';
import { Injectable } from '../../../common';
import { Controller } from '../../../common/decorators/core/controller.decorator';
import { NestEnvironment } from '../../../common/enums/nest-environment.enum';
import { Logger } from '../../../common/services/logger.service';
import { NestContainer } from '../../injector/container';
import { Injector } from '../../injector/injector';
import { InstanceLoader } from '../../injector/instance-loader';
@@ -20,8 +18,6 @@ describe('InstanceLoader', () => {
@Injectable()
class TestProvider {}
before(() => Logger.setMode(NestEnvironment.TEST));
beforeEach(() => {
container = new NestContainer();
loader = new InstanceLoader(container);

View File

@@ -5,7 +5,6 @@ import { Controller } from '../../../common/decorators/core/controller.decorator
import { RequestMapping } from '../../../common/decorators/http/request-mapping.decorator';
import { RequestMethod } from '../../../common/enums/request-method.enum';
import { NestMiddleware } from '../../../common/interfaces/middleware/nest-middleware.interface';
import { ExpressAdapter } from '../../adapters/express-adapter';
import { ApplicationConfig } from '../../application-config';
import { InvalidMiddlewareException } from '../../errors/exceptions/invalid-middleware.exception';
import { RuntimeException } from '../../errors/exceptions/runtime.exception';
@@ -16,6 +15,7 @@ import { MiddlewareBuilder } from '../../middleware/builder';
import { MiddlewareContainer } from '../../middleware/container';
import { MiddlewareModule } from '../../middleware/middleware-module';
import { RouterExceptionFilters } from '../../router/router-exception-filters';
import { NoopHttpAdapter } from '../utils/noop-adapter';
describe('MiddlewareModule', () => {
let middlewareModule: MiddlewareModule;
@@ -45,7 +45,7 @@ describe('MiddlewareModule', () => {
(middlewareModule as any).routerExceptionFilter = new RouterExceptionFilters(
new NestContainer(),
appConfig,
new ExpressAdapter({}),
new NoopHttpAdapter({}),
);
(middlewareModule as any).config = appConfig;
});

View File

@@ -1,9 +1,7 @@
import { expect } from 'chai';
import * as sinon from 'sinon';
import { Injectable } from '../../../common';
import { NestEnvironment } from '../../../common/enums/nest-environment.enum';
import { NestMiddleware } from '../../../common/interfaces/middleware/nest-middleware.interface';
import { Logger } from '../../../common/services/logger.service';
import { MiddlewareContainer } from '../../middleware/container';
import { MiddlewareResolver } from '../../middleware/resolver';
@@ -19,8 +17,6 @@ describe('MiddlewareResolver', () => {
let container: MiddlewareContainer;
let mockContainer: sinon.SinonMock;
before(() => Logger.setMode(NestEnvironment.TEST));
beforeEach(() => {
container = new MiddlewareContainer();
resolver = new MiddlewareResolver(container);

View File

@@ -1,12 +1,11 @@
import * as sinon from 'sinon';
import { expect } from 'chai';
import { RouterExceptionFilters } from '../../router/router-exception-filters';
import { UseFilters } from '../../../common/decorators/core/exception-filters.decorator';
import * as sinon from 'sinon';
import { Catch } from '../../../common/decorators/core/catch.decorator';
import { UnknownModuleException } from '../../errors/exceptions/unknown-module.exception';
import { UseFilters } from '../../../common/decorators/core/exception-filters.decorator';
import { ApplicationConfig } from '../../application-config';
import { ExpressAdapter } from '../../adapters/express-adapter';
import { NestContainer } from '../../injector/container';
import { RouterExceptionFilters } from '../../router/router-exception-filters';
import { NoopHttpAdapter } from '../utils/noop-adapter';
describe('RouterExceptionFilters', () => {
let moduleName: string;
@@ -23,7 +22,7 @@ describe('RouterExceptionFilters', () => {
exceptionFilter = new RouterExceptionFilters(
new NestContainer(),
new ApplicationConfig(),
new ExpressAdapter({}),
new NoopHttpAdapter({}),
);
});
describe('create', () => {

View File

@@ -3,7 +3,7 @@ import * as sinon from 'sinon';
import { RouteParamsMetadata } from '../../../common';
import { CUSTOM_ROUTE_AGRS_METADATA } from '../../../common/constants';
import { RouteParamtypes } from '../../../common/enums/route-paramtypes.enum';
import { ExpressAdapter } from '../../adapters/express-adapter';
import { AbstractHttpAdapter } from '../../adapters';
import { ApplicationConfig } from '../../application-config';
import { GuardsConsumer } from '../../guards/guards-consumer';
import { GuardsContextCreator } from '../../guards/guards-context-creator';
@@ -14,6 +14,7 @@ import { PipesConsumer } from '../../pipes/pipes-consumer';
import { PipesContextCreator } from '../../pipes/pipes-context-creator';
import { RouteParamsFactory } from '../../router/route-params-factory';
import { RouterExecutionContext } from '../../router/router-execution-context';
import { NoopHttpAdapter } from '../utils/noop-adapter';
describe('RouterExecutionContext', () => {
let contextCreator: RouterExecutionContext;
@@ -23,6 +24,7 @@ describe('RouterExecutionContext', () => {
let factory: RouteParamsFactory;
let consumer: PipesConsumer;
let guardsConsumer: GuardsConsumer;
let adapter: AbstractHttpAdapter;
beforeEach(() => {
callback = {
@@ -36,6 +38,7 @@ describe('RouterExecutionContext', () => {
consumer = new PipesConsumer();
guardsConsumer = new GuardsConsumer();
adapter = new NoopHttpAdapter({});
contextCreator = new RouterExecutionContext(
factory,
new PipesContextCreator(new NestContainer(), new ApplicationConfig()),
@@ -44,7 +47,7 @@ describe('RouterExecutionContext', () => {
guardsConsumer,
new InterceptorsContextCreator(new NestContainer()),
new InterceptorsConsumer(),
new ExpressAdapter({}),
adapter,
);
});
describe('create', () => {
@@ -124,7 +127,9 @@ describe('RouterExecutionContext', () => {
});
it('should throw exception when "tryActivate" returns false', () => {
sinon.stub(guardsConsumer, 'tryActivate').callsFake(() => false);
expect(proxyContext(request, response, next)).to.eventually.throw();
proxyContext(request, response, next).catch(
error => expect(error).to.not.be.undefined,
);
});
});
});
@@ -254,11 +259,18 @@ describe('RouterExecutionContext', () => {
it('should throw exception when "tryActivate" returns false', () => {
const guardsFn = contextCreator.createGuardsFn([null], null, null);
sinon.stub(guardsConsumer, 'tryActivate').callsFake(() => false);
expect(guardsFn([])).to.eventually.throw();
guardsFn([]).catch(err => expect(err).to.not.be.undefined);
});
});
describe('createHandleResponseFn', () => {
describe('when "renderTemplate" is defined', () => {
beforeEach(() => {
sinon
.stub(adapter, 'render')
.callsFake((response, view: string, options: any) => {
return response.render(view, options);
});
});
it('should call "res.render()" with expected args', async () => {
const template = 'template';
const value = 'test';

View File

@@ -1,9 +1,9 @@
import * as sinon from 'sinon';
import { expect } from 'chai';
import { RouterProxy } from '../../router/router-proxy';
import { ExceptionsHandler } from '../../exceptions/exceptions-handler';
import * as sinon from 'sinon';
import { HttpException } from '../../../common/exceptions/http.exception';
import { ExpressAdapter } from '../../adapters/express-adapter';
import { ExceptionsHandler } from '../../exceptions/exceptions-handler';
import { RouterProxy } from '../../router/router-proxy';
import { NoopHttpAdapter } from '../utils/noop-adapter';
describe('RouterProxy', () => {
let routerProxy: RouterProxy;
@@ -11,7 +11,7 @@ describe('RouterProxy', () => {
let handler: ExceptionsHandler;
beforeEach(() => {
handler = new ExceptionsHandler(new ExpressAdapter({}));
handler = new ExceptionsHandler(new NoopHttpAdapter({}));
handlerMock = sinon.mock(handler);
routerProxy = new RouterProxy();
});

View File

@@ -1,16 +1,17 @@
import { isNil, isObject } from '@nestjs/common/utils/shared.utils';
import { expect } from 'chai';
import { of } from 'rxjs';
import * as sinon from 'sinon';
import { RequestMethod } from '../../../common';
import { ExpressAdapter } from '../../adapters/express-adapter';
import { RouterResponseController } from '../../router/router-response-controller';
import { NoopHttpAdapter } from '../utils/noop-adapter';
describe('RouterResponseController', () => {
let adapter: ExpressAdapter;
let adapter: NoopHttpAdapter;
let routerResponseController: RouterResponseController;
beforeEach(() => {
adapter = new ExpressAdapter({});
adapter = new NoopHttpAdapter({});
routerResponseController = new RouterResponseController(adapter);
});
@@ -25,6 +26,17 @@ describe('RouterResponseController', () => {
response.status = sinon.stub().returns(response);
});
describe('when result is', () => {
beforeEach(() => {
sinon
.stub(adapter, 'reply')
.callsFake((responseRef: any, body: any, statusCode: number) => {
const res = responseRef.status(statusCode);
if (isNil(body)) {
return res.send();
}
return isObject(body) ? res.json(body) : res.send(String(body));
});
});
describe('nil', () => {
it('should call send()', async () => {
const value = null;
@@ -102,6 +114,13 @@ describe('RouterResponseController', () => {
});
describe('render', () => {
beforeEach(() => {
sinon
.stub(adapter, 'render')
.callsFake((response, view: string, options: any) => {
return response.render(view, options);
});
});
it('should call "res.render()" with expected args', async () => {
const template = 'template';
const value = 'test';

View File

@@ -3,11 +3,11 @@ import { expect } from 'chai';
import * as sinon from 'sinon';
import { Controller } from '../../../common/decorators/core/controller.decorator';
import { Get } from '../../../common/decorators/http/request-mapping.decorator';
import { ExpressAdapter } from '../../adapters/express-adapter';
import { ApplicationConfig } from '../../application-config';
import { Injector } from '../../injector/injector';
import { InstanceWrapper } from '../../injector/instance-wrapper';
import { RoutesResolver } from '../../router/routes-resolver';
import { NoopHttpAdapter } from '../utils/noop-adapter';
describe('RoutesResolver', () => {
@Controller('global')
@@ -60,7 +60,7 @@ describe('RoutesResolver', () => {
});
routes.set('TestRoute', routeWrapper);
const appInstance = new ExpressAdapter(router);
const appInstance = new NoopHttpAdapter(router);
const exploreSpy = sinon.spy(
(routesResolver as any).routerBuilder,
'explore',

View File

@@ -165,9 +165,9 @@ describe('DependenciesScanner', () => {
});
describe('when "related" is nil', () => {
it('should throw exception', () => {
expect(
scanner.insertImport(undefined, [] as any, 'test'),
).to.eventually.throws();
scanner
.insertImport(undefined, [] as any, 'test')
.catch(err => expect(err).to.not.be.undefined);
});
});
});

View File

@@ -0,0 +1,22 @@
import { RequestMethod } from '@nestjs/common';
import { AbstractHttpAdapter } from './../../adapters';
export class NoopHttpAdapter extends AbstractHttpAdapter {
constructor(instance: any) {
super(instance);
}
close(): any {}
initHttpServer(options: any): any {}
useStaticAssets(...args: any[]): any {}
setViewEngine(engine: string): any {}
getRequestMethod(request: any): any {}
getRequestUrl(request: any): any {}
reply(response: any, body: any, statusCode: number): any {}
render(response: any, view: string, options: any): any {}
setErrorHandler(handler: Function): any {}
setNotFoundHandler(handler: Function): any {}
setHeader(response: any, name: string, value: string): any {}
registerParserMiddleware(): any {}
enableCors(options: any): any {}
createMiddlewareFactory(requestMethod: RequestMethod): any {}
}

View File

@@ -1,5 +1,5 @@
import { isFunction } from '@nestjs/common/utils/shared.utils';
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context.host';
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host';
import { Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { RpcExceptionsHandler } from '../exceptions/rpc-exceptions-handler';

View File

@@ -21,8 +21,6 @@ import { ServerFactory } from './server/server-factory';
const { SocketModule } =
optional('@nestjs/websockets/socket-module') || ({} as any);
const { IoAdapter } =
optional('@nestjs/websockets/adapters/io-adapter') || ({} as any);
export class NestMicroservice extends NestApplicationContext
implements INestMicroservice {
@@ -40,7 +38,7 @@ export class NestMicroservice extends NestApplicationContext
config: MicroserviceOptions = {},
private readonly applicationConfig: ApplicationConfig,
) {
super(container, [], null);
super(container);
this.registerWsAdapter();
this.microservicesModule.register(container, this.applicationConfig);
@@ -49,6 +47,7 @@ export class NestMicroservice extends NestApplicationContext
}
public registerWsAdapter() {
const { IoAdapter } = optional('@nestjs/platform-socket.io') || ({} as any);
const ioAdapter = IoAdapter ? new IoAdapter() : null;
this.applicationConfig.setIoAdapter(ioAdapter);
}

View File

@@ -1,3 +1,4 @@
import { Logger } from '@nestjs/common';
import { expect } from 'chai';
import { join } from 'path';
import { Observable } from 'rxjs';
@@ -7,6 +8,11 @@ import { InvalidGrpcPackageException } from '../../errors/invalid-grpc-package.e
import { InvalidGrpcServiceException } from '../../errors/invalid-grpc-service.exception';
import { InvalidProtoDefinitionException } from '../../errors/invalid-proto-definition.exception';
// tslint:disable:no-string-literal
class NoopLogger extends Logger {
log(message: any, context?: string): void {}
error(message: any, trace?: string, context?: string): void {}
warn(message: any, context?: string): void {}
}
class GrpcService {
test = null;
@@ -188,9 +194,13 @@ describe('ClientGrpcProxy', () => {
describe('when package does not exist', () => {
it('should throw "InvalidGrpcPackageException"', () => {
sinon.stub(client, 'lookupPackage').callsFake(() => null);
expect(() => client.createClient()).to.throw(
InvalidGrpcPackageException,
);
(client as any).logger = new NoopLogger();
try {
client.createClient();
} catch (err) {
expect(err).to.be.instanceof(InvalidGrpcPackageException);
}
});
});
});
@@ -201,6 +211,7 @@ describe('ClientGrpcProxy', () => {
sinon.stub(client, 'getOptionsProp').callsFake(() => {
throw new Error();
});
(client as any).logger = new NoopLogger();
expect(() => client.loadProto()).to.throws(
InvalidProtoDefinitionException,
);
@@ -231,7 +242,7 @@ describe('ClientGrpcProxy', () => {
describe('connect', () => {
it('should throw exception', () => {
expect(client.connect()).to.eventually.throws(Error);
client.connect().catch(error => expect(error).to.be.instanceof(Error));
});
});
});

View File

@@ -133,7 +133,9 @@ describe('RpcContextCreator', () => {
);
const data = 'test';
expect(proxy(data)).to.eventually.rejectedWith(RpcException);
proxy(null, data).catch(err =>
expect(err).to.be.instanceOf(RpcException),
);
});
});
});
@@ -167,7 +169,7 @@ describe('RpcContextCreator', () => {
it('should throw exception when "tryActivate" returns false', () => {
const guardsFn = contextCreator.createGuardsFn([null], null, null);
sinon.stub(guardsConsumer, 'tryActivate').callsFake(() => false);
expect(guardsFn([])).to.eventually.throw();
guardsFn([]).catch(err => expect(err).to.not.be.undefined);
});
});
});

View File

@@ -1,3 +1,4 @@
import { Logger } from '@nestjs/common';
import { expect } from 'chai';
import { join } from 'path';
import { of } from 'rxjs';
@@ -5,6 +6,12 @@ import * as sinon from 'sinon';
import { InvalidGrpcPackageException } from '../../errors/invalid-grpc-package.exception';
import { ServerGrpc } from '../../server/server-grpc';
class NoopLogger extends Logger {
log(message: any, context?: string): void {}
error(message: any, trace?: string, context?: string): void {}
warn(message: any, context?: string): void {}
}
describe('ServerGrpc', () => {
let server: ServerGrpc;
beforeEach(() => {
@@ -42,11 +49,14 @@ describe('ServerGrpc', () => {
describe('bindEvents', () => {
describe('when package does not exist', () => {
it('should throw "InvalidGrpcPackageException"', () => {
it('should throw "InvalidGrpcPackageException"', async () => {
sinon.stub(server, 'lookupPackage').callsFake(() => null);
expect(server.bindEvents()).to.eventually.throws(
InvalidGrpcPackageException,
);
(server as any).logger = new NoopLogger();
try {
await server.bindEvents();
} catch (err) {
expect(err).to.be.instanceof(InvalidGrpcPackageException);
}
});
});
describe('when package exist', () => {

View File

@@ -0,0 +1,76 @@
<p align="center">
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo_text.svg" width="320" alt="Nest Logo" /></a>
</p>
[travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master
[travis-url]: https://travis-ci.org/nestjs/nest
[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux
[linux-url]: https://travis-ci.org/nestjs/nest
<p align="center">A progressive <a href="http://nodejs.org" target="blank">Node.js</a> framework for building efficient and scalable server-side applications, heavily inspired by <a href="https://angular.io" target="blank">Angular</a>.</p>
<p align="center">
<a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
<a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
<a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/dm/@nestjs/core.svg" alt="NPM Downloads" /></a>
<a href="https://travis-ci.org/nestjs/nest"><img src="https://api.travis-ci.org/nestjs/nest.svg?branch=master" alt="Travis" /></a>
<a href="https://travis-ci.org/nestjs/nest"><img src="https://img.shields.io/travis/nestjs/nest/master.svg?label=linux" alt="Linux" /></a>
<a href="https://coveralls.io/github/nestjs/nest?branch=master"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#8" alt="Coverage" /></a>
<a href="https://gitter.im/nestjs/nestjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge"><img src="https://badges.gitter.im/nestjs/nestjs.svg" alt="Gitter" /></a>
<a href="https://opencollective.com/nest#backer"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
<a href="https://opencollective.com/nest#sponsor"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
<a href="https://paypal.me/kamilmysliwiec"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
<a href="https://twitter.com/nestframework"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
</p>
<!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
[![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->
## Description
<p>Nest is a framework for building efficient, scalable <a href="http://nodejs.org" target="_blank">Node.js</a> server-side applications. It uses modern JavaScript, is built with <a href="http://www.typescriptlang.org" target="_blank">TypeScript</a> (preserves compatibility with pure JavaScript) and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).</p>
<p>Under the hood, Nest makes use of <a href="https://expressjs.com/" target="_blank">Express</a>, but also, provides compatibility with a wide range of other libraries, like e.g. <a href="https://github.com/fastify/fastify" target="blank">Fastify</a>, allowing for easy use of the myriad third-party plugins which are available.</p>
## Philosophy
<p>In recent years, thanks to Node.js, JavaScript has become the “lingua franca” of the web for both front and backend applications, giving rise to awesome projects like <a href="https://angular.io/" target="_blank">Angular</a>, <a href="https://github.com/facebook/react" target="_blank">React</a> and <a href="https://github.com/vuejs/vue" target="_blank">Vue</a> which improve developer productivity and enable the construction of fast, testable, extensible frontend applications. However, on the server-side, while there are a lot of superb libraries, helpers and tools for Node, none of them effectively solve the main problem - the architecture.</p>
<p>Nest aims to provide an application architecture out of the box which allows for effortless creation of highly testable, scalable, loosely coupled and easily maintainable applications.</p>
## Getting started
* To check out the [guide](https://docs.nestjs.com), visit [docs.nestjs.com](https://docs.nestjs.com). :books:
* 要查看中文 [指南](readme_zh.md), 请访问 [docs.nestjs.cn](https://docs.nestjs.cn). :books:
## Support
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
#### Principal Sponsor
<a href="https://valor-software.com/"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="320" /></a>
#### Gold Sponsors
<a href="http://xtremis.com/"><img src="https://nestjs.com/img/logo-xtremis.svg" width="220" /></a>
#### Silver Sponsors
<a href="https://neoteric.eu/"><img src="https://nestjs.com/img/neoteric-cut.png" width="120" /></a> &nbsp;
<a href="http://gojob.com"><img src="http://nestjs.com/img/gojob-logo.png" valign="bottom" height="95" /></a> &nbsp; <a href="https://www.swingdev.io"><img src="https://nestjs.com/img/swingdev-logo.svg#1" width="150" /> </a>
#### Sponsors
<a href="https://scal.io"><img src="https://nestjs.com/img/scalio-logo.svg" width="110" /></a> &nbsp; <a href="http://angularity.io"><img src="http://angularity.io/media/logo.svg" height="30" /></a> &nbsp; <!--<a href="https://keycdn.com"><img src="https://nestjs.com/img/keycdn.svg" height="30" /></a> &nbsp;--> <a href="https://hostpresto.com"><img src="https://nestjs.com/img/hostpresto.png" height="30" /></a> &nbsp; <a href="https://genuinebee.com/"><img src="https://nestjs.com/img/genuinebee.svg" height="38" /></a> &nbsp; <a href="http://architectnow.net/"><img src="https://nestjs.com/img/architectnow.png" height="24" /></a> &nbsp; <a href="https://quander.io/"><img src="https://nestjs.com/img/quander.png" height="28" /></a>
## Backers
<a href="https://opencollective.com/nest"><img src="https://opencollective.com/nest/backers.svg?width=890"></a>
## Stay in touch
* Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
* Website - [https://nestjs.com](https://nestjs.com/)
* Twitter - [@nestframework](https://twitter.com/nestframework)
## License
Nest is [MIT licensed](LICENSE).

View File

@@ -0,0 +1,133 @@
import { RequestMethod } from '@nestjs/common';
import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface';
import { NestApplicationOptions } from '@nestjs/common/interfaces/nest-application-options.interface';
import { isFunction, isNil, isObject } from '@nestjs/common/utils/shared.utils';
import { AbstractHttpAdapter } from '@nestjs/core/adapters/http-adapter';
import { RouterMethodFactory } from '@nestjs/core/helpers/router-method-factory';
import * as bodyParser from 'body-parser';
import * as cors from 'cors';
import * as express from 'express';
import * as http from 'http';
import * as https from 'https';
import { ServeStaticOptions } from './../interfaces/serve-static-options.interface';
export class ExpressAdapter extends AbstractHttpAdapter {
private readonly routerMethodFactory = new RouterMethodFactory();
constructor(instance?: any) {
super(instance || express());
}
public reply(response, body: any, statusCode: number) {
const res = response.status(statusCode);
if (isNil(body)) {
return res.send();
}
return isObject(body) ? res.json(body) : res.send(String(body));
}
public render(response, view: string, options: any) {
return response.render(view, options);
}
public setErrorHandler(handler: Function) {
return this.use(handler);
}
public setNotFoundHandler(handler: Function) {
return this.use(handler);
}
public setHeader(response, name: string, value: string) {
return response.set(name, value);
}
public close() {
return this.instance.close();
}
public set(...args: any[]) {
return this.instance.set(...args);
}
public enable(...args: any[]) {
return this.instance.enable(...args);
}
public disable(...args: any[]) {
return this.instance.disable(...args);
}
public engine(...args: any[]) {
return this.instance.engine(...args);
}
public useStaticAssets(path: string, options: ServeStaticOptions) {
if (options && options.prefix) {
return this.use(options.prefix, express.static(path, options));
}
return this.use(express.static(path, options));
}
public setBaseViewsDir(path: string) {
return this.set('views', path);
}
public setViewEngine(engine: string) {
return this.set('view engine', engine);
}
public getRequestMethod(request): string {
return request.method;
}
public getRequestUrl(request): string {
return request.url;
}
public enableCors(options: CorsOptions) {
this.use(cors(options));
}
public createMiddlewareFactory(
requestMethod: RequestMethod,
): (path: string, callback: Function) => any {
return this.routerMethodFactory
.get(this.instance, requestMethod)
.bind(this.instance);
}
public initHttpServer(options: NestApplicationOptions) {
const isHttpsEnabled = options && options.httpsOptions;
if (isHttpsEnabled) {
this.httpServer = https.createServer(
options.httpsOptions,
this.getInstance(),
);
return;
}
this.httpServer = http.createServer(this.getInstance());
}
public registerParserMiddleware() {
const parserMiddleware = {
jsonParser: bodyParser.json(),
urlencodedParser: bodyParser.urlencoded({ extended: true }),
};
Object.keys(parserMiddleware)
.filter(parser => !this.isMiddlewareApplied(parser))
.forEach(parserKey => this.use(parserMiddleware[parserKey]));
}
private isMiddlewareApplied(name: string): boolean {
const app = this.getInstance();
return (
!!app._router &&
!!app._router.stack &&
isFunction(app._router.stack.filter) &&
app._router.stack.some(
(layer: any) => layer && layer.handle && layer.handle.name === name,
)
);
}
}

View File

@@ -0,0 +1 @@
export * from './express-adapter';

View File

@@ -0,0 +1,10 @@
/*
* Nest @platform-express
* Copyright(c) 2017 - 2018 Kamil Mysliwiec
* https://nestjs.com
* MIT Licensed
*/
export * from './adapters';
export * from './interfaces';
export * from './multer';

View File

@@ -0,0 +1 @@
export * from './nest-express-application.interface';

View File

@@ -1,6 +1,7 @@
import { ServeStaticOptions } from './external/serve-static-options.interface';
import { INestApplication } from '@nestjs/common';
import { ServeStaticOptions } from './serve-static-options.interface';
export interface INestExpressApplication {
export interface INestExpressApplication extends INestApplication {
/**
* A wrapper function around native `express.set()` method.
* Example `app.set('trust proxy', 'loopback')`
@@ -39,7 +40,7 @@ export interface INestExpressApplication {
*
* @returns {this}
*/
useStaticAssets(options: any): this;
useStaticAssets(options: ServeStaticOptions): this;
useStaticAssets(path: string, options?: ServeStaticOptions): this;
/**

View File

@@ -1,18 +1,20 @@
import {
CallHandler,
ExecutionContext,
Inject,
mixin,
NestInterceptor,
Optional,
Type,
} from '@nestjs/common';
import * as multer from 'multer';
import { Observable } from 'rxjs';
import { Inject, Optional } from '../../decorators';
import { mixin } from '../../decorators/core/injectable.decorator';
import { ExecutionContext, Type } from '../../interfaces';
import { MULTER_MODULE_OPTIONS } from '../files.constants';
import { MulterModuleOptions } from '../interfaces';
import {
MulterField,
MulterOptions,
} from '../../interfaces/external/multer-options.interface';
import {
CallHandler,
NestInterceptor,
} from '../../interfaces/features/nest-interceptor.interface';
import { MULTER_MODULE_OPTIONS } from '../files.constants';
import { MulterModuleOptions } from '../interfaces';
} from '../interfaces/multer-options.interface';
import { transformException } from '../multer/multer.utils';
type MulterInstance = any;
@@ -29,7 +31,7 @@ export function FileFieldsInterceptor(
@Inject(MULTER_MODULE_OPTIONS)
options: MulterModuleOptions = {},
) {
this.multer = multer({
this.multer = (multer as any)({
...options,
...localOptions,
});

View File

@@ -1,15 +1,17 @@
import * as multer from 'multer';
import { Observable } from 'rxjs';
import { Inject, Optional } from '../../decorators';
import { mixin } from '../../decorators/core/injectable.decorator';
import { ExecutionContext, Type } from '../../interfaces';
import { MulterOptions } from '../../interfaces/external/multer-options.interface';
import {
CallHandler,
ExecutionContext,
Inject,
mixin,
NestInterceptor,
} from '../../interfaces/features/nest-interceptor.interface';
Optional,
Type,
} from '@nestjs/common';
import * as multer from 'multer';
import { Observable } from 'rxjs';
import { MULTER_MODULE_OPTIONS } from '../files.constants';
import { MulterModuleOptions } from '../interfaces';
import { MulterOptions } from '../interfaces/multer-options.interface';
import { transformException } from '../multer/multer.utils';
type MulterInstance = any;
@@ -26,7 +28,7 @@ export function FileInterceptor(
@Inject(MULTER_MODULE_OPTIONS)
options: MulterModuleOptions = {},
) {
this.multer = multer({
this.multer = (multer as any)({
...options,
...localOptions,
});

View File

@@ -1,15 +1,17 @@
import * as multer from 'multer';
import { Observable } from 'rxjs';
import { Inject, Optional } from '../../decorators';
import { mixin } from '../../decorators/core/injectable.decorator';
import { ExecutionContext, Type } from '../../interfaces';
import { MulterOptions } from '../../interfaces/external/multer-options.interface';
import {
CallHandler,
ExecutionContext,
Inject,
mixin,
NestInterceptor,
} from '../../interfaces/features/nest-interceptor.interface';
Optional,
Type,
} from '@nestjs/common';
import * as multer from 'multer';
import { Observable } from 'rxjs';
import { MULTER_MODULE_OPTIONS } from '../files.constants';
import { MulterModuleOptions } from '../interfaces';
import { MulterOptions } from '../interfaces/multer-options.interface';
import { transformException } from '../multer/multer.utils';
type MulterInstance = any;
@@ -27,7 +29,7 @@ export function FilesInterceptor(
@Inject(MULTER_MODULE_OPTIONS)
options: MulterModuleOptions = {},
) {
this.multer = multer({
this.multer = (multer as any)({
...options,
...localOptions,
});

View File

@@ -1,5 +1,6 @@
import { ModuleMetadata, Type } from '../../interfaces';
import { MulterOptions } from '../../interfaces/external/multer-options.interface';
import { Type } from '@nestjs/common';
import { ModuleMetadata } from '@nestjs/common/interfaces';
import { MulterOptions } from '../interfaces/multer-options.interface';
export interface MulterModuleOptions extends MulterOptions {}

View File

@@ -1,5 +1,4 @@
import { Module } from './../decorators';
import { DynamicModule, Provider } from './../interfaces';
import { DynamicModule, Module, Provider } from '@nestjs/common';
import { MULTER_MODULE_OPTIONS } from './files.constants';
import {
MulterModuleAsyncOptions,

View File

@@ -1,4 +1,8 @@
import { BadRequestException, HttpException, PayloadTooLargeException } from '../../exceptions';
import {
BadRequestException,
HttpException,
PayloadTooLargeException,
} from '@nestjs/common';
import { multerExceptions } from './multer.constants';
export function transformException(error: Error | undefined) {

View File

@@ -0,0 +1,19 @@
{
"name": "@nestjs/platform-express",
"version": "5.4.1",
"description":
"Nest - modern, fast, powerful node.js web framework (@platform-express)",
"author": "Kamil Mysliwiec",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/nestjs/nest"
},
"dependencies": {
"body-parser": "1.18.3",
"cors": "2.8.4",
"express": "4.16.3",
"multer": "1.3.0"
},
"peerDependencies": {}
}

View File

@@ -1,9 +1,9 @@
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context.host';
import { CallHandler } from '@nestjs/common';
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host';
import { expect } from 'chai';
import { of } from 'rxjs';
import * as sinon from 'sinon';
import { FileFieldsInterceptor } from '../../../files/interceptors/file-fields.interceptor';
import { CallHandler } from '../../../interfaces/features/nest-interceptor.interface';
import { FileFieldsInterceptor } from '../../../multer/interceptors/file-fields.interceptor';
describe('FileFieldsInterceptor', () => {
it('should return metatype with expected structure', async () => {
@@ -57,9 +57,9 @@ describe('FileFieldsInterceptor', () => {
(target as any).fields = {
array: () => callback,
};
expect(
target.intercept(new ExecutionContextHost([]), handler),
).to.eventually.throw();
(target.intercept(new ExecutionContextHost([]), handler) as any).catch(
error => expect(error).to.not.be.undefined,
);
});
});
});

View File

@@ -1,9 +1,9 @@
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context.host';
import { CallHandler } from '@nestjs/common';
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host';
import { expect } from 'chai';
import { of } from 'rxjs';
import * as sinon from 'sinon';
import { FileInterceptor } from '../../../files/interceptors/file.interceptor';
import { CallHandler } from '../../../interfaces/features/nest-interceptor.interface';
import { FileInterceptor } from '../../../multer/interceptors/file.interceptor';
describe('FileInterceptor', () => {
it('should return metatype with expected structure', async () => {
@@ -39,9 +39,9 @@ describe('FileInterceptor', () => {
(target as any).multer = {
single: () => callback,
};
expect(
target.intercept(new ExecutionContextHost([]), handler),
).to.eventually.throw();
(target.intercept(new ExecutionContextHost([]), handler) as any).catch(
error => expect(error).to.not.be.undefined,
);
});
});
});

View File

@@ -1,9 +1,9 @@
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context.host';
import { CallHandler } from '@nestjs/common';
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host';
import { expect } from 'chai';
import { of } from 'rxjs';
import * as sinon from 'sinon';
import { FilesInterceptor } from '../../../files/interceptors/files.interceptor';
import { CallHandler } from '../../../interfaces/features/nest-interceptor.interface';
import { FilesInterceptor } from '../../../multer/interceptors/files.interceptor';
describe('FilesInterceptor', () => {
it('should return metatype with expected structure', async () => {
@@ -41,9 +41,9 @@ describe('FilesInterceptor', () => {
(target as any).multer = {
array: () => callback,
};
expect(
target.intercept(new ExecutionContextHost([]), handler),
).to.eventually.throw();
(target.intercept(new ExecutionContextHost([]), handler) as any).catch(
error => expect(error).to.not.be.undefined,
);
});
});
});

View File

@@ -1,8 +1,7 @@
import { expect } from 'chai';
import { MULTER_MODULE_OPTIONS } from '../../../files/files.constants';
import { MulterModule } from '../../../files/multer.module';
import { Provider, FactoryProvider } from '../../../interfaces';
import * as sinon from 'sinon';
import { MULTER_MODULE_OPTIONS } from '../../../multer/files.constants';
import { MulterModule } from '../../../multer/multer.module';
describe('MulterModule', () => {
describe('register', () => {

View File

@@ -1,11 +1,11 @@
import { expect } from 'chai';
import {
BadRequestException,
HttpException,
PayloadTooLargeException,
} from '../../../exceptions';
import { multerExceptions } from '../../../files/multer/multer.constants';
import { transformException } from '../../../files/multer/multer.utils';
} from '@nestjs/common';
import { expect } from 'chai';
import { multerExceptions } from '../../../multer/multer/multer.constants';
import { transformException } from '../../../multer/multer/multer.utils';
describe('transformException', () => {
describe('if error does not exist', () => {

View File

@@ -0,0 +1,7 @@
{
"extends": "./../tsconfig.base.json",
"compilerOptions": {
"baseUrl": "./"
},
"include": ["*.ts", "**/*.ts"]
}

View File

@@ -0,0 +1,76 @@
<p align="center">
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo_text.svg" width="320" alt="Nest Logo" /></a>
</p>
[travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master
[travis-url]: https://travis-ci.org/nestjs/nest
[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux
[linux-url]: https://travis-ci.org/nestjs/nest
<p align="center">A progressive <a href="http://nodejs.org" target="blank">Node.js</a> framework for building efficient and scalable server-side applications, heavily inspired by <a href="https://angular.io" target="blank">Angular</a>.</p>
<p align="center">
<a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
<a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
<a href="https://www.npmjs.com/~nestjscore"><img src="https://img.shields.io/npm/dm/@nestjs/core.svg" alt="NPM Downloads" /></a>
<a href="https://travis-ci.org/nestjs/nest"><img src="https://api.travis-ci.org/nestjs/nest.svg?branch=master" alt="Travis" /></a>
<a href="https://travis-ci.org/nestjs/nest"><img src="https://img.shields.io/travis/nestjs/nest/master.svg?label=linux" alt="Linux" /></a>
<a href="https://coveralls.io/github/nestjs/nest?branch=master"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#8" alt="Coverage" /></a>
<a href="https://gitter.im/nestjs/nestjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge"><img src="https://badges.gitter.im/nestjs/nestjs.svg" alt="Gitter" /></a>
<a href="https://opencollective.com/nest#backer"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
<a href="https://opencollective.com/nest#sponsor"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
<a href="https://paypal.me/kamilmysliwiec"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
<a href="https://twitter.com/nestframework"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
</p>
<!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
[![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->
## Description
<p>Nest is a framework for building efficient, scalable <a href="http://nodejs.org" target="_blank">Node.js</a> server-side applications. It uses modern JavaScript, is built with <a href="http://www.typescriptlang.org" target="_blank">TypeScript</a> (preserves compatibility with pure JavaScript) and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).</p>
<p>Under the hood, Nest makes use of <a href="https://expressjs.com/" target="_blank">Express</a>, but also, provides compatibility with a wide range of other libraries, like e.g. <a href="https://github.com/fastify/fastify" target="blank">Fastify</a>, allowing for easy use of the myriad third-party plugins which are available.</p>
## Philosophy
<p>In recent years, thanks to Node.js, JavaScript has become the “lingua franca” of the web for both front and backend applications, giving rise to awesome projects like <a href="https://angular.io/" target="_blank">Angular</a>, <a href="https://github.com/facebook/react" target="_blank">React</a> and <a href="https://github.com/vuejs/vue" target="_blank">Vue</a> which improve developer productivity and enable the construction of fast, testable, extensible frontend applications. However, on the server-side, while there are a lot of superb libraries, helpers and tools for Node, none of them effectively solve the main problem - the architecture.</p>
<p>Nest aims to provide an application architecture out of the box which allows for effortless creation of highly testable, scalable, loosely coupled and easily maintainable applications.</p>
## Getting started
* To check out the [guide](https://docs.nestjs.com), visit [docs.nestjs.com](https://docs.nestjs.com). :books:
* 要查看中文 [指南](readme_zh.md), 请访问 [docs.nestjs.cn](https://docs.nestjs.cn). :books:
## Support
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
#### Principal Sponsor
<a href="https://valor-software.com/"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="320" /></a>
#### Gold Sponsors
<a href="http://xtremis.com/"><img src="https://nestjs.com/img/logo-xtremis.svg" width="220" /></a>
#### Silver Sponsors
<a href="https://neoteric.eu/"><img src="https://nestjs.com/img/neoteric-cut.png" width="120" /></a> &nbsp;
<a href="http://gojob.com"><img src="http://nestjs.com/img/gojob-logo.png" valign="bottom" height="95" /></a> &nbsp; <a href="https://www.swingdev.io"><img src="https://nestjs.com/img/swingdev-logo.svg#1" width="150" /> </a>
#### Sponsors
<a href="https://scal.io"><img src="https://nestjs.com/img/scalio-logo.svg" width="110" /></a> &nbsp; <a href="http://angularity.io"><img src="http://angularity.io/media/logo.svg" height="30" /></a> &nbsp; <!--<a href="https://keycdn.com"><img src="https://nestjs.com/img/keycdn.svg" height="30" /></a> &nbsp;--> <a href="https://hostpresto.com"><img src="https://nestjs.com/img/hostpresto.png" height="30" /></a> &nbsp; <a href="https://genuinebee.com/"><img src="https://nestjs.com/img/genuinebee.svg" height="38" /></a> &nbsp; <a href="http://architectnow.net/"><img src="https://nestjs.com/img/architectnow.png" height="24" /></a> &nbsp; <a href="https://quander.io/"><img src="https://nestjs.com/img/quander.png" height="28" /></a>
## Backers
<a href="https://opencollective.com/nest"><img src="https://opencollective.com/nest/backers.svg?width=890"></a>
## Stay in touch
* Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
* Website - [https://nestjs.com](https://nestjs.com/)
* Twitter - [@nestframework](https://twitter.com/nestframework)
## License
Nest is [MIT licensed](LICENSE).

View File

@@ -0,0 +1,132 @@
import { RequestMethod } from '@nestjs/common';
import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface';
import { NestApplicationOptions } from '@nestjs/common/interfaces/nest-application-options.interface';
import { loadPackage } from '@nestjs/common/utils/load-package.util';
import { AbstractHttpAdapter } from '@nestjs/core/adapters/http-adapter';
import * as fastify from 'fastify';
import * as cors from 'fastify-cors';
import * as formBody from 'fastify-formbody';
import * as pathToRegexp from 'path-to-regexp';
export class FastifyAdapter extends AbstractHttpAdapter {
constructor(
instanceOrOptions:
| fastify.FastifyInstance<any, any, any>
| fastify.ServerOptions = fastify(),
) {
const instance =
instanceOrOptions &&
(instanceOrOptions as fastify.FastifyInstance<any, any, any>).server
? instanceOrOptions
: fastify(instanceOrOptions as fastify.ServerOptions);
super(instance);
}
public listen(port: string | number, callback?: () => void);
public listen(port: string | number, hostname: string, callback?: () => void);
public listen(port: any, hostname?: any, callback?: any) {
return this.instance.listen(port, hostname, callback);
}
public reply(response, body: any, statusCode: number) {
return response.code(statusCode).send(body);
}
public render(response, view: string, options: any) {
return response.view(view, options);
}
public setErrorHandler(handler: Function) {
return this.instance.setErrorHandler(handler);
}
public setNotFoundHandler(handler: Function) {
return this.instance.setNotFoundHandler(handler);
}
public getHttpServer<T = any>(): T {
return this.instance.server as T;
}
public getInstance<T = any>(): T {
return this.instance as T;
}
public register(...args: any[]) {
return this.instance.register(...args);
}
public inject(...args: any[]) {
return this.instance.inject(...args);
}
public close() {
return this.instance.close();
}
public initHttpServer(options: NestApplicationOptions) {
this.httpServer = this.instance.server;
}
public useStaticAssets(options: {
root: string;
prefix?: string;
setHeaders?: Function;
send?: any;
}) {
return this.register(
loadPackage('fastify-static', 'FastifyAdapter.useStaticAssets()'),
options,
);
}
setViewEngine(options: any) {
return this.register(
loadPackage('point-of-view', 'FastifyAdapter.setViewEngine()'),
options,
);
}
public setHeader(response, name: string, value: string) {
return response.header(name, value);
}
public getRequestMethod(request): string {
return request.raw.method;
}
public getRequestUrl(request): string {
return request.raw.url;
}
public enableCors(options: CorsOptions) {
this.register(cors(options));
}
public registerParserMiddleware() {
this.register(formBody);
}
public createMiddlewareFactory(
requestMethod: RequestMethod,
): (path: string, callback: Function) => any {
return (path: string, callback: Function) => {
const re = pathToRegexp(path);
const normalizedPath = path === '/*' ? '' : path;
this.instance.use(normalizedPath, (req, res, next) => {
if (!re.exec(req.originalUrl + '/')) {
return next();
}
if (
requestMethod === RequestMethod.ALL ||
req.method === RequestMethod[requestMethod]
) {
return callback(req, res, next);
}
next();
});
};
}
}

View File

@@ -0,0 +1 @@
export * from './fastify-adapter';

View File

@@ -0,0 +1,9 @@
/*
* Nest @platform-express
* Copyright(c) 2017 - 2018 Kamil Mysliwiec
* https://nestjs.com
* MIT Licensed
*/
export * from './adapters';
export * from './interfaces';

View File

@@ -0,0 +1 @@
export * from './nest-fastify-application.interface';

View File

@@ -1,4 +1,7 @@
export interface INestFastifyApplication {
import { INestApplication } from '@nestjs/common';
import { HTTPInjectOptions, HTTPInjectResponse } from 'fastify';
export interface INestFastifyApplication extends INestApplication {
/**
* A wrapper function around native `fastify.register()` method.
* Example `app.register(require('fastify-formbody'))`
@@ -33,45 +36,3 @@ export interface INestFastifyApplication {
*/
inject(opts: HTTPInjectOptions | string): Promise<HTTPInjectResponse>;
}
/** Reference: https://github.com/fastify/fastify */
export type HTTPMethod =
| 'DELETE'
| 'GET'
| 'HEAD'
| 'PATCH'
| 'POST'
| 'PUT'
| 'OPTIONS';
/**
* Fake http inject options
*/
export interface HTTPInjectOptions {
url: string;
method?: HTTPMethod;
authority?: string;
headers?: object;
remoteAddress?: string;
payload?: string | object | Buffer | any;
simulate?: {
end?: boolean;
split?: boolean;
error?: boolean;
close?: boolean;
};
validate?: boolean;
}
/**
* Fake http inject response
*/
export interface HTTPInjectResponse {
raw: any;
headers: object;
statusCode: number;
statusMessage: string;
payload: string;
rawPayload: Buffer;
trailers: object;
}

View File

@@ -0,0 +1,19 @@
{
"name": "@nestjs/platform-fastify",
"version": "5.4.1",
"description":
"Nest - modern, fast, powerful node.js web framework (@platform-fastify)",
"author": "Kamil Mysliwiec",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/nestjs/nest"
},
"dependencies": {
"fastify": "^1.13.1",
"fastify-cors": "^0.2.0",
"fastify-formbody": "2.0.3",
"path-to-regexp": "2.2.1"
},
"peerDependencies": {}
}

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