mirror of
https://github.com/nestjs/nest.git
synced 2026-02-24 00:02:56 +00:00
Compare commits
2 Commits
v10.0.4
...
fix/fastif
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5612e0197 | ||
|
|
6c54448bf7 |
@@ -30,7 +30,7 @@ jobs:
|
||||
build:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:16.20
|
||||
- image: cimg/node:16.19
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
test_node_16:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:16.20
|
||||
- image: cimg/node:16.19
|
||||
steps:
|
||||
- checkout
|
||||
- *restore-cache
|
||||
@@ -70,12 +70,12 @@ jobs:
|
||||
test_node_18:
|
||||
<<: *unit-tests-template
|
||||
docker:
|
||||
- image: cimg/node:18.16
|
||||
- image: cimg/node:18.14
|
||||
|
||||
test_node_19:
|
||||
<<: *unit-tests-template
|
||||
docker:
|
||||
- image: cimg/node:19.9
|
||||
- image: cimg/node:19.8
|
||||
|
||||
lint:
|
||||
working_directory: ~/nest
|
||||
@@ -130,7 +130,7 @@ jobs:
|
||||
codechecks_benchmarks:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:16.20
|
||||
- image: cimg/node:16.19
|
||||
steps:
|
||||
- checkout
|
||||
- *restore-cache
|
||||
@@ -146,7 +146,7 @@ jobs:
|
||||
samples:
|
||||
working_directory: ~/nest
|
||||
docker:
|
||||
- image: cimg/node:16.20
|
||||
- image: cimg/node:16.19
|
||||
environment:
|
||||
- DISABLE_OPENCOLLECTIVE: true
|
||||
steps:
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/Bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/Bug_report.yml
vendored
@@ -6,7 +6,7 @@ body:
|
||||
attributes:
|
||||
value: |
|
||||
## :warning: We use GitHub Issues to track bug reports, feature requests and regressions
|
||||
|
||||
|
||||
If you are not sure that your issue is a bug, you could:
|
||||
|
||||
- read the [FAQ's common errors](https://docs.nestjs.com/faq/common-errors) page
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/Feature_request.yml
vendored
2
.github/ISSUE_TEMPLATE/Feature_request.yml
vendored
@@ -6,7 +6,7 @@ body:
|
||||
attributes:
|
||||
value: |
|
||||
## :warning: We use GitHub Issues to track bug reports, feature requests and regressions
|
||||
|
||||
|
||||
If you are not sure that your issue is a bug, you could:
|
||||
|
||||
- read the [FAQ's common errors](https://docs.nestjs.com/faq/common-errors) page
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/Regression.yml
vendored
2
.github/ISSUE_TEMPLATE/Regression.yml
vendored
@@ -6,7 +6,7 @@ body:
|
||||
attributes:
|
||||
value: |
|
||||
## :warning: We use GitHub Issues to track bug reports, feature requests and regressions
|
||||
|
||||
|
||||
If you are not sure that your issue is a bug, you could:
|
||||
|
||||
- read the [FAQ's common errors](https://docs.nestjs.com/faq/common-errors) page
|
||||
|
||||
@@ -25,7 +25,7 @@ services:
|
||||
- "9001:9001"
|
||||
restart: always
|
||||
mysql:
|
||||
image: mysql:8.0.33
|
||||
image: mysql:8.0.32
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: test
|
||||
@@ -50,7 +50,7 @@ services:
|
||||
zookeeper:
|
||||
container_name: test-zookeeper
|
||||
hostname: zookeeper
|
||||
image: confluentinc/cp-zookeeper:7.4.0
|
||||
image: confluentinc/cp-zookeeper:7.3.2
|
||||
ports:
|
||||
- "2181:2181"
|
||||
environment:
|
||||
@@ -59,7 +59,7 @@ services:
|
||||
kafka:
|
||||
container_name: test-kafka
|
||||
hostname: kafka
|
||||
image: confluentinc/cp-kafka:7.4.0
|
||||
image: confluentinc/cp-kafka:7.3.2
|
||||
depends_on:
|
||||
- zookeeper
|
||||
ports:
|
||||
|
||||
@@ -192,7 +192,7 @@ describe('Middleware (FastifyAdapter)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('should execute middleware only once for given routes', () => {
|
||||
describe.only('should execute middleware only once for given routes', () => {
|
||||
class Middleware implements NestMiddleware {
|
||||
use(request: any, reply: any, next: () => void) {
|
||||
if (request.middlewareExecutionCount === undefined) {
|
||||
|
||||
@@ -4,7 +4,9 @@ import { CatsModule } from './cats/cats.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
MongooseModule.forRoot('mongodb://localhost:27017/test'),
|
||||
MongooseModule.forRoot('mongodb://localhost:27017/test', {
|
||||
useNewUrlParser: true,
|
||||
}),
|
||||
CatsModule,
|
||||
],
|
||||
})
|
||||
|
||||
@@ -10,6 +10,7 @@ class ConfigService implements MongooseOptionsFactory {
|
||||
createMongooseOptions(): MongooseModuleOptions {
|
||||
return {
|
||||
uri: 'mongodb://localhost:27017/test',
|
||||
useNewUrlParser: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ class ConfigService implements MongooseOptionsFactory {
|
||||
createMongooseOptions(): MongooseModuleOptions {
|
||||
return {
|
||||
uri: 'mongodb://localhost:27017/test',
|
||||
useNewUrlParser: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { CatsModule } from './cats/cats.module';
|
||||
imports: [
|
||||
MongooseModule.forRootAsync({
|
||||
useFactory: () => ({
|
||||
useNewUrlParser: true,
|
||||
uri: 'mongodb://localhost:27017/test',
|
||||
}),
|
||||
}),
|
||||
|
||||
@@ -77,7 +77,7 @@ describe('Fastify FileSend', () => {
|
||||
expect(headers['content-disposition']).to.equal(
|
||||
'attachment; filename="Readme.md"',
|
||||
);
|
||||
expect(headers['content-length']).to.equal(`${readme.byteLength}`);
|
||||
expect(headers['content-length']).to.equal(readme.byteLength);
|
||||
expect(payload).to.equal(readmeString);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"type": "mysql",
|
||||
"host": "127.0.0.1",
|
||||
"host": "localhost",
|
||||
"port": 3306,
|
||||
"username": "root",
|
||||
"password": "root",
|
||||
|
||||
@@ -7,7 +7,7 @@ import { PhotoModule } from './photo/photo.module';
|
||||
imports: [
|
||||
TypeOrmModule.forRoot({
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
host: 'localhost',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: 'root',
|
||||
|
||||
@@ -11,7 +11,7 @@ class ConfigService implements TypeOrmOptionsFactory {
|
||||
createTypeOrmOptions(): TypeOrmModuleOptions {
|
||||
return {
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
host: 'localhost',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: 'root',
|
||||
|
||||
@@ -11,7 +11,7 @@ class ConfigService implements TypeOrmOptionsFactory {
|
||||
createTypeOrmOptions(): TypeOrmModuleOptions {
|
||||
return {
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
host: 'localhost',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: 'root',
|
||||
|
||||
@@ -8,7 +8,7 @@ import { PhotoModule } from './photo/photo.module';
|
||||
TypeOrmModule.forRootAsync({
|
||||
useFactory: () => ({
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
host: 'localhost',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: 'root',
|
||||
|
||||
@@ -11,7 +11,7 @@ export class DatabaseModule {
|
||||
imports: [
|
||||
TypeOrmModule.forRoot({
|
||||
type: 'mysql',
|
||||
host: '127.0.0.1',
|
||||
host: 'localhost',
|
||||
port: 3306,
|
||||
username: 'root',
|
||||
password: 'root',
|
||||
|
||||
@@ -418,67 +418,4 @@ describe('URI Versioning', () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
// ======================================================================== //
|
||||
describe('with middleware applied', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
app.enableVersioning({
|
||||
type: VersioningType.URI,
|
||||
defaultVersion: '1',
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
describe('GET /middleware', () => {
|
||||
it('should return "Hello from middleware function!"', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/middleware')
|
||||
.expect(200)
|
||||
.expect('Hello from middleware function!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /middleware/override', () => {
|
||||
it('should return "Hello from middleware function!"', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/middleware/override')
|
||||
.expect(200)
|
||||
.expect('Hello from middleware function!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /middleware/multiple', () => {
|
||||
it('should return "Hello from middleware function!" (v1)', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/middleware/multiple')
|
||||
.expect(200)
|
||||
.expect('Hello from middleware function!');
|
||||
});
|
||||
|
||||
it('should return "Hello from middleware function!" (v2)', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/middleware/multiple')
|
||||
.expect(200)
|
||||
.expect('Hello from middleware function!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /middleware/neutral', () => {
|
||||
it('should return "Hello from middleware function!"', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/middleware/neutral')
|
||||
.expect(200)
|
||||
.expect('Hello from middleware function!');
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import { MiddlewareConsumer, Module } from '@nestjs/common';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AppV1Controller } from './app-v1.controller';
|
||||
import { AppV2Controller } from './app-v2.controller';
|
||||
import { MiddlewareController } from './middleware.controller';
|
||||
import { MultipleMiddlewareVersionController } from './multiple-middleware.controller';
|
||||
import { MultipleVersionController } from './multiple.controller';
|
||||
import { VersionNeutralMiddlewareController } from './neutral-middleware.controller';
|
||||
import { VersionNeutralController } from './neutral.controller';
|
||||
import { NoVersioningController } from './no-versioning.controller';
|
||||
import { OverridePartialController } from './override-partial.controller';
|
||||
import { VersionNeutralController } from './neutral.controller';
|
||||
import { OverrideController } from './override.controller';
|
||||
import { OverridePartialController } from './override-partial.controller';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
@@ -20,19 +17,6 @@ import { OverrideController } from './override.controller';
|
||||
VersionNeutralController,
|
||||
OverrideController,
|
||||
OverridePartialController,
|
||||
MiddlewareController,
|
||||
MultipleMiddlewareVersionController,
|
||||
VersionNeutralMiddlewareController,
|
||||
],
|
||||
})
|
||||
export class AppModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply((req, res) => res.end('Hello from middleware function!'))
|
||||
.forRoutes(
|
||||
MiddlewareController,
|
||||
MultipleMiddlewareVersionController,
|
||||
VersionNeutralMiddlewareController,
|
||||
);
|
||||
}
|
||||
}
|
||||
export class AppModule {}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Controller, Get, Version } from '@nestjs/common';
|
||||
|
||||
@Controller({
|
||||
path: 'middleware',
|
||||
version: '1',
|
||||
})
|
||||
export class MiddlewareController {
|
||||
@Get('/')
|
||||
hello() {
|
||||
return 'Hello from "MiddlewareController"!';
|
||||
}
|
||||
|
||||
@Version('2')
|
||||
@Get('/override')
|
||||
hellov2() {
|
||||
return 'Hello from "MiddlewareController"!';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
|
||||
@Controller({
|
||||
version: ['1', '2'],
|
||||
path: 'middleware',
|
||||
})
|
||||
export class MultipleMiddlewareVersionController {
|
||||
@Get('/multiple')
|
||||
multiple() {
|
||||
return 'Multiple Versions 1 or 2';
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { Controller, Get, VERSION_NEUTRAL } from '@nestjs/common';
|
||||
|
||||
@Controller({
|
||||
path: 'middleware',
|
||||
version: VERSION_NEUTRAL,
|
||||
})
|
||||
export class VersionNeutralMiddlewareController {
|
||||
@Get('/neutral')
|
||||
neutral() {
|
||||
return 'Neutral';
|
||||
}
|
||||
}
|
||||
@@ -66,21 +66,5 @@ describe('WebSocketGateway', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it(`should be able to get the pattern in an interceptor`, async () => {
|
||||
app = await createNestApp(ApplicationGateway);
|
||||
await app.listen(3000);
|
||||
|
||||
ws = io('http://localhost:8080');
|
||||
ws.emit('getClient', {
|
||||
test: 'test',
|
||||
});
|
||||
await new Promise<void>(resolve =>
|
||||
ws.on('popClient', data => {
|
||||
expect(data.path).to.be.eql('getClient');
|
||||
resolve();
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => app.close());
|
||||
});
|
||||
|
||||
@@ -194,30 +194,6 @@ describe('WebSocketGateway (WsAdapter)', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should let the execution context have a getPattern() method on getClient()', async () => {
|
||||
app = await createNestApp(ApplicationGateway);
|
||||
await app.listen(3000);
|
||||
|
||||
ws = new WebSocket('ws://localhost:8080');
|
||||
await new Promise(resolve => ws.on('open', resolve));
|
||||
|
||||
ws.send(
|
||||
JSON.stringify({
|
||||
event: 'getClient',
|
||||
data: {
|
||||
test: 'test',
|
||||
},
|
||||
}),
|
||||
);
|
||||
await new Promise<void>(resolve =>
|
||||
ws.on('message', data => {
|
||||
expect(JSON.parse(data).data.path).to.be.eql('getClient');
|
||||
ws.close();
|
||||
resolve();
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { UseInterceptors } from '@nestjs/common';
|
||||
import {
|
||||
MessageBody,
|
||||
SubscribeMessage,
|
||||
WebSocketGateway,
|
||||
} from '@nestjs/websockets';
|
||||
import { RequestInterceptor } from './request.interceptor';
|
||||
|
||||
@WebSocketGateway(8080)
|
||||
export class ApplicationGateway {
|
||||
@@ -15,13 +13,4 @@ export class ApplicationGateway {
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
@UseInterceptors(RequestInterceptor)
|
||||
@SubscribeMessage('getClient')
|
||||
getPathCalled(client, data) {
|
||||
return {
|
||||
event: 'popClient',
|
||||
data: { ...data, path: client.pattern },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import { CallHandler, ExecutionContext, Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class RequestInterceptor {
|
||||
intercept(context: ExecutionContext, next: CallHandler) {
|
||||
const client = context.switchToWs().getClient();
|
||||
const pattern = context.switchToWs().getPattern();
|
||||
client.pattern = pattern;
|
||||
return next.handle();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
import { UseInterceptors } from '@nestjs/common';
|
||||
import { SubscribeMessage, WebSocketGateway } from '@nestjs/websockets';
|
||||
import { RequestInterceptor } from './request.interceptor';
|
||||
|
||||
@WebSocketGateway()
|
||||
export class ServerGateway {
|
||||
@@ -11,13 +9,4 @@ export class ServerGateway {
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
@UseInterceptors(RequestInterceptor)
|
||||
@SubscribeMessage('getClient')
|
||||
getPathCalled(client, data) {
|
||||
return {
|
||||
event: 'popClient',
|
||||
data: { ...data, path: client.pattern },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "10.0.4"
|
||||
"version": "9.4.2"
|
||||
}
|
||||
|
||||
37383
package-lock.json
generated
37383
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
78
package.json
78
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/core",
|
||||
"version": "10.0.0",
|
||||
"version": "9.4.0",
|
||||
"description": "Modern, fast, powerful node.js web framework",
|
||||
"homepage": "https://nestjs.com",
|
||||
"repository": {
|
||||
@@ -25,7 +25,7 @@
|
||||
"move:node_modules": "gulp move:node_modules",
|
||||
"build:samples": "gulp install:samples && npm run build && npm run move:samples && gulp build:samples && gulp test:samples && gulp test:e2e:samples",
|
||||
"codechecks:benchmarks": "codechecks ./tools/benchmarks/check-benchmarks.ts",
|
||||
"coverage": "nyc report --reporter=text-lcov | coveralls -v",
|
||||
"coverage": "nyc report --reporter=text-lcov | coveralls",
|
||||
"format": "prettier \"**/*.ts\" \"packages/**/*.json\" --ignore-path ./.prettierignore --write && git status",
|
||||
"postinstall": "opencollective",
|
||||
"test": "mocha packages/**/*.spec.ts",
|
||||
@@ -72,67 +72,67 @@
|
||||
"path-to-regexp": "3.2.0",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"rxjs": "7.8.1",
|
||||
"socket.io": "4.7.0",
|
||||
"tslib": "2.6.0",
|
||||
"socket.io": "4.6.1",
|
||||
"tslib": "2.5.2",
|
||||
"uid": "2.0.2",
|
||||
"uuid": "9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@apollo/server": "4.7.5",
|
||||
"@apollo/server": "4.7.1",
|
||||
"@codechecks/client": "0.1.12",
|
||||
"@commitlint/cli": "17.6.6",
|
||||
"@commitlint/config-angular": "17.6.6",
|
||||
"@fastify/cors": "8.3.0",
|
||||
"@commitlint/cli": "17.6.3",
|
||||
"@commitlint/config-angular": "17.6.3",
|
||||
"@fastify/cors": "8.2.1",
|
||||
"@fastify/formbody": "7.4.0",
|
||||
"@fastify/middie": "8.3.0",
|
||||
"@fastify/multipart": "7.7.0",
|
||||
"@fastify/static": "6.10.2",
|
||||
"@fastify/multipart": "7.6.0",
|
||||
"@fastify/static": "6.10.1",
|
||||
"@fastify/view": "7.4.1",
|
||||
"@grpc/grpc-js": "1.8.17",
|
||||
"@grpc/grpc-js": "1.8.14",
|
||||
"@grpc/proto-loader": "0.7.7",
|
||||
"@nestjs/apollo": "12.0.4",
|
||||
"@nestjs/graphql": "12.0.3",
|
||||
"@nestjs/mongoose": "10.0.0",
|
||||
"@nestjs/typeorm": "10.0.0",
|
||||
"@nestjs/apollo": "11.0.5",
|
||||
"@nestjs/graphql": "11.0.5",
|
||||
"@nestjs/mongoose": "9.2.2",
|
||||
"@nestjs/typeorm": "9.0.1",
|
||||
"@types/amqplib": "0.10.1",
|
||||
"@types/bytes": "3.1.1",
|
||||
"@types/chai": "4.3.5",
|
||||
"@types/chai-as-promised": "7.1.5",
|
||||
"@types/cors": "2.8.13",
|
||||
"@types/express": "4.17.17",
|
||||
"@types/gulp": "4.0.12",
|
||||
"@types/gulp": "4.0.10",
|
||||
"@types/http-errors": "2.0.1",
|
||||
"@types/mocha": "10.0.1",
|
||||
"@types/node": "20.3.2",
|
||||
"@types/node": "20.2.3",
|
||||
"@types/sinon": "10.0.15",
|
||||
"@types/supertest": "2.0.12",
|
||||
"@types/ws": "8.5.5",
|
||||
"@typescript-eslint/eslint-plugin": "5.60.0",
|
||||
"@typescript-eslint/parser": "5.60.1",
|
||||
"@types/ws": "8.5.4",
|
||||
"@typescript-eslint/eslint-plugin": "4.33.0",
|
||||
"@typescript-eslint/parser": "4.33.0",
|
||||
"amqp-connection-manager": "4.1.13",
|
||||
"amqplib": "0.10.3",
|
||||
"artillery": "1.7.9",
|
||||
"body-parser": "1.20.2",
|
||||
"bytes": "3.1.2",
|
||||
"cache-manager": "5.2.3",
|
||||
"cache-manager": "5.2.1",
|
||||
"cache-manager-redis-store": "3.0.1",
|
||||
"chai": "4.3.7",
|
||||
"chai-as-promised": "7.1.1",
|
||||
"clang-format": "1.8.0",
|
||||
"commitlint-circle": "1.0.0",
|
||||
"concurrently": "8.2.0",
|
||||
"conventional-changelog": "4.0.0",
|
||||
"core-js": "3.31.0",
|
||||
"concurrently": "8.0.1",
|
||||
"conventional-changelog": "3.1.25",
|
||||
"core-js": "3.30.2",
|
||||
"coveralls": "3.1.1",
|
||||
"delete-empty": "3.0.0",
|
||||
"engine.io-client": "6.5.0",
|
||||
"eslint": "8.43.0",
|
||||
"engine.io-client": "6.4.0",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eventsource": "2.0.2",
|
||||
"fancy-log": "2.0.0",
|
||||
"fastify": "4.18.0",
|
||||
"graphql": "16.7.1",
|
||||
"fastify": "4.17.0",
|
||||
"graphql": "16.6.0",
|
||||
"graphql-tools": "9.0.0",
|
||||
"gulp": "4.0.2",
|
||||
"gulp-clang-format": "1.0.27",
|
||||
@@ -148,35 +148,35 @@
|
||||
"kafkajs": "2.2.4",
|
||||
"lerna": "2.11.0",
|
||||
"lerna-changelog": "2.2.0",
|
||||
"light-my-request": "5.10.0",
|
||||
"light-my-request": "5.9.1",
|
||||
"lint-staged": "13.2.2",
|
||||
"markdown-table": "2.0.0",
|
||||
"merge-graphql-schemas": "1.7.8",
|
||||
"mocha": "10.2.0",
|
||||
"mongoose": "7.3.1",
|
||||
"mongoose": "7.2.0",
|
||||
"mqtt": "4.3.7",
|
||||
"multer": "1.4.4",
|
||||
"mysql2": "3.4.1",
|
||||
"nats": "2.15.1",
|
||||
"mysql2": "3.3.1",
|
||||
"nats": "2.13.1",
|
||||
"nodemon": "2.0.22",
|
||||
"nyc": "15.1.0",
|
||||
"prettier": "2.8.8",
|
||||
"redis": "4.6.7",
|
||||
"redis": "4.6.6",
|
||||
"rxjs-compat": "6.6.7",
|
||||
"sinon": "15.2.0",
|
||||
"sinon": "15.1.0",
|
||||
"sinon-chai": "3.7.0",
|
||||
"socket.io-client": "4.7.0",
|
||||
"socket.io-client": "4.6.1",
|
||||
"subscriptions-transport-ws": "0.11.0",
|
||||
"supertest": "6.3.3",
|
||||
"ts-morph": "19.0.0",
|
||||
"ts-morph": "18.0.0",
|
||||
"ts-node": "10.9.1",
|
||||
"typeorm": "0.3.17",
|
||||
"typescript": "5.1.5",
|
||||
"typeorm": "0.3.16",
|
||||
"typescript": "5.0.4",
|
||||
"wrk": "1.2.1",
|
||||
"ws": "8.13.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
"node": ">= 12.9.0"
|
||||
},
|
||||
"collective": {
|
||||
"type": "opencollective",
|
||||
|
||||
@@ -136,8 +136,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -5,8 +5,7 @@ import {
|
||||
import { isObject, isString } from '../utils/shared.utils';
|
||||
|
||||
export interface HttpExceptionOptions {
|
||||
/** original cause of the error */
|
||||
cause?: unknown;
|
||||
cause?: Error;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
@@ -69,13 +68,14 @@ export class HttpException extends Error {
|
||||
this.initCause();
|
||||
}
|
||||
|
||||
public cause: unknown;
|
||||
public cause: Error | undefined;
|
||||
|
||||
/**
|
||||
* Configures error chaining support
|
||||
*
|
||||
* @see https://nodejs.org/en/blog/release/v16.9.0/#error-cause
|
||||
* @see https://github.com/microsoft/TypeScript/issues/45167
|
||||
* See:
|
||||
* - https://nodejs.org/en/blog/release/v16.9.0/#error-cause
|
||||
* - https://github.com/microsoft/TypeScript/issues/45167
|
||||
*/
|
||||
public initCause(): void {
|
||||
if (this.options?.cause) {
|
||||
|
||||
@@ -31,10 +31,6 @@ export interface WsArgumentsHost {
|
||||
* Returns the client object.
|
||||
*/
|
||||
getClient<T = any>(): T;
|
||||
/**
|
||||
* Returns the pattern for the event
|
||||
*/
|
||||
getPattern(): string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/common",
|
||||
"version": "10.0.4",
|
||||
"version": "9.4.2",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@common)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"homepage": "https://nestjs.com",
|
||||
@@ -19,7 +19,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iterare": "1.2.1",
|
||||
"tslib": "2.6.0",
|
||||
"tslib": "2.5.2",
|
||||
"uid": "2.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -21,13 +21,12 @@ export class FileTypeValidator extends FileValidator<FileTypeValidatorOptions> {
|
||||
return `Validation failed (expected type is ${this.validationOptions.fileType})`;
|
||||
}
|
||||
|
||||
isValid<TFile extends IFile = any>(file?: TFile): boolean {
|
||||
isValid<TFile extends IFile = any>(file: TFile): boolean {
|
||||
if (!this.validationOptions) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (
|
||||
!!file &&
|
||||
'mimetype' in file &&
|
||||
!!file.mimetype.match(this.validationOptions.fileType)
|
||||
);
|
||||
|
||||
@@ -26,8 +26,8 @@ export class MaxFileSizeValidator extends FileValidator<MaxFileSizeValidatorOpti
|
||||
return `Validation failed (expected size is less than ${this.validationOptions.maxSize})`;
|
||||
}
|
||||
|
||||
public isValid<TFile extends IFile = any>(file?: TFile): boolean {
|
||||
if (!this.validationOptions || !file) {
|
||||
public isValid<TFile extends IFile = any>(file: TFile): boolean {
|
||||
if (!this.validationOptions) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
ErrorHttpStatusCode,
|
||||
HttpErrorByCode,
|
||||
} from '../utils/http-error-by-code.util';
|
||||
import { isNil } from '../utils/shared.utils';
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
@@ -17,7 +16,6 @@ import { isNil } from '../utils/shared.utils';
|
||||
export interface ParseBoolPipeOptions {
|
||||
errorHttpStatusCode?: ErrorHttpStatusCode;
|
||||
exceptionFactory?: (error: string) => any;
|
||||
optional?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,7 +31,7 @@ export class ParseBoolPipe
|
||||
{
|
||||
protected exceptionFactory: (error: string) => any;
|
||||
|
||||
constructor(@Optional() protected readonly options?: ParseBoolPipeOptions) {
|
||||
constructor(@Optional() options?: ParseBoolPipeOptions) {
|
||||
options = options || {};
|
||||
const { exceptionFactory, errorHttpStatusCode = HttpStatus.BAD_REQUEST } =
|
||||
options;
|
||||
@@ -53,9 +51,6 @@ export class ParseBoolPipe
|
||||
value: string | boolean,
|
||||
metadata: ArgumentMetadata,
|
||||
): Promise<boolean> {
|
||||
if (isNil(value) && this.options.optional) {
|
||||
return value;
|
||||
}
|
||||
if (this.isTrue(value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import { ArgumentMetadata, HttpStatus } from '../index';
|
||||
import { Injectable, Optional } from '../decorators/core';
|
||||
import { ArgumentMetadata, HttpStatus, Injectable, Optional } from '../index';
|
||||
import { PipeTransform } from '../interfaces/features/pipe-transform.interface';
|
||||
import {
|
||||
ErrorHttpStatusCode,
|
||||
HttpErrorByCode,
|
||||
} from '../utils/http-error-by-code.util';
|
||||
import { isNil } from '../utils/shared.utils';
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
*/
|
||||
export interface ParseEnumPipeOptions {
|
||||
optional?: boolean;
|
||||
errorHttpStatusCode?: ErrorHttpStatusCode;
|
||||
exceptionFactory?: (error: string) => any;
|
||||
}
|
||||
@@ -26,9 +23,10 @@ export interface ParseEnumPipeOptions {
|
||||
@Injectable()
|
||||
export class ParseEnumPipe<T = any> implements PipeTransform<T> {
|
||||
protected exceptionFactory: (error: string) => any;
|
||||
|
||||
constructor(
|
||||
protected readonly enumType: T,
|
||||
@Optional() protected readonly options?: ParseEnumPipeOptions,
|
||||
@Optional() options?: ParseEnumPipeOptions,
|
||||
) {
|
||||
if (!enumType) {
|
||||
throw new Error(
|
||||
@@ -52,9 +50,6 @@ export class ParseEnumPipe<T = any> implements PipeTransform<T> {
|
||||
* @param metadata contains metadata about the currently processed route argument
|
||||
*/
|
||||
async transform(value: T, metadata: ArgumentMetadata): Promise<T> {
|
||||
if (isNil(value) && this.options.optional) {
|
||||
return value;
|
||||
}
|
||||
if (!this.isEnum(value)) {
|
||||
throw this.exceptionFactory(
|
||||
'Validation failed (enum string is expected)',
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
ErrorHttpStatusCode,
|
||||
HttpErrorByCode,
|
||||
} from '../utils/http-error-by-code.util';
|
||||
import { isNil } from '../utils/shared.utils';
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
@@ -13,7 +12,6 @@ import { isNil } from '../utils/shared.utils';
|
||||
export interface ParseFloatPipeOptions {
|
||||
errorHttpStatusCode?: ErrorHttpStatusCode;
|
||||
exceptionFactory?: (error: string) => any;
|
||||
optional?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,7 +25,7 @@ export interface ParseFloatPipeOptions {
|
||||
export class ParseFloatPipe implements PipeTransform<string> {
|
||||
protected exceptionFactory: (error: string) => any;
|
||||
|
||||
constructor(@Optional() protected readonly options?: ParseFloatPipeOptions) {
|
||||
constructor(@Optional() options?: ParseFloatPipeOptions) {
|
||||
options = options || {};
|
||||
const { exceptionFactory, errorHttpStatusCode = HttpStatus.BAD_REQUEST } =
|
||||
options;
|
||||
@@ -45,9 +43,6 @@ export class ParseFloatPipe implements PipeTransform<string> {
|
||||
* @param metadata contains metadata about the currently processed route argument
|
||||
*/
|
||||
async transform(value: string, metadata: ArgumentMetadata): Promise<number> {
|
||||
if (isNil(value) && this.options.optional) {
|
||||
return value;
|
||||
}
|
||||
if (!this.isNumeric(value)) {
|
||||
throw this.exceptionFactory(
|
||||
'Validation failed (numeric string is expected)',
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
ErrorHttpStatusCode,
|
||||
HttpErrorByCode,
|
||||
} from '../utils/http-error-by-code.util';
|
||||
import { isNil } from '../utils/shared.utils';
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
@@ -17,7 +16,6 @@ import { isNil } from '../utils/shared.utils';
|
||||
export interface ParseIntPipeOptions {
|
||||
errorHttpStatusCode?: ErrorHttpStatusCode;
|
||||
exceptionFactory?: (error: string) => any;
|
||||
optional?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,7 +29,7 @@ export interface ParseIntPipeOptions {
|
||||
export class ParseIntPipe implements PipeTransform<string> {
|
||||
protected exceptionFactory: (error: string) => any;
|
||||
|
||||
constructor(@Optional() protected readonly options?: ParseIntPipeOptions) {
|
||||
constructor(@Optional() options?: ParseIntPipeOptions) {
|
||||
options = options || {};
|
||||
const { exceptionFactory, errorHttpStatusCode = HttpStatus.BAD_REQUEST } =
|
||||
options;
|
||||
@@ -49,9 +47,6 @@ export class ParseIntPipe implements PipeTransform<string> {
|
||||
* @param metadata contains metadata about the currently processed route argument
|
||||
*/
|
||||
async transform(value: string, metadata: ArgumentMetadata): Promise<number> {
|
||||
if (isNil(value) && this.options.optional) {
|
||||
return value;
|
||||
}
|
||||
if (!this.isNumeric(value)) {
|
||||
throw this.exceptionFactory(
|
||||
'Validation failed (numeric string is expected)',
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
ErrorHttpStatusCode,
|
||||
HttpErrorByCode,
|
||||
} from '../utils/http-error-by-code.util';
|
||||
import { isNil, isString } from '../utils/shared.utils';
|
||||
import { isString } from '../utils/shared.utils';
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
@@ -18,7 +18,6 @@ export interface ParseUUIDPipeOptions {
|
||||
version?: '3' | '4' | '5';
|
||||
errorHttpStatusCode?: ErrorHttpStatusCode;
|
||||
exceptionFactory?: (errors: string) => any;
|
||||
optional?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,7 +38,7 @@ export class ParseUUIDPipe implements PipeTransform<string> {
|
||||
private readonly version: '3' | '4' | '5';
|
||||
protected exceptionFactory: (errors: string) => any;
|
||||
|
||||
constructor(@Optional() protected readonly options?: ParseUUIDPipeOptions) {
|
||||
constructor(@Optional() options?: ParseUUIDPipeOptions) {
|
||||
options = options || {};
|
||||
const {
|
||||
exceptionFactory,
|
||||
@@ -54,9 +53,6 @@ export class ParseUUIDPipe implements PipeTransform<string> {
|
||||
}
|
||||
|
||||
async transform(value: string, metadata: ArgumentMetadata): Promise<string> {
|
||||
if (isNil(value) && this.options.optional) {
|
||||
return value;
|
||||
}
|
||||
if (!this.isUUID(value, this.version)) {
|
||||
throw this.exceptionFactory(
|
||||
`Validation failed (uuid${
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { LogLevel } from '../logger.service';
|
||||
|
||||
const LOG_LEVEL_VALUES: Record<LogLevel, number> = {
|
||||
verbose: 0,
|
||||
debug: 1,
|
||||
debug: 0,
|
||||
verbose: 1,
|
||||
log: 2,
|
||||
warn: 3,
|
||||
error: 4,
|
||||
|
||||
@@ -72,14 +72,6 @@ describe('FileTypeValidator', () => {
|
||||
|
||||
expect(fileTypeValidator.isValid(requestFile)).to.equal(false);
|
||||
});
|
||||
|
||||
it('should return false when no file provided', () => {
|
||||
const fileTypeValidator = new FileTypeValidator({
|
||||
fileType: 'image/jpeg',
|
||||
});
|
||||
|
||||
expect(fileTypeValidator.isValid()).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildErrorMessage', () => {
|
||||
|
||||
@@ -40,14 +40,6 @@ describe('MaxFileSizeValidator', () => {
|
||||
|
||||
expect(maxFileSizeValidator.isValid(requestFile)).to.equal(false);
|
||||
});
|
||||
|
||||
it('should return true when no file provided', () => {
|
||||
const maxFileSizeValidator = new MaxFileSizeValidator({
|
||||
maxSize: oneKb,
|
||||
});
|
||||
|
||||
expect(maxFileSizeValidator.isValid()).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildErrorMessage', () => {
|
||||
|
||||
@@ -18,12 +18,6 @@ describe('ParseBoolPipe', () => {
|
||||
expect(await target.transform(false, {} as ArgumentMetadata)).to.be
|
||||
.false;
|
||||
});
|
||||
|
||||
it('should not throw an error if the value is undefined/null and optional is true', async () => {
|
||||
const target = new ParseBoolPipe({ optional: true });
|
||||
const value = await target.transform(undefined, {} as ArgumentMetadata);
|
||||
expect(value).to.equal(undefined);
|
||||
});
|
||||
});
|
||||
describe('when validation fails', () => {
|
||||
it('should throw an error', async () => {
|
||||
|
||||
@@ -14,7 +14,6 @@ describe('ParseEnumPipe', () => {
|
||||
Up = 'UP',
|
||||
}
|
||||
let target: ParseEnumPipe;
|
||||
|
||||
beforeEach(() => {
|
||||
target = new ParseEnumPipe(Direction, {
|
||||
exceptionFactory: (error: any) => new CustomTestError(),
|
||||
@@ -27,12 +26,6 @@ describe('ParseEnumPipe', () => {
|
||||
Direction.Up,
|
||||
);
|
||||
});
|
||||
|
||||
it('should not throw an error if enumType is undefined/null and optional is true', async () => {
|
||||
const target = new ParseEnumPipe('DOWN', { optional: true });
|
||||
const value = await target.transform(undefined, {} as ArgumentMetadata);
|
||||
expect(value).to.equal(undefined);
|
||||
});
|
||||
});
|
||||
describe('when validation fails', () => {
|
||||
it('should throw an error', async () => {
|
||||
@@ -40,16 +33,6 @@ describe('ParseEnumPipe', () => {
|
||||
target.transform('DOWN', {} as ArgumentMetadata),
|
||||
).to.be.rejectedWith(CustomTestError);
|
||||
});
|
||||
|
||||
it('should throw an error if enumType is wrong and optional is true', async () => {
|
||||
target = new ParseEnumPipe(Direction, {
|
||||
exceptionFactory: (error: any) => new CustomTestError(),
|
||||
optional: true,
|
||||
});
|
||||
return expect(
|
||||
target.transform('DOWN', {} as ArgumentMetadata),
|
||||
).to.be.rejectedWith(CustomTestError);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('constructor', () => {
|
||||
|
||||
@@ -25,11 +25,6 @@ describe('ParseFloatPipe', () => {
|
||||
parseFloat(num),
|
||||
);
|
||||
});
|
||||
it('should not throw an error if the value is undefined/null and optional is true', async () => {
|
||||
const target = new ParseFloatPipe({ optional: true });
|
||||
const value = await target.transform(undefined, {} as ArgumentMetadata);
|
||||
expect(value).to.equal(undefined);
|
||||
});
|
||||
});
|
||||
describe('when validation fails', () => {
|
||||
it('should throw an error', async () => {
|
||||
|
||||
@@ -30,11 +30,6 @@ describe('ParseIntPipe', () => {
|
||||
-3,
|
||||
);
|
||||
});
|
||||
it('should not throw an error if the value is undefined/null and optional is true', async () => {
|
||||
const target = new ParseIntPipe({ optional: true });
|
||||
const value = await target.transform(undefined, {} as ArgumentMetadata);
|
||||
expect(value).to.equal(undefined);
|
||||
});
|
||||
});
|
||||
describe('when validation fails', () => {
|
||||
it('should throw an error', async () => {
|
||||
|
||||
@@ -41,11 +41,6 @@ describe('ParseUUIDPipe', () => {
|
||||
target = new ParseUUIDPipe({ version: '5', exceptionFactory });
|
||||
expect(await target.transform(v5, {} as ArgumentMetadata)).to.equal(v5);
|
||||
});
|
||||
it('should not throw an error if the value is undefined/null and optional is true', async () => {
|
||||
const target = new ParseUUIDPipe({ optional: true });
|
||||
const value = await target.transform(undefined, {} as ArgumentMetadata);
|
||||
expect(value).to.equal(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when validation fails', () => {
|
||||
|
||||
@@ -136,8 +136,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -59,7 +59,6 @@ export class ExecutionContextHost implements ExecutionContext {
|
||||
return Object.assign(this, {
|
||||
getClient: () => this.getArgByIndex(0),
|
||||
getData: () => this.getArgByIndex(1),
|
||||
getPattern: () => this.getArgByIndex(this.getArgs().length - 1),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@ import {
|
||||
Controller,
|
||||
} from '@nestjs/common/interfaces';
|
||||
import { isEmpty } from '@nestjs/common/utils/shared.utils';
|
||||
import { AsyncResource } from 'async_hooks';
|
||||
import { Observable, defer, from as fromPromise } from 'rxjs';
|
||||
import { defer, from as fromPromise, Observable } from 'rxjs';
|
||||
import { mergeAll, switchMap } from 'rxjs/operators';
|
||||
import { ExecutionContextHost } from '../helpers/execution-context-host';
|
||||
|
||||
@@ -27,7 +26,7 @@ export class InterceptorsConsumer {
|
||||
|
||||
const nextFn = async (i = 0) => {
|
||||
if (i >= interceptors.length) {
|
||||
return defer(AsyncResource.bind(() => this.transformDeferred(next)));
|
||||
return this.transformDeferred(next);
|
||||
}
|
||||
const handler: CallHandler = {
|
||||
handle: () => fromPromise(nextFn(i + 1)).pipe(mergeAll()),
|
||||
|
||||
@@ -9,7 +9,7 @@ export class MetadataScanner {
|
||||
private readonly cachedScannedPrototypes: Map<object, string[]> = new Map();
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @deprecated
|
||||
* @see {@link getAllMethodNames}
|
||||
* @see getAllMethodNames
|
||||
*/
|
||||
@@ -62,7 +62,7 @@ export class MetadataScanner {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @deprecated
|
||||
* @see {@link getAllMethodNames}
|
||||
* @see getAllMethodNames
|
||||
*/
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
MiddlewareConfiguration,
|
||||
RouteInfo,
|
||||
} from '@nestjs/common/interfaces/middleware';
|
||||
import { stripEndSlash } from '@nestjs/common/utils/shared.utils';
|
||||
import { iterate } from 'iterare';
|
||||
import { RouteInfoPathExtractor } from './route-info-path-extractor';
|
||||
import { RoutesMapper } from './routes-mapper';
|
||||
@@ -101,27 +100,21 @@ export class MiddlewareBuilder implements MiddlewareConsumer {
|
||||
const routesWithRegex = routes
|
||||
.filter(route => route.path.includes(':'))
|
||||
.map(route => ({
|
||||
method: route.method,
|
||||
path: route.path,
|
||||
regex: new RegExp(
|
||||
'^(' + route.path.replace(regexMatchParams, wildcard) + ')$',
|
||||
'g',
|
||||
),
|
||||
}));
|
||||
|
||||
return routes.filter(route => {
|
||||
const isOverlapped = (item: { regex: RegExp } & RouteInfo): boolean => {
|
||||
if (route.method !== item.method) {
|
||||
return false;
|
||||
}
|
||||
const normalizedRoutePath = stripEndSlash(route.path);
|
||||
return (
|
||||
normalizedRoutePath !== item.path &&
|
||||
item.regex.test(normalizedRoutePath)
|
||||
);
|
||||
const isOverlapped = (v: { path: string; regex: RegExp }) => {
|
||||
return route.path !== v.path && route.path.match(v.regex);
|
||||
};
|
||||
const routeMatch = routesWithRegex.find(isOverlapped);
|
||||
return routeMatch === undefined;
|
||||
|
||||
if (routeMatch === undefined) {
|
||||
return route;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -66,7 +66,7 @@ export class MiddlewareModule<
|
||||
config,
|
||||
appRef,
|
||||
);
|
||||
this.routesMapper = new RoutesMapper(container, config);
|
||||
this.routesMapper = new RoutesMapper(container);
|
||||
this.resolver = new MiddlewareResolver(middlewareContainer, injector);
|
||||
this.routeInfoPathExtractor = new RouteInfoPathExtractor(config);
|
||||
this.injector = injector;
|
||||
|
||||
@@ -1,48 +1,35 @@
|
||||
import {
|
||||
MODULE_PATH,
|
||||
PATH_METADATA,
|
||||
VERSION_METADATA,
|
||||
} from '@nestjs/common/constants';
|
||||
import {
|
||||
RouteInfo,
|
||||
Type,
|
||||
VERSION_NEUTRAL,
|
||||
VersionValue,
|
||||
} from '@nestjs/common/interfaces';
|
||||
import { MODULE_PATH, PATH_METADATA } from '@nestjs/common/constants';
|
||||
import { RouteInfo, Type } from '@nestjs/common/interfaces';
|
||||
import {
|
||||
addLeadingSlash,
|
||||
isString,
|
||||
isUndefined,
|
||||
} from '@nestjs/common/utils/shared.utils';
|
||||
import { ApplicationConfig } from '../application-config';
|
||||
import { NestContainer } from '../injector/container';
|
||||
import { Module } from '../injector/module';
|
||||
import { MetadataScanner } from '../metadata-scanner';
|
||||
import { PathsExplorer, RouteDefinition } from '../router/paths-explorer';
|
||||
import { PathsExplorer } from '../router/paths-explorer';
|
||||
import { targetModulesByContainer } from '../router/router-module';
|
||||
|
||||
export class RoutesMapper {
|
||||
private readonly pathsExplorer: PathsExplorer;
|
||||
|
||||
constructor(
|
||||
private readonly container: NestContainer,
|
||||
private readonly applicationConfig: ApplicationConfig,
|
||||
) {
|
||||
constructor(private readonly container: NestContainer) {
|
||||
this.pathsExplorer = new PathsExplorer(new MetadataScanner());
|
||||
}
|
||||
|
||||
public mapRouteToRouteInfo(
|
||||
controllerOrRoute: Type<any> | RouteInfo | string,
|
||||
route: Type<any> | RouteInfo | string,
|
||||
): RouteInfo[] {
|
||||
if (isString(controllerOrRoute)) {
|
||||
return this.getRouteInfoFromPath(controllerOrRoute);
|
||||
if (isString(route)) {
|
||||
return this.getRouteInfoFromPath(route);
|
||||
}
|
||||
const routePathOrPaths = this.getRoutePath(controllerOrRoute);
|
||||
if (this.isRouteInfo(routePathOrPaths, controllerOrRoute)) {
|
||||
return this.getRouteInfoFromObject(controllerOrRoute);
|
||||
const routePathOrPaths = this.getRoutePath(route);
|
||||
if (this.isRouteInfo(routePathOrPaths, route)) {
|
||||
return this.getRouteInfoFromObject(route);
|
||||
}
|
||||
|
||||
return this.getRouteInfoFromController(controllerOrRoute, routePathOrPaths);
|
||||
return this.getRouteInfoFromController(route, routePathOrPaths);
|
||||
}
|
||||
|
||||
private getRouteInfoFromPath(routePath: string): RouteInfo[] {
|
||||
@@ -75,47 +62,33 @@ export class RoutesMapper {
|
||||
Object.create(controller),
|
||||
controller.prototype,
|
||||
);
|
||||
const controllerVersion = this.getVersionMetadata(controller);
|
||||
const versioningConfig = this.applicationConfig.getVersioning();
|
||||
const moduleRef = this.getHostModuleOfController(controller);
|
||||
const modulePath = this.getModulePath(moduleRef?.metatype);
|
||||
|
||||
const concatPaths = <T>(acc: T[], currentValue: T[]) =>
|
||||
acc.concat(currentValue);
|
||||
|
||||
const toUndefinedIfNeural = (version: VersionValue) =>
|
||||
version === VERSION_NEUTRAL ? undefined : version;
|
||||
|
||||
const toRouteInfo = (item: RouteDefinition, prefix: string) =>
|
||||
item.path
|
||||
?.map(p => {
|
||||
let endpointPath = modulePath ?? '';
|
||||
endpointPath += this.normalizeGlobalPath(prefix) + addLeadingSlash(p);
|
||||
|
||||
const routeInfo: RouteInfo = {
|
||||
path: endpointPath,
|
||||
method: item.requestMethod,
|
||||
};
|
||||
const version = item.version ?? controllerVersion;
|
||||
if (version && versioningConfig) {
|
||||
if (typeof version !== 'string' && Array.isArray(version)) {
|
||||
return version.map(v => ({
|
||||
...routeInfo,
|
||||
version: toUndefinedIfNeural(v),
|
||||
}));
|
||||
}
|
||||
routeInfo.version = toUndefinedIfNeural(version);
|
||||
}
|
||||
|
||||
return routeInfo;
|
||||
})
|
||||
.flat() as RouteInfo[];
|
||||
|
||||
return []
|
||||
.concat(routePath)
|
||||
.map(routePath =>
|
||||
controllerPaths
|
||||
.map(item => toRouteInfo(item, routePath))
|
||||
.map(item =>
|
||||
item.path?.map(p => {
|
||||
let path = modulePath ?? '';
|
||||
path += this.normalizeGlobalPath(routePath) + addLeadingSlash(p);
|
||||
|
||||
const routeInfo: RouteInfo = {
|
||||
path,
|
||||
method: item.requestMethod,
|
||||
};
|
||||
|
||||
if (item.version) {
|
||||
routeInfo.version = item.version;
|
||||
}
|
||||
|
||||
return routeInfo;
|
||||
}),
|
||||
)
|
||||
.reduce(concatPaths, []),
|
||||
)
|
||||
.reduce(concatPaths, []);
|
||||
@@ -168,16 +141,4 @@ export class RoutesMapper {
|
||||
);
|
||||
return modulePath ?? Reflect.getMetadata(MODULE_PATH, metatype);
|
||||
}
|
||||
|
||||
private getVersionMetadata(
|
||||
metatype: Type<unknown> | Function,
|
||||
): VersionValue | undefined {
|
||||
const versioningConfig = this.applicationConfig.getVersioning();
|
||||
if (versioningConfig) {
|
||||
return (
|
||||
Reflect.getMetadata(VERSION_METADATA, metatype) ??
|
||||
versioningConfig.defaultVersion
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/core",
|
||||
"version": "10.0.4",
|
||||
"version": "9.4.2",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@core)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
@@ -32,17 +32,17 @@
|
||||
"fast-safe-stringify": "2.1.1",
|
||||
"iterare": "1.2.1",
|
||||
"path-to-regexp": "3.2.0",
|
||||
"tslib": "2.6.0",
|
||||
"tslib": "2.5.2",
|
||||
"uid": "2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/common": "10.0.4"
|
||||
"@nestjs/common": "9.4.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^10.0.0",
|
||||
"@nestjs/microservices": "^10.0.0",
|
||||
"@nestjs/platform-express": "^10.0.0",
|
||||
"@nestjs/websockets": "^10.0.0",
|
||||
"@nestjs/common": "^9.0.0",
|
||||
"@nestjs/microservices": "^9.0.0",
|
||||
"@nestjs/platform-express": "^9.0.0",
|
||||
"@nestjs/websockets": "^9.0.0",
|
||||
"reflect-metadata": "^0.1.12",
|
||||
"rxjs": "^7.1.0"
|
||||
},
|
||||
|
||||
@@ -16,7 +16,7 @@ describe('Error Messages', () => {
|
||||
it('should display class', () => {
|
||||
const expectedResult =
|
||||
stringCleaner(`Nest can't resolve dependencies of the CatService (?, CatService). Please make sure that the argument dependency at index [0] is available in the current context.
|
||||
|
||||
|
||||
Potential solutions:
|
||||
- If dependency is a provider, is it part of the current Module?
|
||||
- If dependency is exported from a separate @Module, is that module imported within Module?
|
||||
@@ -39,7 +39,7 @@ describe('Error Messages', () => {
|
||||
it('should display the provide token', () => {
|
||||
const expectedResult =
|
||||
stringCleaner(`Nest can't resolve dependencies of the CatService (?, MY_TOKEN). Please make sure that the argument dependency at index [0] is available in the current context.
|
||||
|
||||
|
||||
Potential solutions:
|
||||
- If dependency is a provider, is it part of the current Module?
|
||||
- If dependency is exported from a separate @Module, is that module imported within Module?
|
||||
@@ -60,7 +60,7 @@ describe('Error Messages', () => {
|
||||
it('should display the function name', () => {
|
||||
const expectedResult =
|
||||
stringCleaner(`Nest can't resolve dependencies of the CatService (?, CatFunction). Please make sure that the argument dependency at index [0] is available in the current context.
|
||||
|
||||
|
||||
Potential solutions:
|
||||
- If dependency is a provider, is it part of the current Module?
|
||||
- If dependency is exported from a separate @Module, is that module imported within Module?
|
||||
@@ -81,7 +81,7 @@ describe('Error Messages', () => {
|
||||
it('should use "+" if unknown dependency name', () => {
|
||||
const expectedResult =
|
||||
stringCleaner(`Nest can't resolve dependencies of the CatService (?, +). Please make sure that the argument dependency at index [0] is available in the current context.
|
||||
|
||||
|
||||
Potential solutions:
|
||||
- If dependency is a provider, is it part of the current Module?
|
||||
- If dependency is exported from a separate @Module, is that module imported within Module?
|
||||
@@ -102,7 +102,7 @@ describe('Error Messages', () => {
|
||||
it('should display the module name', () => {
|
||||
const expectedResult =
|
||||
stringCleaner(`Nest can't resolve dependencies of the CatService (?, MY_TOKEN). Please make sure that the argument dependency at index [0] is available in the TestModule context.
|
||||
|
||||
|
||||
Potential solutions:
|
||||
- Is TestModule a valid NestJS module?
|
||||
- If dependency is a provider, is it part of the current TestModule?
|
||||
@@ -136,7 +136,7 @@ describe('Error Messages', () => {
|
||||
it('should display the symbol name of the provider', () => {
|
||||
const expectedResult =
|
||||
stringCleaner(`Nest can't resolve dependencies of the Symbol(CatProvider) (?). Please make sure that the argument dependency at index [0] is available in the current context.
|
||||
|
||||
|
||||
Potential solutions:
|
||||
- If dependency is a provider, is it part of the current Module?
|
||||
- If dependency is exported from a separate @Module, is that module imported within Module?
|
||||
@@ -157,7 +157,7 @@ describe('Error Messages', () => {
|
||||
it('should display the symbol dependency of the provider', () => {
|
||||
const expectedResult =
|
||||
stringCleaner(`Nest can't resolve dependencies of the CatProvider (?, Symbol(DogProvider)). Please make sure that the argument dependency at index [0] is available in the current context.
|
||||
|
||||
|
||||
Potential solutions:
|
||||
- If dependency is a provider, is it part of the current Module?
|
||||
- If dependency is exported from a separate @Module, is that module imported within Module?
|
||||
@@ -201,7 +201,7 @@ Scope [AppModule -> CatsModule]`);
|
||||
it('should display the module name with the invalid index and scope', () => {
|
||||
const expectedMessage =
|
||||
stringCleaner(`Nest cannot create the CatsModule instance.
|
||||
Received an unexpected value at index [0] of the CatsModule "imports" array.
|
||||
Received an unexpected value at index [0] of the CatsModule "imports" array.
|
||||
|
||||
Scope [AppModule -> CatsModule]`);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common';
|
||||
import { AsyncLocalStorage } from 'async_hooks';
|
||||
import { expect } from 'chai';
|
||||
import { Observable, lastValueFrom, of, retry } from 'rxjs';
|
||||
import { Observable, lastValueFrom, of } from 'rxjs';
|
||||
import * as sinon from 'sinon';
|
||||
import { InterceptorsConsumer } from '../../interceptors/interceptors-consumer';
|
||||
|
||||
@@ -85,8 +85,8 @@ describe('InterceptorsConsumer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when AsyncLocalStorage is used', () => {
|
||||
it('should allow an interceptor to set values in AsyncLocalStorage that are accesible from the controller', async () => {
|
||||
describe('AsyncLocalStorage', () => {
|
||||
it('Allows an interceptor to set values in AsyncLocalStorage that are accesible from the controller', async () => {
|
||||
const storage = new AsyncLocalStorage<Record<string, any>>();
|
||||
class StorageInterceptor implements NestInterceptor {
|
||||
intercept(
|
||||
@@ -96,9 +96,7 @@ describe('InterceptorsConsumer', () => {
|
||||
return storage.run({ value: 'hello' }, () => next.handle());
|
||||
}
|
||||
}
|
||||
const next = () => {
|
||||
return Promise.resolve(storage.getStore().value);
|
||||
};
|
||||
const next = () => Promise.resolve(storage.getStore().value);
|
||||
const intercepted = await consumer.intercept(
|
||||
[new StorageInterceptor()],
|
||||
null,
|
||||
@@ -110,35 +108,6 @@ describe('InterceptorsConsumer', () => {
|
||||
expect(result).to.equal('hello');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when retrying is enabled', () => {
|
||||
it('should retry a specified amount of times', async () => {
|
||||
let count = 0;
|
||||
const next = () => {
|
||||
count++;
|
||||
if (count < 3) {
|
||||
return Promise.reject(new Error('count not reached'));
|
||||
}
|
||||
return Promise.resolve(count);
|
||||
};
|
||||
class RetryInterceptor implements NestInterceptor {
|
||||
intercept(
|
||||
_context: ExecutionContext,
|
||||
next: CallHandler<any>,
|
||||
): Observable<any> | Promise<Observable<any>> {
|
||||
return next.handle().pipe(retry(4));
|
||||
}
|
||||
}
|
||||
const intercepted = await consumer.intercept(
|
||||
[new RetryInterceptor()],
|
||||
null,
|
||||
{ constructor: null },
|
||||
null,
|
||||
next,
|
||||
);
|
||||
expect(await transformToResult(intercepted)).to.equal(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('createContext', () => {
|
||||
it('should return execution context object', () => {
|
||||
|
||||
@@ -1,18 +1,5 @@
|
||||
import { expect } from 'chai';
|
||||
import {
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Head,
|
||||
Options,
|
||||
Patch,
|
||||
Post,
|
||||
Put,
|
||||
RequestMethod,
|
||||
Version,
|
||||
VersioningType,
|
||||
} from '../../../common';
|
||||
import { MiddlewareConfigProxy } from '../../../common/interfaces';
|
||||
import { Controller, Get, RequestMethod, Version } from '../../../common';
|
||||
import { ApplicationConfig } from '../../application-config';
|
||||
import { NestContainer } from '../../injector/container';
|
||||
import { MiddlewareBuilder } from '../../middleware/builder';
|
||||
@@ -26,26 +13,23 @@ describe('MiddlewareBuilder', () => {
|
||||
beforeEach(() => {
|
||||
const container = new NestContainer();
|
||||
const appConfig = new ApplicationConfig();
|
||||
appConfig.enableVersioning({ type: VersioningType.URI });
|
||||
builder = new MiddlewareBuilder(
|
||||
new RoutesMapper(container, appConfig),
|
||||
new RoutesMapper(container),
|
||||
new NoopHttpAdapter({}),
|
||||
new RouteInfoPathExtractor(appConfig),
|
||||
);
|
||||
});
|
||||
describe('apply', () => {
|
||||
let configProxy;
|
||||
beforeEach(() => {
|
||||
configProxy = builder.apply([]);
|
||||
});
|
||||
it('should return configuration proxy', () => {
|
||||
const configProxy = builder.apply([]);
|
||||
const metatype = (MiddlewareBuilder as any).ConfigProxy;
|
||||
expect(configProxy instanceof metatype).to.be.true;
|
||||
});
|
||||
|
||||
describe('configuration proxy', () => {
|
||||
describe('when "forRoutes()" called', () => {
|
||||
let configProxy: MiddlewareConfigProxy;
|
||||
beforeEach(() => {
|
||||
configProxy = builder.apply([]);
|
||||
});
|
||||
@Controller('path')
|
||||
class Test {
|
||||
@Get('route')
|
||||
@@ -56,7 +40,6 @@ describe('MiddlewareBuilder', () => {
|
||||
public getAllVersioned() {}
|
||||
}
|
||||
const route = { path: '/test', method: RequestMethod.GET };
|
||||
|
||||
it('should store configuration passed as argument', () => {
|
||||
configProxy.forRoutes(route, Test);
|
||||
|
||||
@@ -81,106 +64,6 @@ describe('MiddlewareBuilder', () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
@Controller('users')
|
||||
class UsersController {
|
||||
@Head('rsvp')
|
||||
hRsvp() {}
|
||||
|
||||
@Options('rsvp')
|
||||
oRsvp() {}
|
||||
|
||||
@Get('rsvp')
|
||||
gRsvp() {}
|
||||
|
||||
@Post('rsvp')
|
||||
pRsvp() {}
|
||||
|
||||
@Put('rsvp')
|
||||
puRsvp() {}
|
||||
|
||||
@Patch('rsvp')
|
||||
ptRsvp() {}
|
||||
|
||||
@Delete('rsvp')
|
||||
dRsvp() {}
|
||||
|
||||
@Post()
|
||||
create() {}
|
||||
|
||||
@Get()
|
||||
findAll() {}
|
||||
|
||||
@Get(':id')
|
||||
findOne() {}
|
||||
|
||||
@Patch(':id')
|
||||
update() {}
|
||||
|
||||
@Delete(':id')
|
||||
remove() {}
|
||||
}
|
||||
|
||||
it('should remove overlapping routes', () => {
|
||||
configProxy.forRoutes(UsersController);
|
||||
|
||||
expect(builder.build()).to.deep.equal([
|
||||
{
|
||||
middleware: [],
|
||||
forRoutes: [
|
||||
{
|
||||
method: RequestMethod.HEAD,
|
||||
path: '/users/rsvp',
|
||||
},
|
||||
{
|
||||
method: RequestMethod.OPTIONS,
|
||||
path: '/users/rsvp',
|
||||
},
|
||||
{
|
||||
method: RequestMethod.POST,
|
||||
path: '/users/rsvp',
|
||||
},
|
||||
{
|
||||
method: RequestMethod.PUT,
|
||||
path: '/users/rsvp',
|
||||
},
|
||||
{
|
||||
method: RequestMethod.POST,
|
||||
path: '/users/',
|
||||
},
|
||||
{
|
||||
method: RequestMethod.GET,
|
||||
path: '/users/',
|
||||
},
|
||||
{
|
||||
method: RequestMethod.GET,
|
||||
path: '/users/:id',
|
||||
},
|
||||
{
|
||||
method: RequestMethod.PATCH,
|
||||
path: '/users/:id',
|
||||
},
|
||||
{
|
||||
method: RequestMethod.DELETE,
|
||||
path: '/users/:id',
|
||||
},
|
||||
// Overlapping:
|
||||
// {
|
||||
// method: RequestMethod.GET,
|
||||
// path: '/users/rsvp',
|
||||
// },
|
||||
// {
|
||||
// method: RequestMethod.PATCH,
|
||||
// path: '/users/rsvp',
|
||||
// },
|
||||
// {
|
||||
// method: RequestMethod.DELETE,
|
||||
// path: '/users/rsvp',
|
||||
// },
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Version } from '../../../common';
|
||||
import { MiddlewareConfiguration } from '../../../common/interfaces';
|
||||
import { expect } from 'chai';
|
||||
import { Version, VersioningType } from '../../../common';
|
||||
import { Controller } from '../../../common/decorators/core/controller.decorator';
|
||||
import {
|
||||
Get,
|
||||
RequestMapping,
|
||||
} from '../../../common/decorators/http/request-mapping.decorator';
|
||||
import { RequestMethod } from '../../../common/enums/request-method.enum';
|
||||
import { MiddlewareConfiguration } from '../../../common/interfaces';
|
||||
import { ApplicationConfig } from '../../application-config';
|
||||
import { NestContainer } from '../../injector/container';
|
||||
import { RoutesMapper } from '../../middleware/routes-mapper';
|
||||
|
||||
@@ -27,9 +26,7 @@ describe('RoutesMapper', () => {
|
||||
|
||||
let mapper: RoutesMapper;
|
||||
beforeEach(() => {
|
||||
const appConfig = new ApplicationConfig();
|
||||
appConfig.enableVersioning({ type: VersioningType.URI });
|
||||
mapper = new RoutesMapper(new NestContainer(), appConfig);
|
||||
mapper = new RoutesMapper(new NestContainer());
|
||||
});
|
||||
|
||||
it('should map @Controller() to "ControllerMetadata" in forRoutes', () => {
|
||||
@@ -84,47 +81,4 @@ describe('RoutesMapper', () => {
|
||||
{ path: '/test2/another', method: RequestMethod.DELETE },
|
||||
]);
|
||||
});
|
||||
|
||||
@Controller({
|
||||
version: '1',
|
||||
path: 'versioned',
|
||||
})
|
||||
class VersionedController {
|
||||
@Get()
|
||||
hello() {
|
||||
return 'Hello from "VersionedController"!';
|
||||
}
|
||||
|
||||
@Version('2')
|
||||
@Get('/override')
|
||||
override() {
|
||||
return 'Hello from "VersionedController"!';
|
||||
}
|
||||
}
|
||||
|
||||
@Controller({
|
||||
version: ['1', '2'],
|
||||
})
|
||||
class MultipleVersionController {
|
||||
@Get('multiple')
|
||||
multiple() {
|
||||
return 'Multiple Versions 1 or 2';
|
||||
}
|
||||
}
|
||||
|
||||
it('should map a versioned controller to the corresponding route info objects (single version)', () => {
|
||||
expect(mapper.mapRouteToRouteInfo(VersionedController)).to.deep.equal([
|
||||
{ path: '/versioned/', version: '1', method: RequestMethod.GET },
|
||||
{ path: '/versioned/override', version: '2', method: RequestMethod.GET },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should map a versioned controller to the corresponding route info objects (multiple versions)', () => {
|
||||
expect(mapper.mapRouteToRouteInfo(MultipleVersionController)).to.deep.equal(
|
||||
[
|
||||
{ path: '/multiple', version: '1', method: RequestMethod.GET },
|
||||
{ path: '/multiple', version: '2', method: RequestMethod.GET },
|
||||
],
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -136,8 +136,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -163,13 +163,12 @@ export class ClientKafka extends ClientProxy {
|
||||
}
|
||||
|
||||
const consumerSubscribeOptions = this.options.subscribe || {};
|
||||
|
||||
if (this.responsePatterns.length > 0) {
|
||||
await this.consumer.subscribe({
|
||||
const subscribeTo = async (responsePattern: string) =>
|
||||
this.consumer.subscribe({
|
||||
topic: responsePattern,
|
||||
...consumerSubscribeOptions,
|
||||
topics: this.responsePatterns,
|
||||
});
|
||||
}
|
||||
await Promise.all(this.responsePatterns.map(subscribeTo));
|
||||
|
||||
await this.consumer.run(
|
||||
Object.assign(this.options.run || {}, {
|
||||
@@ -300,12 +299,12 @@ export class ClientKafka extends ClientProxy {
|
||||
const consumerAssignments: { [key: string]: number } = {};
|
||||
|
||||
// only need to set the minimum
|
||||
Object.keys(data.payload.memberAssignment).forEach(topic => {
|
||||
const memberPartitions = data.payload.memberAssignment[topic];
|
||||
Object.keys(data.payload.memberAssignment).forEach(memberId => {
|
||||
const minimumPartition = Math.min(
|
||||
...data.payload.memberAssignment[memberId],
|
||||
);
|
||||
|
||||
if (memberPartitions.length) {
|
||||
consumerAssignments[topic] = Math.min(...memberPartitions);
|
||||
}
|
||||
consumerAssignments[memberId] = minimumPartition;
|
||||
});
|
||||
|
||||
this.consumerAssignments = consumerAssignments;
|
||||
|
||||
@@ -240,7 +240,7 @@ export interface KafkaOptions {
|
||||
client?: KafkaConfig;
|
||||
consumer?: ConsumerConfig;
|
||||
run?: Omit<ConsumerRunConfig, 'eachBatch' | 'eachMessage'>;
|
||||
subscribe?: Omit<ConsumerSubscribeTopics, 'topics'>;
|
||||
subscribe?: Omit<ConsumerSubscribeTopics, 'topic'>;
|
||||
producer?: ProducerConfig;
|
||||
send?: Omit<ProducerRecord, 'topic' | 'messages'>;
|
||||
serializer?: Serializer;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/microservices",
|
||||
"version": "10.0.4",
|
||||
"version": "9.4.2",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@microservices)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
@@ -19,17 +19,17 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"iterare": "1.2.1",
|
||||
"tslib": "2.6.0"
|
||||
"tslib": "2.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/common": "10.0.4",
|
||||
"@nestjs/core": "10.0.4"
|
||||
"@nestjs/common": "9.4.2",
|
||||
"@nestjs/core": "9.4.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@grpc/grpc-js": "*",
|
||||
"@nestjs/common": "^10.0.0",
|
||||
"@nestjs/core": "^10.0.0",
|
||||
"@nestjs/websockets": "^10.0.0",
|
||||
"@nestjs/common": "^9.0.0",
|
||||
"@nestjs/core": "^9.0.0",
|
||||
"@nestjs/websockets": "^9.0.0",
|
||||
"amqp-connection-manager": "*",
|
||||
"amqplib": "*",
|
||||
"cache-manager": "*",
|
||||
|
||||
@@ -122,13 +122,12 @@ export class ServerKafka extends Server implements CustomTransportStrategy {
|
||||
public async bindEvents(consumer: Consumer) {
|
||||
const registeredPatterns = [...this.messageHandlers.keys()];
|
||||
const consumerSubscribeOptions = this.options.subscribe || {};
|
||||
|
||||
if (registeredPatterns.length > 0) {
|
||||
await this.consumer.subscribe({
|
||||
const subscribeToPattern = async (pattern: string) =>
|
||||
consumer.subscribe({
|
||||
topic: pattern,
|
||||
...consumerSubscribeOptions,
|
||||
topics: registeredPatterns,
|
||||
});
|
||||
}
|
||||
await Promise.all(registeredPatterns.map(subscribeToPattern));
|
||||
|
||||
const consumerRunOptions = Object.assign(this.options.run || {}, {
|
||||
eachMessage: this.getMessageHandler(),
|
||||
|
||||
@@ -67,7 +67,6 @@ export class ServerMqtt extends Server implements CustomTransportStrategy {
|
||||
|
||||
public bindEvents(mqttClient: MqttClient) {
|
||||
mqttClient.on(MESSAGE_EVENT, this.getMessageHandler(mqttClient).bind(this));
|
||||
|
||||
const registeredPatterns = [...this.messageHandlers.keys()];
|
||||
registeredPatterns.forEach(pattern => {
|
||||
const { isEventHandler } = this.messageHandlers.get(pattern);
|
||||
|
||||
@@ -395,34 +395,6 @@ describe('ClientKafka', () => {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('should not update consumer assignments if there are no partitions assigned to consumer', async () => {
|
||||
await client.connect();
|
||||
|
||||
const consumerAssignments: ConsumerGroupJoinEvent = {
|
||||
id: 'id',
|
||||
type: 'type',
|
||||
timestamp: 1234567890,
|
||||
payload: {
|
||||
duration: 20,
|
||||
groupId: 'group-id',
|
||||
isLeader: true,
|
||||
leaderId: 'member-1',
|
||||
groupProtocol: 'RoundRobin',
|
||||
memberId: 'member-1',
|
||||
memberAssignment: {
|
||||
'topic-a': [],
|
||||
'topic-b': [3, 4, 5],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
client['setConsumerAssignments'](consumerAssignments);
|
||||
|
||||
expect(client['consumerAssignments']).to.deep.eq({
|
||||
'topic-b': 3,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('bindTopics', () => {
|
||||
@@ -435,7 +407,7 @@ describe('ClientKafka', () => {
|
||||
expect(subscribe.calledOnce).to.be.true;
|
||||
expect(
|
||||
subscribe.calledWith({
|
||||
topics: [replyTopic],
|
||||
topic: replyTopic,
|
||||
}),
|
||||
).to.be.true;
|
||||
expect(run.calledOnce).to.be.true;
|
||||
@@ -452,7 +424,7 @@ describe('ClientKafka', () => {
|
||||
expect(subscribe.calledOnce).to.be.true;
|
||||
expect(
|
||||
subscribe.calledWith({
|
||||
topics: [replyTopic],
|
||||
topic: replyTopic,
|
||||
fromBeginning: true,
|
||||
}),
|
||||
).to.be.true;
|
||||
|
||||
@@ -190,7 +190,7 @@ describe('ServerKafka', () => {
|
||||
expect(subscribe.called).to.be.true;
|
||||
expect(
|
||||
subscribe.calledWith({
|
||||
topics: [pattern],
|
||||
topic: pattern,
|
||||
}),
|
||||
).to.be.true;
|
||||
|
||||
@@ -214,7 +214,7 @@ describe('ServerKafka', () => {
|
||||
expect(subscribe.called).to.be.true;
|
||||
expect(
|
||||
subscribe.calledWith({
|
||||
topics: [pattern],
|
||||
topic: pattern,
|
||||
fromBeginning: true,
|
||||
}),
|
||||
).to.be.true;
|
||||
|
||||
@@ -136,8 +136,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -16,11 +16,6 @@ import { transformException } from '../multer/multer.utils';
|
||||
|
||||
type MulterInstance = any;
|
||||
|
||||
/**
|
||||
* @param localOptions
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export function AnyFilesInterceptor(
|
||||
localOptions?: MulterOptions,
|
||||
): Type<NestInterceptor> {
|
||||
|
||||
@@ -19,11 +19,6 @@ import { transformException } from '../multer/multer.utils';
|
||||
|
||||
type MulterInstance = any;
|
||||
|
||||
/**
|
||||
* @param uploadFields
|
||||
* @param localOptions
|
||||
* @publicApi
|
||||
*/
|
||||
export function FileFieldsInterceptor(
|
||||
uploadFields: MulterField[],
|
||||
localOptions?: MulterOptions,
|
||||
|
||||
@@ -16,12 +16,6 @@ import { transformException } from '../multer/multer.utils';
|
||||
|
||||
type MulterInstance = any;
|
||||
|
||||
/**
|
||||
* @param fieldName
|
||||
* @param localOptions
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export function FileInterceptor(
|
||||
fieldName: string,
|
||||
localOptions?: MulterOptions,
|
||||
|
||||
@@ -16,14 +16,6 @@ import { transformException } from '../multer/multer.utils';
|
||||
|
||||
type MulterInstance = any;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param fieldName
|
||||
* @param maxCount
|
||||
* @param localOptions
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export function FilesInterceptor(
|
||||
fieldName: string,
|
||||
maxCount?: number,
|
||||
|
||||
@@ -2,4 +2,3 @@ export * from './any-files.interceptor';
|
||||
export * from './file-fields.interceptor';
|
||||
export * from './file.interceptor';
|
||||
export * from './files.interceptor';
|
||||
export * from './no-files.interceptor';
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
import {
|
||||
CallHandler,
|
||||
ExecutionContext,
|
||||
Inject,
|
||||
mixin,
|
||||
NestInterceptor,
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param localOptions
|
||||
* @publicApi
|
||||
*/
|
||||
export function NoFilesInterceptor(
|
||||
localOptions?: MulterOptions,
|
||||
): Type<NestInterceptor> {
|
||||
class MixinInterceptor implements NestInterceptor {
|
||||
protected multer: MulterInstance;
|
||||
|
||||
constructor(
|
||||
@Optional()
|
||||
@Inject(MULTER_MODULE_OPTIONS)
|
||||
options: MulterModuleOptions = {},
|
||||
) {
|
||||
this.multer = (multer as any)({
|
||||
...options,
|
||||
...localOptions,
|
||||
});
|
||||
}
|
||||
|
||||
async intercept(
|
||||
context: ExecutionContext,
|
||||
next: CallHandler,
|
||||
): Promise<Observable<any>> {
|
||||
const ctx = context.switchToHttp();
|
||||
|
||||
await new Promise<void>((resolve, reject) =>
|
||||
this.multer.none()(ctx.getRequest(), ctx.getResponse(), (err: any) => {
|
||||
if (err) {
|
||||
const error = transformException(err);
|
||||
return reject(error);
|
||||
}
|
||||
resolve();
|
||||
}),
|
||||
);
|
||||
return next.handle();
|
||||
}
|
||||
}
|
||||
const Interceptor = mixin(MixinInterceptor);
|
||||
return Interceptor;
|
||||
}
|
||||
@@ -3,17 +3,10 @@ import { MulterOptions } from './multer-options.interface';
|
||||
|
||||
export type MulterModuleOptions = MulterOptions;
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
*/
|
||||
export interface MulterOptionsFactory {
|
||||
createMulterOptions(): Promise<MulterModuleOptions> | MulterModuleOptions;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
*/
|
||||
export interface MulterModuleAsyncOptions
|
||||
extends Pick<ModuleMetadata, 'imports'> {
|
||||
useExisting?: Type<MulterOptionsFactory>;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/**
|
||||
* @see https://github.com/expressjs/multer
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export interface MulterOptions {
|
||||
dest?: string;
|
||||
@@ -57,9 +55,6 @@ export interface MulterOptions {
|
||||
): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
*/
|
||||
export interface MulterField {
|
||||
/** The field name. */
|
||||
name: string;
|
||||
|
||||
@@ -8,9 +8,6 @@ import {
|
||||
} from './interfaces/files-upload-module.interface';
|
||||
import { MULTER_MODULE_ID } from './multer.constants';
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
*/
|
||||
@Module({})
|
||||
export class MulterModule {
|
||||
static register(options: MulterModuleOptions = {}): DynamicModule {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/platform-express",
|
||||
"version": "10.0.4",
|
||||
"version": "9.4.2",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@platform-express)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
@@ -22,14 +22,14 @@
|
||||
"cors": "2.8.5",
|
||||
"express": "4.18.2",
|
||||
"multer": "1.4.4-lts.1",
|
||||
"tslib": "2.6.0"
|
||||
"tslib": "2.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/common": "10.0.4",
|
||||
"@nestjs/core": "10.0.4"
|
||||
"@nestjs/common": "9.4.2",
|
||||
"@nestjs/core": "9.4.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^10.0.0",
|
||||
"@nestjs/core": "^10.0.0"
|
||||
"@nestjs/common": "^9.0.0",
|
||||
"@nestjs/core": "^9.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
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 { NoFilesInterceptor } from '../../../multer/interceptors/no-files.interceptor';
|
||||
|
||||
describe('NoFilesInterceptor', () => {
|
||||
it('should return metatype with expected structure', async () => {
|
||||
const targetClass = NoFilesInterceptor();
|
||||
expect(targetClass.prototype.intercept).to.not.be.undefined;
|
||||
});
|
||||
describe('intercept', () => {
|
||||
let handler: CallHandler;
|
||||
beforeEach(() => {
|
||||
handler = {
|
||||
handle: () => of('test'),
|
||||
};
|
||||
});
|
||||
it('should call none() with expected params', async () => {
|
||||
const target = new (NoFilesInterceptor())();
|
||||
|
||||
const callback = (req, res, next) => next();
|
||||
const noneSpy = sinon
|
||||
.stub((target as any).multer, 'none')
|
||||
.returns(callback);
|
||||
|
||||
await target.intercept(new ExecutionContextHost([]), handler);
|
||||
|
||||
expect(noneSpy.called).to.be.true;
|
||||
});
|
||||
it('should transform exception', async () => {
|
||||
const target = new (NoFilesInterceptor())();
|
||||
const err = {};
|
||||
const callback = (req, res, next) => next(err);
|
||||
(target as any).multer = {
|
||||
none: () => callback,
|
||||
};
|
||||
(target.intercept(new ExecutionContextHost([]), handler) as any).catch(
|
||||
error => expect(error).to.not.be.undefined,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -136,8 +136,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/platform-fastify",
|
||||
"version": "10.0.4",
|
||||
"version": "9.4.2",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@platform-fastify)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
@@ -18,19 +18,19 @@
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fastify/cors": "8.3.0",
|
||||
"@fastify/cors": "8.2.1",
|
||||
"@fastify/formbody": "7.4.0",
|
||||
"@fastify/middie": "8.3.0",
|
||||
"fastify": "4.18.0",
|
||||
"light-my-request": "5.10.0",
|
||||
"fastify": "4.17.0",
|
||||
"light-my-request": "5.9.1",
|
||||
"path-to-regexp": "3.2.0",
|
||||
"tslib": "2.6.0"
|
||||
"tslib": "2.5.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@fastify/static": "^6.0.0",
|
||||
"@fastify/view": "^7.0.0",
|
||||
"@nestjs/common": "^10.0.0",
|
||||
"@nestjs/core": "^10.0.0"
|
||||
"@nestjs/common": "^9.0.0",
|
||||
"@nestjs/core": "^9.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@fastify/static": {
|
||||
|
||||
@@ -136,8 +136,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/platform-socket.io",
|
||||
"version": "10.0.4",
|
||||
"version": "9.4.2",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@platform-socket.io)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
@@ -18,12 +18,12 @@
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"socket.io": "4.7.0",
|
||||
"tslib": "2.6.0"
|
||||
"socket.io": "4.6.1",
|
||||
"tslib": "2.5.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^10.0.0",
|
||||
"@nestjs/websockets": "^10.0.0",
|
||||
"@nestjs/common": "^9.0.0",
|
||||
"@nestjs/websockets": "^9.0.0",
|
||||
"rxjs": "^7.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,8 +136,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/platform-ws",
|
||||
"version": "10.0.4",
|
||||
"version": "9.4.2",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@platform-ws)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
@@ -18,12 +18,12 @@
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": "2.6.0",
|
||||
"tslib": "2.5.2",
|
||||
"ws": "8.13.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^10.0.0",
|
||||
"@nestjs/websockets": "^10.0.0",
|
||||
"@nestjs/common": "^9.0.0",
|
||||
"@nestjs/websockets": "^9.0.0",
|
||||
"rxjs": "^7.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,8 +136,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/testing",
|
||||
"version": "10.0.4",
|
||||
"version": "9.4.2",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@testing)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
@@ -18,13 +18,13 @@
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": "2.6.0"
|
||||
"tslib": "2.5.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^10.0.0",
|
||||
"@nestjs/core": "^10.0.0",
|
||||
"@nestjs/microservices": "^10.0.0",
|
||||
"@nestjs/platform-express": "^10.0.0"
|
||||
"@nestjs/common": "^9.0.0",
|
||||
"@nestjs/core": "^9.0.0",
|
||||
"@nestjs/microservices": "^9.0.0",
|
||||
"@nestjs/platform-express": "^9.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@nestjs/microservices": {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"useUnknownInCatchVariables": false,
|
||||
"target": "ES2021",
|
||||
"target": "es2017",
|
||||
"sourceMap": false,
|
||||
"allowJs": false,
|
||||
"strict": true,
|
||||
|
||||
@@ -136,8 +136,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.mobilefactory.jp/" target="_blank"><img src="https://nestjs.com/img/mobilefactory-logo.png" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
InterceptorsContextCreator,
|
||||
} from '@nestjs/core/interceptors';
|
||||
import { PipesConsumer, PipesContextCreator } from '@nestjs/core/pipes';
|
||||
import { MESSAGE_METADATA, PARAM_ARGS_METADATA } from '../constants';
|
||||
import { PARAM_ARGS_METADATA } from '../constants';
|
||||
import { WsException } from '../errors/ws-exception';
|
||||
import { WsParamsFactory } from '../factories/ws-params-factory';
|
||||
import { ExceptionFiltersContext } from './exception-filters-context';
|
||||
@@ -66,6 +66,7 @@ export class WsContextCreator {
|
||||
methodName,
|
||||
contextType,
|
||||
);
|
||||
|
||||
const exceptionHandler = this.exceptionFiltersContext.create(
|
||||
instance,
|
||||
callback,
|
||||
@@ -109,8 +110,6 @@ export class WsContextCreator {
|
||||
};
|
||||
|
||||
return this.wsProxy.create(async (...args: unknown[]) => {
|
||||
args.push(this.reflectCallbackPattern(callback));
|
||||
|
||||
const initialArgs = this.contextUtils.createNullArray(argsLength);
|
||||
fnCanActivate && (await fnCanActivate(args));
|
||||
|
||||
@@ -132,10 +131,6 @@ export class WsContextCreator {
|
||||
return Reflect.getMetadata(PARAMTYPES_METADATA, instance, callback.name);
|
||||
}
|
||||
|
||||
public reflectCallbackPattern(callback: (...args: any[]) => any): string {
|
||||
return Reflect.getMetadata(MESSAGE_METADATA, callback);
|
||||
}
|
||||
|
||||
public createGuardsFn<TContext extends string = ContextType>(
|
||||
guards: any[],
|
||||
instance: Controller,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.int
|
||||
|
||||
/**
|
||||
* External interface
|
||||
* @see https://github.com/socketio/socket.io/blob/master/lib/index.ts
|
||||
* @see https://github.com/socketio/socket.io/blob/master/lib/index.ts
|
||||
* @publicApi
|
||||
*/
|
||||
export interface GatewayMetadata {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/websockets",
|
||||
"version": "10.0.4",
|
||||
"version": "9.4.2",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@websockets)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"license": "MIT",
|
||||
@@ -15,16 +15,16 @@
|
||||
"dependencies": {
|
||||
"iterare": "1.2.1",
|
||||
"object-hash": "3.0.0",
|
||||
"tslib": "2.6.0"
|
||||
"tslib": "2.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/common": "10.0.4",
|
||||
"@nestjs/core": "10.0.4"
|
||||
"@nestjs/common": "9.4.2",
|
||||
"@nestjs/core": "9.4.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nestjs/common": "^10.0.0",
|
||||
"@nestjs/core": "^10.0.0",
|
||||
"@nestjs/platform-socket.io": "^10.0.0",
|
||||
"@nestjs/common": "^9.0.0",
|
||||
"@nestjs/core": "^9.0.0",
|
||||
"@nestjs/platform-socket.io": "^9.0.0",
|
||||
"reflect-metadata": "^0.1.12",
|
||||
"rxjs": "^7.1.0"
|
||||
},
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
|
||||
[circleci-url]: https://circleci.com/gh/nestjs/nest
|
||||
|
||||
<p align="center">用于构建高效且可扩展的服务器端应用程序的渐进式 <a href="http://nodejs.cn" target="blank">Node.js</a> 框架,深受 <a href="https://angular.cn" target="_blank">Angular</a> 的启发。</p>
|
||||
|
||||
<p align="center">用于构建高效且可扩展的服务器端应用程序的渐进式 <a href="http://nodejs.cn" target="blank">Node.js</a> 框架,深受 <a href="https://angular.cn" target="_blank">Angular</a> 的启发。</p>
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
|
||||
@@ -46,7 +46,7 @@ QQ群:277386223
|
||||
QQ群:336289049
|
||||
QQ群:489719517
|
||||
|
||||
> 注意:这个交流群不是 NestJS 官方支持和维护的,只是为了方便国内开发者交流而建立的。
|
||||
> 注意:这个交流群不是 NestJS 官方支持和维护的,只是为了方便国内开发者交流而建立的。
|
||||
> (Note: This channel is not officially supported and maintained by the NestJS org members.)
|
||||
|
||||
## 赞助商
|
||||
|
||||
5593
sample/01-cats-app/package-lock.json
generated
5593
sample/01-cats-app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -19,36 +19,36 @@
|
||||
"test:e2e": "jest --config ./e2e/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "10.0.3",
|
||||
"@nestjs/core": "10.0.3",
|
||||
"@nestjs/platform-express": "10.0.3",
|
||||
"@nestjs/common": "9.3.12",
|
||||
"@nestjs/core": "9.3.12",
|
||||
"@nestjs/platform-express": "9.3.12",
|
||||
"class-transformer": "0.5.1",
|
||||
"class-validator": "0.14.0",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"rimraf": "5.0.1",
|
||||
"rxjs": "7.8.1"
|
||||
"rimraf": "4.4.1",
|
||||
"rxjs": "7.5.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "10.0.5",
|
||||
"@nestjs/schematics": "10.0.1",
|
||||
"@nestjs/testing": "10.0.3",
|
||||
"@types/express": "4.17.17",
|
||||
"@types/jest": "29.5.2",
|
||||
"@types/node": "20.3.1",
|
||||
"@nestjs/cli": "9.4.0",
|
||||
"@nestjs/schematics": "9.0.4",
|
||||
"@nestjs/testing": "9.3.12",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/jest": "28.1.4",
|
||||
"@types/node": "18.0.3",
|
||||
"@types/supertest": "2.0.12",
|
||||
"jest": "29.5.0",
|
||||
"prettier": "2.8.8",
|
||||
"supertest": "6.3.3",
|
||||
"ts-jest": "29.1.0",
|
||||
"ts-loader": "9.4.3",
|
||||
"ts-node": "10.9.1",
|
||||
"jest": "28.1.2",
|
||||
"prettier": "2.7.1",
|
||||
"supertest": "6.2.4",
|
||||
"ts-jest": "28.0.8",
|
||||
"ts-loader": "9.3.1",
|
||||
"ts-node": "10.8.2",
|
||||
"tsconfig-paths": "4.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.60.0",
|
||||
"@typescript-eslint/parser": "5.60.0",
|
||||
"eslint": "8.42.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.56.0",
|
||||
"@typescript-eslint/parser": "5.56.0",
|
||||
"eslint": "8.19.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"typescript": "5.1.3"
|
||||
"eslint-plugin-import": "2.26.0",
|
||||
"typescript": "4.9.5"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
|
||||
5911
sample/02-gateways/package-lock.json
generated
5911
sample/02-gateways/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -19,42 +19,42 @@
|
||||
"test:e2e": "jest --config ./e2e/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nestjs/common": "10.0.3",
|
||||
"@nestjs/core": "10.0.3",
|
||||
"@nestjs/platform-express": "10.0.3",
|
||||
"@nestjs/platform-socket.io": "10.0.3",
|
||||
"@nestjs/websockets": "10.0.3",
|
||||
"@socket.io/redis-adapter": "8.2.1",
|
||||
"@nestjs/common": "9.3.12",
|
||||
"@nestjs/core": "9.3.12",
|
||||
"@nestjs/platform-express": "9.3.12",
|
||||
"@nestjs/platform-socket.io": "9.3.12",
|
||||
"@nestjs/websockets": "9.3.12",
|
||||
"@socket.io/redis-adapter": "7.2.0",
|
||||
"class-transformer": "0.5.1",
|
||||
"class-validator": "0.14.0",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"rimraf": "5.0.1",
|
||||
"rxjs": "7.8.1",
|
||||
"socket.io": "4.7.0"
|
||||
"rimraf": "4.4.1",
|
||||
"rxjs": "7.5.5",
|
||||
"socket.io": "4.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "10.0.5",
|
||||
"@nestjs/schematics": "10.0.1",
|
||||
"@nestjs/testing": "10.0.3",
|
||||
"@types/express": "4.17.17",
|
||||
"@types/jest": "29.5.2",
|
||||
"@types/node": "20.3.1",
|
||||
"@nestjs/cli": "9.4.0",
|
||||
"@nestjs/schematics": "9.0.4",
|
||||
"@nestjs/testing": "9.3.12",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/jest": "28.1.4",
|
||||
"@types/node": "18.0.3",
|
||||
"@types/supertest": "2.0.12",
|
||||
"@types/ws": "8.5.5",
|
||||
"@typescript-eslint/eslint-plugin": "5.60.0",
|
||||
"@typescript-eslint/parser": "5.60.0",
|
||||
"eslint": "8.42.0",
|
||||
"@types/ws": "8.5.3",
|
||||
"@typescript-eslint/eslint-plugin": "5.56.0",
|
||||
"@typescript-eslint/parser": "5.56.0",
|
||||
"eslint": "8.19.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"jest": "29.5.0",
|
||||
"prettier": "2.8.8",
|
||||
"redis": "4.6.7",
|
||||
"supertest": "6.3.3",
|
||||
"ts-jest": "29.1.0",
|
||||
"ts-loader": "9.4.3",
|
||||
"ts-node": "10.9.1",
|
||||
"eslint-plugin-import": "2.26.0",
|
||||
"jest": "28.1.2",
|
||||
"prettier": "2.7.1",
|
||||
"redis": "4.6.5",
|
||||
"supertest": "6.2.4",
|
||||
"ts-jest": "28.0.8",
|
||||
"ts-loader": "9.3.1",
|
||||
"ts-node": "10.8.2",
|
||||
"tsconfig-paths": "4.2.0",
|
||||
"typescript": "5.1.3"
|
||||
"typescript": "4.9.5"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
|
||||
5629
sample/03-microservices/package-lock.json
generated
5629
sample/03-microservices/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user