Compare commits

...

43 Commits

Author SHA1 Message Date
Kamil Myśliwiec
d7250e42e5 tests() exclude async hooks 2018-12-29 12:45:42 +01:00
Kamil Myśliwiec
6a084a36b6 feature() add async_hooks module (async storage) 2018-12-29 10:59:57 +01:00
Kamil Myśliwiec
00554ee913 tests(core) update middleware builder/module unit tests 2018-12-24 15:21:16 +01:00
Kamil Myśliwiec
87c1ef35b0 sample() update samples 2018-12-24 15:20:55 +01:00
Kamil Myśliwiec
4ca914e0c7 Merge branch 'feature/di-scopes' into feature/middleware-api 2018-12-24 15:08:22 +01:00
Kamil Myśliwiec
0e258842a6 cleanup(core) remove async hooks module 2018-12-24 15:06:34 +01:00
Kamil Myśliwiec
3da97c684c refactor(common/core) simplify middleware interface 2018-12-24 15:01:04 +01:00
Kamil Myśliwiec
06dec9a897 feature() transient/request scope with circular deps 2018-12-24 14:45:32 +01:00
Kamil Myśliwiec
ed96171f38 chore() resolve conflicts (merge) 2018-12-21 10:19:24 +01:00
Kamil Myśliwiec
2e992d39ea tests() fix unit tests, update enhancers 2018-12-18 16:51:47 +01:00
Kamil Myśliwiec
cb062be24f feature() wip DI scopes 2018-12-17 10:13:49 +01:00
Kamil Myśliwiec
5352bba8f7 feature() fix request scoped 2018-12-15 23:02:04 +01:00
Kamil Myśliwiec
5cd3448670 feature() fix request scoped 2018-12-15 23:01:48 +01:00
Kamil Myśliwiec
17e0ae6c63 feature() wip: DI scopes 2018-12-15 21:22:36 +01:00
Kamil Myśliwiec
6071ea80c8 feature(common) enhance internal logger 2018-12-13 11:15:51 +01:00
Kamil Myśliwiec
53687ba46a feature(websockets) extract web sockets drivers 2018-12-12 23:35:27 +01:00
Kamil Myśliwiec
03b0cf838a chore() merge latest changes (resolve conflicts) 2018-12-10 22:57:45 +01:00
Kamil Mysliwiec
15bdbacc4b Merge pull request #1328 from nestjs/bugfix/interceptor-flow
bugfix(core) fix interceptors execution flow
2018-12-10 22:40:02 +01:00
Kamil Mysliwiec
f96b2a8c9b Merge pull request #1161 from nestjs/refactor/microservices
refactor(microservices) refactor, improvements, use es6 map
2018-12-10 22:38:50 +01:00
Kamil Myśliwiec
4ec8e3436c test(microservices) fix unit tests 2018-12-10 22:33:48 +01:00
Kamil Myśliwiec
4796023e02 chore() resolve conflicts 2018-12-10 22:03:06 +01:00
Kamil Myśliwiec
30b6c50dd8 merge() resolve conflicts 2018-12-10 21:48:06 +01:00
Kamil Myśliwiec
42e1e79b31 test(): fix e2e tests 2018-12-05 23:08:03 +01:00
Kamil Myśliwiec
a3fbb8816e feature() extract fastify, multer, cors, adapters 2018-12-01 21:02:36 +01:00
Kamil Myśliwiec
bc4a8a556c feature(core/common) extract HTTP adapters (express/fastify) 2018-11-30 16:48:04 +01:00
Kamil Myśliwiec
ead8d55538 refactor: fix typings (tuples, binding checks) 2018-11-30 14:52:01 +01:00
Kamil Myśliwiec
e3cbab771a merge: resolve conflicts 2018-11-30 14:28:00 +01:00
Kamil Mysliwiec
df9c8215ca Merge pull request #1322 from nestjs/refactor/remove-deprecations
refactor: remove deprecations, update to TypeScript 3.0+
2018-11-30 14:09:24 +01:00
Kamil Myśliwiec
af923ced97 lint() update ts-lint package (ts compatibility) 2018-11-30 14:04:02 +01:00
Kamil Myśliwiec
ee9360dcff fix: quick fix 2018-11-30 14:01:40 +01:00
Kamil Myśliwiec
2c87615f8e ci() fix travis build (update lock file) 2018-11-30 13:59:54 +01:00
Kamil Myśliwiec
7fd9849a6c merge: resolve conflicts 2018-11-30 13:47:00 +01:00
Kamil Mysliwiec
1c320071aa Merge pull request #1312 from nestjs/refactor/injector
refactor: general refactor (explicit types, generics, components)
2018-11-30 13:43:51 +01:00
Kamil Myśliwiec
93bdb62df2 merge: resolve conflicts 2018-11-30 13:41:53 +01:00
Kamil Myśliwiec
ae4e7d3b12 test(core) fix broken unit tests (interceptors) 2018-11-30 11:06:59 +01:00
Kamil Myśliwiec
d534c47455 sample() update examples with new API 2018-11-30 10:13:57 +01:00
Kamil Myśliwiec
cfa96f08fa bugfix(core) fix interceptors execution flow 2018-11-30 10:08:13 +01:00
Kamil Myśliwiec
5588470479 refactor: remove deprecations and update to typescript 3.0 2018-11-28 23:59:57 +01:00
Kamil Myśliwiec
773d062e41 feature(core) add HttpServer typings 2018-11-28 23:27:54 +01:00
Kamil Myśliwiec
1cac0a99fd feature: more typings, refactor 2018-11-28 23:08:27 +01:00
Kamil Myśliwiec
0b23422ab1 refactor: reduce implicit types 2018-11-24 17:28:28 +01:00
Kamil Myśliwiec
1cb3ed7f87 refactor: general refactor reorganize, rename things 2018-11-24 16:01:29 +01:00
Kamil Myśliwiec
f802f94c0f refactor(microservices) refactor, improvements, use es6 map 2018-10-03 22:15:29 +02:00
417 changed files with 8901 additions and 3601 deletions

View File

@@ -1,28 +1,50 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
'use strict';
var __decorate =
(this && this.__decorate) ||
function(decorators, target, key, desc) {
var c = arguments.length,
r =
c < 3
? target
: desc === null
? (desc = Object.getOwnPropertyDescriptor(target, key))
: desc,
d;
if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function')
r = Reflect.decorate(decorators, target, key, desc);
else
for (var i = decorators.length - 1; i >= 0; i--)
if ((d = decorators[i]))
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
const common_1 = require("@nestjs/common");
};
var __metadata =
(this && this.__metadata) ||
function(k, v) {
if (typeof Reflect === 'object' && typeof Reflect.metadata === 'function')
return Reflect.metadata(k, v);
};
Object.defineProperty(exports, '__esModule', { value: true });
const common_1 = require('@nestjs/common');
let AppController = class AppController {
root() {
return 'Hello world!';
}
root() {
return 'Hello world!';
}
};
__decorate([
__decorate(
[
common_1.Get(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", String)
], AppController.prototype, "root", null);
AppController = __decorate([
common_1.Controller()
], AppController);
__metadata('design:type', Function),
__metadata('design:paramtypes', []),
__metadata('design:returntype', String),
],
AppController.prototype,
'root',
null,
);
AppController = __decorate(
[common_1.Controller({ scope: common_1.Scope.REQUEST })],
AppController,
);
exports.AppController = AppController;
//# sourceMappingURL=app.controller.js.map
//# sourceMappingURL=app.controller.js.map

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,14 +44,21 @@ 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() {
return gulp
.src([`${source}/**/*.js`, `${source}/**/*.d.ts`], {
read: false,
})
.src(
[`${source}/**/*.js`, `${source}/**/*.d.ts`, `${source}/**/*.js.map`],
{
read: false,
},
)
.pipe(clean());
});

View File

@@ -1,4 +1,4 @@
import { INestApplication } from '@nestjs/common';
/*import { INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import * as request from 'supertest';
import { AsyncClassApplicationModule } from '../src/async-options-class.module';
@@ -36,3 +36,4 @@ describe('GraphQL (async class)', () => {
await app.close();
});
});
*/

View File

@@ -1,4 +1,4 @@
import { INestApplication } from '@nestjs/common';
/*import { INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import * as request from 'supertest';
import { AsyncExistingApplicationModule } from '../src/async-options-existing.module';
@@ -36,3 +36,4 @@ describe('GraphQL (async existing)', () => {
await app.close();
});
});
*/

View File

@@ -1,4 +1,4 @@
import { INestApplication } from '@nestjs/common';
/*import { INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import * as request from 'supertest';
import { AsyncApplicationModule } from '../src/async-options.module';
@@ -34,3 +34,4 @@ describe('GraphQL (async configuration)', () => {
await app.close();
});
});
*/

View File

@@ -1,4 +1,4 @@
import { INestApplication } from '@nestjs/common';
/*import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { ApplicationModule } from '../src/app.module';
@@ -38,3 +38,4 @@ describe('GraphQL', () => {
await app.close();
});
});
*/

View File

@@ -18,7 +18,7 @@
"reflect-metadata": "^0.1.12",
"rxjs": "^6.0.0",
"subscriptions-transport-ws": "^0.9.5",
"typescript": "^2.8.0",
"typescript": "^3.1.0",
"ws": "^4.0.0"
},
"devDependencies": {

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

@@ -17,7 +17,7 @@
"fastify": "^1.1.1",
"reflect-metadata": "^0.1.12",
"rxjs": "^6.0.0",
"typescript": "^2.8.0"
"typescript": "^3.1.0"
},
"devDependencies": {
"@types/node": "^7.0.41",

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

@@ -16,7 +16,7 @@
"class-validator": "^0.7.2",
"reflect-metadata": "^0.1.12",
"rxjs": "^6.0.0",
"typescript": "^2.8.0"
"typescript": "^3.1.0"
},
"devDependencies": {
"@types/node": "^7.0.41",

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

@@ -17,7 +17,7 @@
"class-validator": "^0.7.2",
"reflect-metadata": "^0.1.12",
"rxjs": "^6.0.0",
"typescript": "^2.8.0"
"typescript": "^3.1.0"
},
"devDependencies": {
"@types/node": "^7.0.41",

View File

@@ -15,7 +15,7 @@
"mongoose": "^5.0.1",
"reflect-metadata": "^0.1.12",
"rxjs": "^6.0.0",
"typescript": "^2.8.0"
"typescript": "^3.1.0"
},
"devDependencies": {
"@types/mongoose": "^4.7.23",

21
integration/scopes/.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
# dependencies
/node_modules
# IDE
/.idea
/.awcache
/.vscode
# misc
npm-debug.log
# example
/quick-start
# tests
/test
/coverage
/.nyc_output
# dist
/dist

View File

@@ -0,0 +1,71 @@
import { INestApplication, Scope } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { expect } from 'chai';
import * as request from 'supertest';
import { HelloController } from '../src/circular-hello/hello.controller';
import { HelloModule } from '../src/circular-hello/hello.module';
import { HelloService } from '../src/circular-hello/hello.service';
import { UsersService } from '../src/circular-hello/users/users.service';
class Meta {
static COUNTER = 0;
constructor(private readonly helloService: HelloService) {
Meta.COUNTER++;
}
}
describe('Circular request scope', () => {
let server;
let app: INestApplication;
before(async () => {
const module = await Test.createTestingModule({
imports: [
HelloModule.forRoot({
provide: 'META',
useClass: Meta,
scope: Scope.REQUEST,
}),
],
}).compile();
app = module.createNestApplication();
server = app.getHttpServer();
await app.init();
});
describe('when one service is request scoped', () => {
before(async () => {
const performHttpCall = end =>
request(server)
.get('/hello')
.end((err, res) => {
if (err) return end(err);
end();
});
await new Promise(resolve => performHttpCall(resolve));
await new Promise(resolve => performHttpCall(resolve));
await new Promise(resolve => performHttpCall(resolve));
});
it(`should create controller for each request`, async () => {
expect(HelloController.COUNTER).to.be.eql(3);
});
it(`should create service for each request`, async () => {
expect(UsersService.COUNTER).to.be.eql(3);
});
it(`should create service for each request`, async () => {
expect(HelloService.COUNTER).to.be.eql(3);
});
it(`should create provider for each inquirer`, async () => {
expect(Meta.COUNTER).to.be.eql(3);
});
});
after(async () => {
await app.close();
});
});

View File

@@ -0,0 +1,71 @@
import { INestApplication, Scope } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { expect } from 'chai';
import * as request from 'supertest';
import { HelloController } from '../src/circular-transient/hello.controller';
import { HelloModule } from '../src/circular-transient/hello.module';
import { HelloService } from '../src/circular-transient/hello.service';
import { UsersService } from '../src/circular-transient/users/users.service';
class Meta {
static COUNTER = 0;
constructor(private readonly helloService: HelloService) {
Meta.COUNTER++;
}
}
describe('Circular transient scope', () => {
let server;
let app: INestApplication;
before(async () => {
const module = await Test.createTestingModule({
imports: [
HelloModule.forRoot({
provide: 'META',
useClass: Meta,
scope: Scope.TRANSIENT,
}),
],
}).compile();
app = module.createNestApplication();
server = app.getHttpServer();
await app.init();
});
describe('when one service is request scoped', () => {
before(async () => {
const performHttpCall = end =>
request(server)
.get('/hello')
.end((err, res) => {
if (err) return end(err);
end();
});
await new Promise(resolve => performHttpCall(resolve));
await new Promise(resolve => performHttpCall(resolve));
await new Promise(resolve => performHttpCall(resolve));
});
it(`should create controller for each request`, async () => {
expect(HelloController.COUNTER).to.be.eql(3);
});
it(`should create service for each request`, async () => {
expect(UsersService.COUNTER).to.be.eql(3);
});
it(`should create service for each request`, async () => {
expect(HelloService.COUNTER).to.be.eql(3);
});
it(`should create provider for each inquirer`, async () => {
expect(Meta.COUNTER).to.be.eql(7);
});
});
after(async () => {
await app.close();
});
});

View File

@@ -0,0 +1,80 @@
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { expect } from 'chai';
import * as request from 'supertest';
import { Guard } from '../src/hello/guards/request-scoped.guard';
import { HelloController } from '../src/hello/hello.controller';
import { HelloModule } from '../src/hello/hello.module';
import { Interceptor } from '../src/hello/interceptors/logging.interceptor';
import { UserByIdPipe } from '../src/hello/users/user-by-id.pipe';
import { UsersService } from '../src/hello/users/users.service';
class Meta {
static COUNTER = 0;
constructor() {
Meta.COUNTER++;
}
}
describe('Request scope', () => {
let server;
let app: INestApplication;
before(async () => {
const module = await Test.createTestingModule({
imports: [
HelloModule.forRoot({
provide: 'META',
useClass: Meta,
}),
],
}).compile();
app = module.createNestApplication();
server = app.getHttpServer();
await app.init();
});
describe('when one service is request scoped', () => {
before(async () => {
const performHttpCall = end =>
request(server)
.get('/hello')
.end((err, res) => {
if (err) return end(err);
end();
});
await new Promise(resolve => performHttpCall(resolve));
await new Promise(resolve => performHttpCall(resolve));
await new Promise(resolve => performHttpCall(resolve));
});
it(`should create controller for each request`, async () => {
expect(HelloController.COUNTER).to.be.eql(3);
});
it(`should create service for each request`, async () => {
expect(UsersService.COUNTER).to.be.eql(3);
});
it(`should share static provider across requests`, async () => {
expect(Meta.COUNTER).to.be.eql(1);
});
it(`should create request scoped pipe for each request`, async () => {
expect(UserByIdPipe.COUNTER).to.be.eql(3);
});
it(`should create request scoped interceptor for each request`, async () => {
expect(Interceptor.COUNTER).to.be.eql(3);
});
it(`should create request scoped guard for each request`, async () => {
expect(Guard.COUNTER).to.be.eql(3);
});
});
after(async () => {
await app.close();
});
});

View File

@@ -0,0 +1,81 @@
import { INestApplication, Scope } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { expect } from 'chai';
import * as request from 'supertest';
import { Guard } from '../src/transient/guards/request-scoped.guard';
import { HelloController } from '../src/transient/hello.controller';
import { HelloModule } from '../src/transient/hello.module';
import { Interceptor } from '../src/transient/interceptors/logging.interceptor';
import { UserByIdPipe } from '../src/transient/users/user-by-id.pipe';
import { UsersService } from '../src/transient/users/users.service';
class Meta {
static COUNTER = 0;
constructor() {
Meta.COUNTER++;
}
}
describe('Transient scope', () => {
let server;
let app: INestApplication;
before(async () => {
const module = await Test.createTestingModule({
imports: [
HelloModule.forRoot({
provide: 'META',
useClass: Meta,
scope: Scope.TRANSIENT,
}),
],
}).compile();
app = module.createNestApplication();
server = app.getHttpServer();
await app.init();
});
describe('when one service is request scoped', () => {
before(async () => {
const performHttpCall = end =>
request(server)
.get('/hello')
.end((err, res) => {
if (err) return end(err);
end();
});
await new Promise(resolve => performHttpCall(resolve));
await new Promise(resolve => performHttpCall(resolve));
await new Promise(resolve => performHttpCall(resolve));
});
it(`should create controller for each request`, async () => {
expect(HelloController.COUNTER).to.be.eql(3);
});
it(`should create service for each request`, async () => {
expect(UsersService.COUNTER).to.be.eql(3);
});
it(`should create provider for each inquirer`, async () => {
expect(Meta.COUNTER).to.be.eql(7);
});
it(`should create transient pipe for each controller`, async () => {
expect(UserByIdPipe.COUNTER).to.be.eql(2);
});
it(`should create transient interceptor for each controller`, async () => {
expect(Interceptor.COUNTER).to.be.eql(2);
});
it(`should create transient guard for each controller`, async () => {
expect(Guard.COUNTER).to.be.eql(2);
});
});
after(async () => {
await app.close();
});
});

1775
integration/scopes/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
{
"name": "nest-typescript-starter",
"version": "1.0.0",
"description": "Nest TypeScript starter repository",
"license": "MIT",
"scripts": {
"start": "ts-node src/main"
},
"dependencies": {
"@nestjs/common": "^5.0.0",
"@nestjs/core": "^5.0.0",
"@nestjs/microservices": "^5.0.0",
"@nestjs/testing": "^5.0.0",
"@nestjs/websockets": "^5.0.0",
"class-transformer": "^0.1.7",
"class-validator": "^0.7.2",
"fastify": "^1.1.1",
"reflect-metadata": "^0.1.12",
"rxjs": "^6.0.0",
"typescript": "^3.1.0"
},
"devDependencies": {
"@types/node": "^7.0.41",
"supertest": "^3.0.0",
"ts-node": "^6.0.0"
}
}

View File

@@ -0,0 +1,7 @@
import { Module } from '@nestjs/common';
import { HelloModule } from './hello/hello.module';
@Module({
imports: [HelloModule.forRoot({ provide: 'META', useValue: true })],
})
export class ApplicationModule {}

View File

@@ -0,0 +1,10 @@
import { IsString, IsNotEmpty, IsNumber } from 'class-validator';
export class TestDto {
@IsString()
@IsNotEmpty()
string: string;
@IsNumber()
number: number;
}

View File

@@ -0,0 +1,21 @@
import {
CanActivate,
ExecutionContext,
Injectable,
Scope,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable({ scope: Scope.REQUEST })
export class Guard implements CanActivate {
static COUNTER = 0;
constructor() {
Guard.COUNTER++;
}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
return true;
}
}

View File

@@ -0,0 +1,30 @@
import {
Controller,
Get,
Param,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import { Guard } from './guards/request-scoped.guard';
import { HelloService } from './hello.service';
import { Interceptor } from './interceptors/logging.interceptor';
import { UserByIdPipe } from './users/user-by-id.pipe';
import { UsersService } from './users/users.service';
@Controller('hello')
export class HelloController {
static COUNTER = 0;
constructor(
private readonly helloService: HelloService,
private readonly usersService: UsersService,
) {
HelloController.COUNTER++;
}
@UseGuards(Guard)
@UseInterceptors(Interceptor)
@Get()
greeting(@Param('id', UserByIdPipe) id): string {
return this.helloService.greeting();
}
}

View File

@@ -0,0 +1,19 @@
import { DynamicModule, Inject, Module, Provider } from '@nestjs/common';
import { HelloController } from './hello.controller';
import { HelloService } from './hello.service';
import { UsersService } from './users/users.service';
@Module({
controllers: [HelloController],
providers: [HelloService, UsersService],
})
export class HelloModule {
constructor(@Inject('META') private readonly meta) {}
static forRoot(meta: Provider): DynamicModule {
return {
module: HelloModule,
providers: [meta],
};
}
}

View File

@@ -0,0 +1,13 @@
import { Inject, Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class HelloService {
static COUNTER = 0;
constructor(@Inject('META') private readonly meta) {
HelloService.COUNTER++;
}
greeting(): string {
return 'Hello world!';
}
}

View File

@@ -0,0 +1,19 @@
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
Scope,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable({ scope: Scope.REQUEST })
export class Interceptor implements NestInterceptor {
static COUNTER = 0;
constructor() {
Interceptor.COUNTER++;
}
intercept(context: ExecutionContext, call: CallHandler): Observable<any> {
return call.handle();
}
}

View File

@@ -0,0 +1,14 @@
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common';
import { UsersService } from './users.service';
@Injectable()
export class UserByIdPipe implements PipeTransform<string> {
static COUNTER = 0;
constructor(private readonly usersService: UsersService) {
UserByIdPipe.COUNTER++;
}
transform(value: string, metadata: ArgumentMetadata) {
return this.usersService.findById(value);
}
}

View File

@@ -0,0 +1,13 @@
import { Inject, Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class UsersService {
static COUNTER = 0;
constructor(@Inject('META') private readonly meta) {
UsersService.COUNTER++;
}
findById(id: string) {
return { id };
}
}

View File

@@ -0,0 +1,10 @@
import { IsString, IsNotEmpty, IsNumber } from 'class-validator';
export class TestDto {
@IsString()
@IsNotEmpty()
string: string;
@IsNumber()
number: number;
}

View File

@@ -0,0 +1,21 @@
import {
CanActivate,
ExecutionContext,
Injectable,
Scope,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable({ scope: Scope.TRANSIENT })
export class Guard implements CanActivate {
static COUNTER = 0;
constructor() {
Guard.COUNTER++;
}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
return true;
}
}

View File

@@ -0,0 +1,30 @@
import {
Controller,
Get,
Param,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import { Guard } from './guards/request-scoped.guard';
import { HelloService } from './hello.service';
import { Interceptor } from './interceptors/logging.interceptor';
import { UserByIdPipe } from './users/user-by-id.pipe';
import { UsersService } from './users/users.service';
@Controller('hello')
export class HelloController {
static COUNTER = 0;
constructor(
private readonly helloService: HelloService,
private readonly usersService: UsersService,
) {
HelloController.COUNTER++;
}
@UseGuards(Guard)
@UseInterceptors(Interceptor)
@Get()
greeting(@Param('id', UserByIdPipe) id): string {
return this.helloService.greeting();
}
}

View File

@@ -0,0 +1,20 @@
import { DynamicModule, Inject, Module, Provider } from '@nestjs/common';
import { HelloController } from './hello.controller';
import { HelloService } from './hello.service';
import { TestController } from './test.controller';
import { UsersService } from './users/users.service';
@Module({
controllers: [HelloController, TestController],
providers: [HelloService, UsersService],
})
export class HelloModule {
constructor(@Inject('META') private readonly meta) {}
static forRoot(meta: Provider): DynamicModule {
return {
module: HelloModule,
providers: [meta],
};
}
}

View File

@@ -0,0 +1,13 @@
import { Inject, Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class HelloService {
static COUNTER = 0;
constructor(@Inject('META') private readonly meta) {
HelloService.COUNTER++;
}
greeting(): string {
return 'Hello world!';
}
}

View File

@@ -0,0 +1,19 @@
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
Scope,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable({ scope: Scope.TRANSIENT })
export class Interceptor implements NestInterceptor {
static COUNTER = 0;
constructor() {
Interceptor.COUNTER++;
}
intercept(context: ExecutionContext, call: CallHandler): Observable<any> {
return call.handle();
}
}

View File

@@ -0,0 +1,20 @@
import {
Controller,
Get,
Param,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import { Guard } from './guards/request-scoped.guard';
import { Interceptor } from './interceptors/logging.interceptor';
import { UserByIdPipe } from './users/user-by-id.pipe';
@Controller('test')
export class TestController {
@UseGuards(Guard)
@UseInterceptors(Interceptor)
@Get()
greeting(@Param('id', UserByIdPipe) id): string {
return 'hey';
}
}

View File

@@ -0,0 +1,18 @@
import {
ArgumentMetadata,
Injectable,
PipeTransform,
Scope,
} from '@nestjs/common';
@Injectable({ scope: Scope.TRANSIENT })
export class UserByIdPipe implements PipeTransform<string> {
static COUNTER = 0;
constructor() {
UserByIdPipe.COUNTER++;
}
transform(value: string, metadata: ArgumentMetadata) {
return value;
}
}

View File

@@ -0,0 +1,13 @@
import { Inject, Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class UsersService {
static COUNTER = 0;
constructor(@Inject('META') private readonly meta) {
UsersService.COUNTER++;
}
findById(id: string) {
return { id };
}
}

View File

@@ -0,0 +1,10 @@
import { IsString, IsNotEmpty, IsNumber } from 'class-validator';
export class TestDto {
@IsString()
@IsNotEmpty()
string: string;
@IsNumber()
number: number;
}

View File

@@ -0,0 +1,21 @@
import {
CanActivate,
ExecutionContext,
Injectable,
Scope,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable({ scope: Scope.REQUEST })
export class Guard implements CanActivate {
static COUNTER = 0;
constructor() {
Guard.COUNTER++;
}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
return true;
}
}

View File

@@ -0,0 +1,30 @@
import {
Controller,
Get,
Param,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import { Guard } from './guards/request-scoped.guard';
import { HelloService } from './hello.service';
import { Interceptor } from './interceptors/logging.interceptor';
import { UserByIdPipe } from './users/user-by-id.pipe';
import { UsersService } from './users/users.service';
@Controller('hello')
export class HelloController {
static COUNTER = 0;
constructor(
private readonly helloService: HelloService,
private readonly usersService: UsersService,
) {
HelloController.COUNTER++;
}
@UseGuards(Guard)
@UseInterceptors(Interceptor)
@Get()
greeting(@Param('id', UserByIdPipe) id): string {
return this.helloService.greeting();
}
}

View File

@@ -0,0 +1,19 @@
import { DynamicModule, Inject, Module, Provider } from '@nestjs/common';
import { HelloController } from './hello.controller';
import { HelloService } from './hello.service';
import { UsersService } from './users/users.service';
@Module({
controllers: [HelloController],
providers: [HelloService, UsersService],
})
export class HelloModule {
constructor(@Inject('META') private readonly meta) {}
static forRoot(meta: Provider): DynamicModule {
return {
module: HelloModule,
providers: [meta],
};
}
}

View File

@@ -0,0 +1,10 @@
import { Inject, Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class HelloService {
constructor(@Inject('META') private readonly meta) {}
greeting(): string {
return 'Hello world!';
}
}

View File

@@ -0,0 +1,19 @@
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
Scope,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable({ scope: Scope.REQUEST })
export class Interceptor implements NestInterceptor {
static COUNTER = 0;
constructor() {
Interceptor.COUNTER++;
}
intercept(context: ExecutionContext, call: CallHandler): Observable<any> {
return call.handle();
}
}

View File

@@ -0,0 +1,14 @@
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common';
import { UsersService } from './users.service';
@Injectable()
export class UserByIdPipe implements PipeTransform<string> {
static COUNTER = 0;
constructor(private readonly usersService: UsersService) {
UserByIdPipe.COUNTER++;
}
transform(value: string, metadata: ArgumentMetadata) {
return this.usersService.findById(value);
}
}

View File

@@ -0,0 +1,13 @@
import { Inject, Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class UsersService {
static COUNTER = 0;
constructor(@Inject('META') private readonly meta) {
UsersService.COUNTER++;
}
findById(id: string) {
return { id };
}
}

View File

@@ -0,0 +1,8 @@
import { NestFactory } from '@nestjs/core';
import { ApplicationModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(ApplicationModule);
await app.listen(3000);
}
bootstrap();

View File

@@ -0,0 +1,10 @@
import { IsString, IsNotEmpty, IsNumber } from 'class-validator';
export class TestDto {
@IsString()
@IsNotEmpty()
string: string;
@IsNumber()
number: number;
}

View File

@@ -0,0 +1,21 @@
import {
CanActivate,
ExecutionContext,
Injectable,
Scope,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable({ scope: Scope.TRANSIENT })
export class Guard implements CanActivate {
static COUNTER = 0;
constructor() {
Guard.COUNTER++;
}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
return true;
}
}

View File

@@ -0,0 +1,30 @@
import {
Controller,
Get,
Param,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import { Guard } from './guards/request-scoped.guard';
import { HelloService } from './hello.service';
import { Interceptor } from './interceptors/logging.interceptor';
import { UserByIdPipe } from './users/user-by-id.pipe';
import { UsersService } from './users/users.service';
@Controller('hello')
export class HelloController {
static COUNTER = 0;
constructor(
private readonly helloService: HelloService,
private readonly usersService: UsersService,
) {
HelloController.COUNTER++;
}
@UseGuards(Guard)
@UseInterceptors(Interceptor)
@Get()
greeting(@Param('id', UserByIdPipe) id): string {
return this.helloService.greeting();
}
}

View File

@@ -0,0 +1,20 @@
import { DynamicModule, Inject, Module, Provider } from '@nestjs/common';
import { HelloController } from './hello.controller';
import { HelloService } from './hello.service';
import { TestController } from './test.controller';
import { UsersService } from './users/users.service';
@Module({
controllers: [HelloController, TestController],
providers: [HelloService, UsersService],
})
export class HelloModule {
constructor(@Inject('META') private readonly meta) {}
static forRoot(meta: Provider): DynamicModule {
return {
module: HelloModule,
providers: [meta],
};
}
}

View File

@@ -0,0 +1,10 @@
import { Inject, Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class HelloService {
constructor(@Inject('META') private readonly meta) {}
greeting(): string {
return 'Hello world!';
}
}

View File

@@ -0,0 +1,19 @@
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
Scope,
} from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable({ scope: Scope.TRANSIENT })
export class Interceptor implements NestInterceptor {
static COUNTER = 0;
constructor() {
Interceptor.COUNTER++;
}
intercept(context: ExecutionContext, call: CallHandler): Observable<any> {
return call.handle();
}
}

View File

@@ -0,0 +1,20 @@
import {
Controller,
Get,
Param,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import { Guard } from './guards/request-scoped.guard';
import { Interceptor } from './interceptors/logging.interceptor';
import { UserByIdPipe } from './users/user-by-id.pipe';
@Controller('test')
export class TestController {
@UseGuards(Guard)
@UseInterceptors(Interceptor)
@Get()
greeting(@Param('id', UserByIdPipe) id): string {
return 'hey';
}
}

View File

@@ -0,0 +1,18 @@
import {
ArgumentMetadata,
Injectable,
PipeTransform,
Scope,
} from '@nestjs/common';
@Injectable({ scope: Scope.TRANSIENT })
export class UserByIdPipe implements PipeTransform<string> {
static COUNTER = 0;
constructor() {
UserByIdPipe.COUNTER++;
}
transform(value: string, metadata: ArgumentMetadata) {
return value;
}
}

View File

@@ -0,0 +1,13 @@
import { Inject, Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class UsersService {
static COUNTER = 0;
constructor(@Inject('META') private readonly meta) {
UsersService.COUNTER++;
}
findById(id: string) {
return { id };
}
}

View File

@@ -0,0 +1,22 @@
{
"compilerOptions": {
"module": "commonjs",
"declaration": false,
"noImplicitAny": false,
"removeComments": true,
"noLib": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es6",
"sourceMap": true,
"allowJs": true,
"outDir": "./dist"
},
"include": [
"src/**/*",
"e2e/**/*"
],
"exclude": [
"node_modules",
]
}

View File

@@ -0,0 +1,53 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {
"no-unused-expression": true
},
"rules": {
"eofline": false,
"quotemark": [
true,
"single"
],
"ordered-imports": [
false
],
"max-line-length": [
150
],
"member-ordering": [
false
],
"curly": false,
"interface-name": [
false
],
"array-type": [
false
],
"member-access": [
false
],
"no-empty-interface": false,
"no-empty": false,
"arrow-parens": false,
"object-literal-sort-keys": false,
"no-unused-expression": false,
"max-classes-per-file": [
false
],
"variable-name": [
false
],
"one-line": [
false
],
"one-variable-per-declaration": [
false
]
},
"rulesDirectory": []
}

View File

@@ -16,7 +16,7 @@
"reflect-metadata": "^0.1.12",
"rxjs": "^6.0.0",
"typeorm": "^0.1.16",
"typescript": "^2.8.0"
"typescript": "^3.1.0"
},
"devDependencies": {
"@types/node": "^7.0.41",

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';

View File

@@ -16,7 +16,7 @@
"class-validator": "^0.7.2",
"reflect-metadata": "^0.1.12",
"rxjs": "^6.0.0",
"typescript": "^2.8.0"
"typescript": "^3.1.0"
},
"devDependencies": {
"@types/node": "^7.0.41",

227
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "nestjs",
"version": "5.4.0",
"version": "5.4.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -111,20 +111,32 @@
}
},
"@nestjs/common": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@nestjs/common/-/common-5.1.0.tgz",
"integrity": "sha512-JAZFqdU+f4DRE4yOvpfWDtwgmCavyfE2Vu7mSwYsklU9TlBBE9XBygN2J38aQC83dmCJ1H889shd+hBIiVyEXA==",
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/@nestjs/common/-/common-5.5.0.tgz",
"integrity": "sha512-Ifh1D4ypsJYs/3YBIocU+X5yuAZSVKuCsz8kaKB4ZUO5WwJjh4/x6hlr4A+9XUMe8fPLtYXVohJoRUU5HbwyIA==",
"requires": {
"axios": "0.17.1",
"axios": "0.18.0",
"cli-color": "1.2.0",
"deprecate": "1.0.0",
"multer": "1.3.0"
"multer": "1.3.0",
"uuid": "3.3.2"
},
"dependencies": {
"axios": {
"version": "0.18.0",
"resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
"requires": {
"follow-redirects": "^1.3.0",
"is-buffer": "^1.1.5"
}
}
}
},
"@nestjs/core": {
"version": "5.3.15",
"resolved": "https://registry.npmjs.org/@nestjs/core/-/core-5.3.15.tgz",
"integrity": "sha512-pbF+e7JTBxiR+vu6VmrXsP9UQqBkQrH7o6HHQdovCP1Q2/NEBhpFvzMC3mWo0/4J11qTCN06vc6sWjstpX1fMg==",
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/@nestjs/core/-/core-5.5.0.tgz",
"integrity": "sha512-XPUjSJyex6KMdTUKK1oeD7ea9mNLcwlSEbcKV7OWaNHIVq/XJaFpbzjbmd+/U/ZZaO1IWhpisfLW9gr/O8eb4w==",
"requires": {
"@nuxtjs/opencollective": "0.1.0",
"body-parser": "1.18.3",
@@ -243,16 +255,16 @@
"integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4="
},
"mime-db": {
"version": "1.36.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
"integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw=="
"version": "1.37.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
"integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg=="
},
"mime-types": {
"version": "2.1.20",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
"integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
"version": "2.1.21",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
"integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
"requires": {
"mime-db": "~1.36.0"
"mime-db": "~1.37.0"
}
},
"proxy-addr": {
@@ -586,9 +598,9 @@
"dev": true
},
"@types/node": {
"version": "7.0.48",
"resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.48.tgz",
"integrity": "sha512-LLlXafM3BD52MH056tHxTXO8JFCnpJJQkdzIU3+m8ew+CXJY/5zIXgDNb4TK/QFvlI8QexLS5tL+sE0Qhegr1w=="
"version": "10.12.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.14.tgz",
"integrity": "sha512-0rVcFRhM93kRGAU88ASCjX9Y3FWDCh+33G5Z5evpKOea4xcpLqDGwmo64+DjgaSezTN5j9KdnUzvxhOw7fNciQ=="
},
"@types/pino": {
"version": "4.7.1",
@@ -1686,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": {
@@ -4972,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",
@@ -8467,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",
@@ -10463,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": {
@@ -13420,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": {
@@ -15419,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",
@@ -15467,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"
}
}
}
},
@@ -15568,9 +15574,9 @@
"integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ=="
},
"tslint": {
"version": "5.9.1",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.9.1.tgz",
"integrity": "sha1-ElX4ej/1frCw4fDmEKi0dIBGya4=",
"version": "5.11.0",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz",
"integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=",
"dev": true,
"requires": {
"babel-code-frame": "^6.22.0",
@@ -15584,7 +15590,7 @@
"resolve": "^1.3.2",
"semver": "^5.3.0",
"tslib": "^1.8.0",
"tsutils": "^2.12.1"
"tsutils": "^2.27.2"
},
"dependencies": {
"ansi-styles": {
@@ -15597,9 +15603,9 @@
}
},
"chalk": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz",
"integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==",
"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",
@@ -15608,31 +15614,17 @@
}
},
"commander": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
"integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
"dev": true
},
"esprima": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
"integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true
},
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -15640,34 +15632,25 @@
"dev": true
},
"js-yaml": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz",
"integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==",
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
"integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
"dev": true,
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"semver": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
"integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
"dev": true
},
"supports-color": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
@@ -15676,9 +15659,9 @@
}
},
"tsutils": {
"version": "2.26.1",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.26.1.tgz",
"integrity": "sha512-bnm9bcjOqOr1UljleL94wVCDlpa6KjfGaTkefeLch4GRafgDkROxPizbB/FxTEdI++5JqhxczRy/Qub0syNqZA==",
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
"dev": true,
"requires": {
"tslib": "^1.8.1"
@@ -15727,9 +15710,9 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"typescript": {
"version": "2.8.1",
"resolved": "http://registry.npmjs.org/typescript/-/typescript-2.8.1.tgz",
"integrity": "sha512-Ao/f6d/4EPLq0YwzsQz8iXflezpTkQzqAyenTiw4kCUGr1uPiFLC3+fZ+gMZz6eeI/qdRUqvC+HxIJzUAzEFdg==",
"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

@@ -5,30 +5,21 @@
"scripts": {
"coverage": "nyc report --reporter=text-lcov | coveralls",
"precommit": "lint-staged",
"test":
"nyc --require ts-node/register mocha packages/**/*.spec.ts --reporter spec --require 'node_modules/reflect-metadata/Reflect.js'",
"integration-test":
"mocha integration/**/*.spec.ts --reporter spec --require ts-node/register --require 'node_modules/reflect-metadata/Reflect.js'",
"lint":
"tslint -p tsconfig.json -c tslint.json \"packages/**/*.ts\" -e \"*.spec.ts\"",
"format":
"prettier **/**/*.ts --ignore-path ./.prettierignore --write && git status",
"test": "nyc --require ts-node/register mocha packages/**/*.spec.ts --reporter spec --require 'node_modules/reflect-metadata/Reflect.js'",
"integration-test": "mocha integration/**/*.spec.ts --reporter spec --require ts-node/register --require 'node_modules/reflect-metadata/Reflect.js'",
"lint": "tslint -p tsconfig.json -c tslint.json \"packages/**/*.ts\" -e \"*.spec.ts\"",
"format": "prettier **/**/*.ts --ignore-path ./.prettierignore --write && git status",
"clean": "gulp clean:bundle",
"build": "npm run clean && gulp build",
"prebuild:dev": "rm -rf node_modules/@nestjs",
"build:dev": "gulp build --dist node_modules/@nestjs && gulp move",
"postinstall": "opencollective",
"prerelease": "gulp copy-misc && gulp build --dist node_modules/@nestjs",
"publish":
"npm run prerelease && npm run build && ./node_modules/.bin/lerna publish --force-publish --exact -m \"chore(@nestjs) publish %s release\"",
"publish:rc":
"npm run prerelease && npm run build && ./node_modules/.bin/lerna publish --npm-tag=rc -m \"chore(@nestjs) publish %s release\"",
"publish:next":
"npm run prerelease && npm run build && ./node_modules/.bin/lerna publish --npm-tag=next --skip-git -m \"chore(@nestjs) publish %s release\"",
"publish:beta":
"npm run prerelease && npm run build && ./node_modules/.bin/lerna publish --npm-tag=beta -m \"chore(@nestjs) publish %s release\"",
"publish:test":
"npm run prerelease && npm run build && ./node_modules/.bin/lerna publish --force-publish --npm-tag=test --skip-git -m \"chore(@nestjs) publish %s release\""
"publish": "npm run prerelease && npm run build && ./node_modules/.bin/lerna publish --force-publish --exact -m \"chore(@nestjs) publish %s release\"",
"publish:rc": "npm run prerelease && npm run build && ./node_modules/.bin/lerna publish --npm-tag=rc -m \"chore(@nestjs) publish %s release\"",
"publish:next": "npm run prerelease && npm run build && ./node_modules/.bin/lerna publish --npm-tag=next --skip-git -m \"chore(@nestjs) publish %s release\"",
"publish:beta": "npm run prerelease && npm run build && ./node_modules/.bin/lerna publish --npm-tag=beta -m \"chore(@nestjs) publish %s release\"",
"publish:test": "npm run prerelease && npm run build && ./node_modules/.bin/lerna publish --force-publish --npm-tag=test --skip-git -m \"chore(@nestjs) publish %s release\""
},
"engines": {
"node": ">= 8.9.0"
@@ -41,8 +32,8 @@
"license": "MIT",
"dependencies": {
"@grpc/proto-loader": "^0.3.0",
"@nestjs/common": "5.1.0",
"@nestjs/core": "^5.3.10",
"@nestjs/common": "^5.5.0",
"@nestjs/core": "^5.5.0",
"@nestjs/microservices": "5.1.0",
"@nestjs/testing": "5.1.0",
"@nestjs/websockets": "5.1.0",
@@ -56,15 +47,16 @@
"cli-color": "^1.1.0",
"connect": "^3.6.6",
"cors": "^2.8.4",
"deprecate": "^1.0.0",
"engine.io-client": "^3.1.1",
"express": "^4.16.2",
"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",
@@ -92,7 +84,7 @@
"@types/express": "^4.0.39",
"@types/kafka-node": "^2.0.6",
"@types/mocha": "^2.2.38",
"@types/node": "^7.0.5",
"@types/node": "^10.12.14",
"@types/redis": "^0.12.36",
"@types/reflect-metadata": "0.0.5",
"@types/sinon": "^1.16.36",
@@ -124,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",
"tslint": "^5.9.1",
"typescript": "^2.8.1"
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"typescript": "^3.2.2"
},
"collective": {
"type": "opencollective",
@@ -141,16 +133,18 @@
}
},
"nyc": {
"include": ["packages/**/*.ts"],
"include": [
"packages/**/*.ts"
],
"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",
"packages/common/http/*.ts",
"packages/common/hooks/*.ts",
"packages/common/utils/load-package.util.ts",
"packages/microservices/exceptions/",
"packages/microservices/microservices-module.ts",
@@ -161,13 +155,23 @@
"packages/common/serializer/**/*",
"packages/common/services/logger.service.ts"
],
"extension": [".ts"],
"require": ["ts-node/register"],
"reporter": ["text-summary", "html"],
"extension": [
".ts"
],
"require": [
"ts-node/register"
],
"reporter": [
"text-summary",
"html"
],
"sourceMap": true,
"instrument": true
},
"lint-staged": {
"packages/**/*.{ts,json}": ["npm run format", "git add"]
"packages/**/*.{ts,json}": [
"npm run format",
"git add"
]
}
}

View File

@@ -1,6 +1,6 @@
(The MIT License)
Copyright (c) 2017 Kamil Myśliwiec <http://kamilmysliwiec.com>
Copyright (c) 2018 Kamil Myśliwiec <https://kamilmysliwiec.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -1,39 +1,50 @@
import { Observable, of } from 'rxjs';
import { tap } from 'rxjs/operators';
import { Inject, Injectable, Optional } from '../../decorators';
import { ExecutionContext, NestInterceptor } from '../../interfaces';
import {
CallHandler,
ExecutionContext,
HttpServer,
NestInterceptor,
} from '../../interfaces';
import { CACHE_KEY_METADATA, CACHE_MANAGER } from '../cache.constants';
const APPLICATION_REFERENCE_HOST = 'ApplicationReferenceHost';
const REFLECTOR = 'Reflector';
export interface ApplicationHost<T extends HttpServer = any> {
applicationRef: T;
}
@Injectable()
export class CacheInterceptor implements NestInterceptor {
@Optional()
@Inject(APPLICATION_REFERENCE_HOST)
protected readonly applicationRefHost: any;
protected readonly applicationRefHost: ApplicationHost;
constructor(
@Inject(CACHE_MANAGER) protected readonly cacheManager: any,
@Inject(REFLECTOR) protected readonly reflector,
@Inject(REFLECTOR) protected readonly reflector: any,
) {}
async intercept(
context: ExecutionContext,
call$: Observable<any>,
next: CallHandler,
): Promise<Observable<any>> {
const key = this.trackBy(context);
if (!key) {
return call$;
return next.handle();
}
try {
const value = await this.cacheManager.get(key);
if (value) {
return of(value);
}
return call$.pipe(tap(response => this.cacheManager.set(key, response)));
return next
.handle()
.pipe(tap(response => this.cacheManager.set(key, response)));
} catch {
return call$;
return next.handle();
}
}

View File

@@ -1,20 +1,19 @@
export const METADATA = {
MODULES: 'modules',
IMPORTS: 'imports',
COMPONENTS: 'components',
PROVIDERS: 'providers',
CONTROLLERS: 'controllers',
EXPORTS: 'exports',
};
export const SHARED_MODULE_METADATA = '__sharedModule__';
export const GLOBAL_MODULE_METADATA = '__globalModule__';
export const SHARED_MODULE_METADATA = '__module:shared__';
export const GLOBAL_MODULE_METADATA = '__module:global__';
export const PATH_METADATA = 'path';
export const PARAMTYPES_METADATA = 'design:paramtypes';
export const SELF_DECLARED_DEPS_METADATA = 'self:paramtypes';
export const OPTIONAL_DEPS_METADATA = 'optional:paramtypes';
export const PROPERTY_DEPS_METADATA = 'self:properties_metadata';
export const OPTIONAL_PROPERTY_DEPS_METADATA = 'optional:properties_metadata';
export const SCOPE_OPTIONS_METADATA = 'scope:options';
export const METHOD_METADATA = 'method';
export const ROUTE_ARGS_METADATA = '__routeArguments__';
@@ -26,7 +25,6 @@ export const GUARDS_METADATA = '__guards__';
export const RENDER_METADATA = '__renderTemplate__';
export const INTERCEPTORS_METADATA = '__interceptors__';
export const HTTP_CODE_METADATA = '__httpCode__';
export const GATEWAY_MIDDLEWARES = '__gatewayMiddleware';
export const MODULE_PATH = '__module_path__';
export const HEADERS_METADATA = '__headers__';
export const REDIRECT_METADATA = '__redirect__';

View File

@@ -1,10 +1,14 @@
/**
* Binds parameters decorators to the particular method
* Binds parameter decorators to the method
* Useful when the language doesn't provide a 'Parameter Decorators' feature (vanilla JavaScript)
* @param {} ...decorators
*/
export function Bind(...decorators: any[]) {
return (target: object, key, descriptor) => {
export function Bind(...decorators: any[]): MethodDecorator {
return <T>(
target: object,
key: string | symbol,
descriptor: TypedPropertyDescriptor<T>,
) => {
decorators.forEach((fn, index) => fn(target, key, index));
return descriptor;
};

View File

@@ -2,7 +2,7 @@ import { FILTER_CATCH_EXCEPTIONS } from '../../constants';
import { Type } from '../../interfaces';
/**
* Defines the Exceptions Filter. Takes set of exception types as an argument which has to be caught by this Filter.
* Defines an exception filter. Takes set of exception types as arguments which have to be caught by this filter.
* The class should implement the `ExceptionFilter` interface.
*/
export function Catch(...exceptions: Type<any>[]): ClassDecorator {

View File

@@ -1,74 +0,0 @@
import * as deprecate from 'deprecate';
import * as uuid from 'uuid/v4';
/**
* Defines the injectable class. This class can inject dependencies through constructor.
* Those dependencies have to belong to the same module.
*/
export function Injectable(): ClassDecorator {
return (target: object) => {};
}
/**
* @deprecated
* Defines the Component. The component can inject dependencies through constructor.
* Those dependencies have to belong to the same module.
*/
export function Component(): ClassDecorator {
deprecate(
'The @Component() decorator is deprecated and will be removed within next major release. Use @Injectable() instead.',
);
return (target: object) => {};
}
/**
* @deprecated
* Defines the Pipe. The Pipe should implement the `PipeTransform` interface.
*/
export function Pipe(): ClassDecorator {
deprecate(
'The @Pipe() decorator is deprecated and will be removed within next major release. Use @Injectable() instead.',
);
return (target: object) => {};
}
/**
* @deprecated
* Defines the Guard. The Guard should implement the `CanActivate` interface.
*/
export function Guard(): ClassDecorator {
deprecate(
'The @Guard() decorator is deprecated and will be removed within next major release. Use @Injectable() instead.',
);
return (target: object) => {};
}
/**
* @deprecated
* Defines the Middleware. The Middleware should implement the `NestMiddleware` interface.
*/
export function Middleware(): ClassDecorator {
deprecate(
'The @Middleware() decorator is deprecated and will be removed within next major release. Use @Injectable() instead.',
);
return (target: object) => {};
}
/**
* @deprecated
* Defines the Interceptor. The Interceptor should implement `HttpInterceptor`, `RpcInterceptor` or `WsInterceptor` interface.
*/
export function Interceptor(): ClassDecorator {
deprecate(
'The @Interceptor() decorator is deprecated and will be removed within next major release. Use @Injectable() instead.',
);
return (target: object) => {};
}
export function mixin(mixinClass) {
Object.defineProperty(mixinClass, 'name', {
value: uuid(),
});
Injectable()(mixinClass);
return mixinClass;
}

View File

@@ -1,8 +1,8 @@
import { isUndefined } from '../../utils/shared.utils';
import { PATH_METADATA } from '../../constants';
import { isUndefined } from '../../utils/shared.utils';
/**
* Defines the Controller. The controller can inject dependencies through constructor.
* Defines the controller. Controller can inject dependencies through constructor.
* Those dependencies have to belong to the same module.
*/
export function Controller(prefix?: string): ClassDecorator {

View File

@@ -1,8 +1,10 @@
import { PARAMTYPES_METADATA } from '../../constants';
export function flatten(arr: any[]) {
export function flatten<T extends any[] = any, R extends any[] = any>(
arr: T,
): R {
const flat = [].concat(...arr);
return flat.some(Array.isArray) ? flatten(flat) : flat;
return (flat.some(Array.isArray) ? flatten(flat) : flat) as R;
}
export const Dependencies = (...dependencies: any[]): ClassDecorator => {

View File

@@ -5,9 +5,12 @@ import { isFunction } from '../../utils/shared.utils';
import { validateEach } from '../../utils/validate-each.util';
const defineFiltersMetadata = (...filters: (Function | ExceptionFilter)[]) => {
return (target: any, key?, descriptor?) => {
const isFilterValid = filter =>
filter && (isFunction(filter) || isFunction(filter.catch));
return (target: any, key?: string, descriptor?: any) => {
const isFilterValid = <T extends Function | Record<string, any>>(
filter: T,
) =>
filter &&
(isFunction(filter) || isFunction((filter as Record<string, any>).catch));
if (descriptor) {
validateEach(
@@ -31,12 +34,12 @@ const defineFiltersMetadata = (...filters: (Function | ExceptionFilter)[]) => {
};
/**
* Setups exception filters to the chosen context.
* Bounds exception filters to the chosen context.
* When the `@UseFilters()` is used on the controller level:
* - Exception Filter will be set up to every handler (every method)
*
* When the `@UseFilters()` is used on the handle level:
* - Exception Filter will be set up only to specified method
* - Exception Filter will be set up only to the specified method
*
* @param {ExceptionFilter[]} ...filters
*/

View File

@@ -1,10 +1,10 @@
export * from './bind.decorator';
export * from './catch.decorator';
export * from './component.decorator';
export * from './controller.decorator';
export * from './dependencies.decorator';
export * from './exception-filters.decorator';
export * from './inject.decorator';
export * from './injectable.decorator';
export * from './optional.decorator';
export * from './reflect-metadata.decorator';
export * from './use-guards.decorator';

View File

@@ -6,7 +6,7 @@ import { isFunction, isUndefined } from '../../utils/shared.utils';
/**
* Injects provider which has to be available in the current injector (module) scope.
* Providers are recognized by types or tokens.
* Providers are recognized by either types or tokens.
*/
export function Inject<T = any>(token?: T) {
return (target: Object, key: string | symbol, index?: number) => {

View File

@@ -0,0 +1,24 @@
import * as uuid from 'uuid/v4';
import { ScopeOptions } from '../../interfaces/scope-options.interface';
import { SCOPE_OPTIONS_METADATA } from './../../constants';
import { Type } from './../../interfaces/type.interface';
export interface InjectableOptions extends ScopeOptions {}
/**
* Defines the injectable class. This class can inject dependencies through constructor.
* Those dependencies have to belong to the same module.
*/
export function Injectable(options?: InjectableOptions): ClassDecorator {
return (target: object) => {
Reflect.defineMetadata(SCOPE_OPTIONS_METADATA, options, target);
};
}
export function mixin(mixinClass: Type<any>) {
Object.defineProperty(mixinClass, 'name', {
value: uuid(),
});
Injectable()(mixinClass);
return mixinClass;
}

View File

@@ -2,11 +2,10 @@
* Assigns the metadata to the class/function under specified `key`.
* This metadata can be reflected using `Reflector` class.
*/
export const ReflectMetadata = <K = any, V = any>(metadataKey: K, metadataValue: V) => (
target: object,
key?,
descriptor?,
) => {
export const ReflectMetadata = <K = any, V = any>(
metadataKey: K,
metadataValue: V,
) => (target: object, key?: any, descriptor?: any) => {
if (descriptor) {
Reflect.defineMetadata(metadataKey, metadataValue, descriptor.value);
return descriptor;

View File

@@ -1,8 +1,8 @@
import { GUARDS_METADATA } from '../../constants';
import { extendArrayMetadata } from '../../utils/extend-metadata.util';
import { validateEach } from '../../utils/validate-each.util';
import { isFunction } from '../../utils/shared.utils';
import { CanActivate } from '../../interfaces';
import { extendArrayMetadata } from '../../utils/extend-metadata.util';
import { isFunction } from '../../utils/shared.utils';
import { validateEach } from '../../utils/validate-each.util';
/**
* Binds guards to the particular context.
@@ -10,14 +10,16 @@ import { CanActivate } from '../../interfaces';
* - Guard will be register to each handler (every method)
*
* When the `@UseGuards()` is used on the handler level:
* - Guard will be registered only to specified method
* - Guard will be registered only to the specified method
*
* @param {} ...guards
*/
export function UseGuards(...guards: (CanActivate | Function)[]) {
return (target: any, key?, descriptor?) => {
const isValidGuard = guard =>
guard && (isFunction(guard) || isFunction(guard.canActivate));
return (target: any, key?: string, descriptor?: any) => {
const isValidGuard = <T extends Function | Record<string, any>>(guard: T) =>
guard &&
(isFunction(guard) ||
isFunction((guard as Record<string, any>).canActivate));
if (descriptor) {
validateEach(

View File

@@ -10,17 +10,20 @@ import { validateEach } from '../../utils/validate-each.util';
* - Interceptor will be register to each handler (every method)
*
* When the `@UseInterceptors()` is used on the handle level:
* - Interceptor will be registered only to specified method
* - Interceptor will be registered only to the specified method
*
* @param {} ...interceptors
*/
export function UseInterceptors(
...interceptors: (NestInterceptor | Function)[]
) {
return (target: any, key?, descriptor?) => {
const isValidInterceptor = interceptor =>
return (target: any, key?: string, descriptor?: any) => {
const isValidInterceptor = <T extends Function | Record<string, any>>(
interceptor: T,
) =>
interceptor &&
(isFunction(interceptor) || isFunction(interceptor.intercept));
(isFunction(interceptor) ||
isFunction((interceptor as Record<string, any>).intercept));
if (descriptor) {
validateEach(

View File

@@ -1,8 +1,8 @@
import { PipeTransform } from '../../interfaces/index';
import { PIPES_METADATA } from '../../constants';
import { PipeTransform } from '../../interfaces/index';
import { extendArrayMetadata } from '../../utils/extend-metadata.util';
import { validateEach } from '../../utils/validate-each.util';
import { isFunction } from '../../utils/shared.utils';
import { validateEach } from '../../utils/validate-each.util';
/**
* Binds pipes to the particular context.
@@ -10,14 +10,16 @@ import { isFunction } from '../../utils/shared.utils';
* - Pipe will be register to each handler (every method)
*
* When the `@UsePipes()` is used on the handle level:
* - Pipe will be registered only to specified method
* - Pipe will be registered only to the specified method
*
* @param {PipeTransform[]} ...pipes
*/
export function UsePipes(...pipes: (PipeTransform | Function)[]) {
return (target: any, key?, descriptor?) => {
const isPipeValid = pipe =>
pipe && (isFunction(pipe) || isFunction(pipe.transform));
return (target: any, key?: string, descriptor?: any) => {
const isPipeValid = <T extends Function | Record<string, any>>(pipe: T) =>
pipe &&
(isFunction(pipe) || isFunction((pipe as Record<string, any>).transform));
if (descriptor) {
extendArrayMetadata(PIPES_METADATA, pipes, descriptor.value);
return descriptor;

View File

@@ -1,4 +1,3 @@
import * as deprecate from 'deprecate';
import * as uuid from 'uuid/v4';
import {
CUSTOM_ROUTE_AGRS_METADATA,
@@ -47,7 +46,7 @@ export function createParamDecorator(
const args =
Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
const isPipe = pipe =>
const isPipe = (pipe: any) =>
pipe &&
((isFunction(pipe) && pipe.prototype) || isFunction(pipe.transform));
@@ -71,20 +70,3 @@ export function createParamDecorator(
enhancers.forEach(fn => fn(target, key, index));
};
}
/**
* Defines HTTP route param decorator
* @deprecated
* @param factory
*/
export function createRouteParamDecorator(
factory: CustomParamFactory,
): (
data?: any,
...pipes: (Type<PipeTransform> | PipeTransform)[]
) => ParameterDecorator {
deprecate(
'The "createRouteParamDecorator" function is deprecated and will be removed within next major release. Use "createParamDecorator" instead.',
);
return createParamDecorator(factory);
}

View File

@@ -41,7 +41,7 @@ const createRouteParamDecorator = (paramtype: RouteParamtypes) => {
};
const createPipesRouteParamDecorator = (paramtype: RouteParamtypes) => (
data?,
data?: any,
...pipes: (Type<PipeTransform> | PipeTransform)[]
): ParameterDecorator => (target, key, index) => {
const args =
@@ -80,48 +80,54 @@ export const Headers: (
property?: string,
) => ParameterDecorator = createRouteParamDecorator(RouteParamtypes.HEADERS);
export function Query();
export function Query(...pipes: (Type<PipeTransform> | PipeTransform)[]);
export function Query(): ParameterDecorator;
export function Query(
...pipes: (Type<PipeTransform> | PipeTransform)[]
): ParameterDecorator;
export function Query(
property: string,
...pipes: (Type<PipeTransform> | PipeTransform)[]
);
): ParameterDecorator;
export function Query(
property?: string | (Type<PipeTransform> | PipeTransform),
...pipes: (Type<PipeTransform> | PipeTransform)[]
) {
): ParameterDecorator {
return createPipesRouteParamDecorator(RouteParamtypes.QUERY)(
property,
...pipes,
);
}
export function Body();
export function Body(...pipes: (Type<PipeTransform> | PipeTransform)[]);
export function Body(): ParameterDecorator;
export function Body(
...pipes: (Type<PipeTransform> | PipeTransform)[]
): ParameterDecorator;
export function Body(
property: string,
...pipes: (Type<PipeTransform> | PipeTransform)[]
);
): ParameterDecorator;
export function Body(
property?: string | (Type<PipeTransform> | PipeTransform),
...pipes: (Type<PipeTransform> | PipeTransform)[]
) {
): ParameterDecorator {
return createPipesRouteParamDecorator(RouteParamtypes.BODY)(
property,
...pipes,
);
}
export function Param();
export function Param(...pipes: (Type<PipeTransform> | PipeTransform)[]);
export function Param(): ParameterDecorator;
export function Param(
...pipes: (Type<PipeTransform> | PipeTransform)[]
): ParameterDecorator;
export function Param(
property: string,
...pipes: (Type<PipeTransform> | PipeTransform)[]
);
): ParameterDecorator;
export function Param(
property?: string | (Type<PipeTransform> | PipeTransform),
...pipes: (Type<PipeTransform> | PipeTransform)[]
) {
): ParameterDecorator {
return createPipesRouteParamDecorator(RouteParamtypes.PARAM)(
property,
...pipes,

View File

@@ -1,2 +1,4 @@
export const InvalidModuleConfigMessage = (property: string) =>
`Invalid property '${property}' in @Module() decorator.`;
export const INVALID_MODULE_CONFIG_MESSAGE = (
text: TemplateStringsArray,
property: string,
) => `Invalid property '${property}' in the @Module() decorator.`;

View File

@@ -1,7 +1,7 @@
import { InvalidModuleConfigMessage } from './constants';
import { INVALID_MODULE_CONFIG_MESSAGE } from './constants';
export class InvalidModuleConfigException extends Error {
constructor(property: string) {
super(InvalidModuleConfigMessage(property));
super(INVALID_MODULE_CONFIG_MESSAGE`${property}`);
}
}

View File

@@ -1,4 +1,5 @@
import { GLOBAL_MODULE_METADATA } from '../../constants';
/**
* Makes the module global-scoped.
* Once imported will be available for all existing modules.

View File

@@ -1,20 +1,19 @@
import * as deprecate from 'deprecate';
import { METADATA as metadataConstants } from '../../constants';
import { ModuleMetadata } from '../../interfaces/modules/module-metadata.interface';
import { InvalidModuleConfigException } from './exceptions/invalid-module-config.exception';
const metadataKeys = [
metadataConstants.MODULES,
metadataConstants.IMPORTS,
metadataConstants.EXPORTS,
metadataConstants.COMPONENTS,
metadataConstants.CONTROLLERS,
metadataConstants.PROVIDERS,
];
const validateKeys = (keys: string[]) => {
const isKeyInvalid = key => metadataKeys.findIndex(k => k === key) < 0;
const validateKey = key => {
const isKeyInvalid = (key: string) =>
metadataKeys.findIndex(k => k === key) < 0;
const validateKey = (key: string) => {
if (!isKeyInvalid(key)) {
return;
}
@@ -29,41 +28,17 @@ const validateKeys = (keys: string[]) => {
* - `controllers` - the list of controllers (e.g. HTTP controllers)
* - `providers` - the list of providers that belong to this module. They can be injected between themselves.
* - `exports` - the set of components, which should be available for modules, which imports this module
* - `components` - @deprecated the list of components that belong to this module. They can be injected between themselves.
* @param options {ModuleMetadata} Module metadata
*/
export function Module(metadata: ModuleMetadata): ClassDecorator {
const propsKeys = Object.keys(metadata);
validateKeys(propsKeys);
showDeprecatedWarnings(metadata);
overrideModuleMetadata(metadata);
return (target: object) => {
for (const property in metadata) {
if (metadata.hasOwnProperty(property)) {
Reflect.defineMetadata(property, metadata[property], target);
Reflect.defineMetadata(property, (metadata as any)[property], target);
}
}
};
}
function overrideModuleMetadata(moduleMetadata: ModuleMetadata) {
moduleMetadata.modules = moduleMetadata.imports
? moduleMetadata.imports
: moduleMetadata.modules;
moduleMetadata.components = moduleMetadata.providers
? moduleMetadata.providers
: moduleMetadata.components;
}
function showDeprecatedWarnings(moduleMetadata: ModuleMetadata) {
const MODULES_DEPRECATED_WARNING =
'The "modules" key in the @Module() decorator is deprecated and will be removed within next major release. Use the "imports" key instead.';
const COMPONENTS_DEPRECATED_WARNING =
'The "components" key in the @Module() decorator is deprecated and will be removed within next major release. Use the "providers" key instead.';
moduleMetadata.modules && deprecate(MODULES_DEPRECATED_WARNING);
moduleMetadata.components && deprecate(COMPONENTS_DEPRECATED_WARNING);
}

View File

@@ -1,4 +1,5 @@
import { SHARED_MODULE_METADATA } from '../../constants';
/**
* Makes the module single-scoped (not singleton).
* In this case, Nest will always create a new instance of this particular module when it's imported by another one.
@@ -7,7 +8,7 @@ export function SingleScope(): ClassDecorator {
return (target: any) => {
const Metatype = target as FunctionConstructor;
const Type = class extends Metatype {
constructor(...args) {
constructor(...args: any[]) {
super(...args);
}
};

View File

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

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