Skip to content

Commit f96b2a8

Browse files
Merge pull request nestjs#1161 from nestjs/refactor/microservices
refactor(microservices) refactor, improvements, use es6 map
2 parents ead8d55 + 4ec8e34 commit f96b2a8

61 files changed

Lines changed: 504 additions & 168 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

integration/microservices/e2e/sum-nats.spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,15 @@ describe('NATS transport', () => {
7373
.expect(200, 'true');
7474
});
7575

76+
it(`/GET (exception)`, () => {
77+
return request(server)
78+
.get('/exception')
79+
.expect(200, {
80+
message: 'test',
81+
status: 'error',
82+
});
83+
});
84+
7685
afterEach(async () => {
7786
await app.close();
7887
});

integration/microservices/src/nats/nats.controller.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
import { Body, Controller, HttpCode, Post, Query } from '@nestjs/common';
1+
import { Body, Controller, Get, HttpCode, Post, Query } from '@nestjs/common';
22
import {
33
Client,
44
ClientProxy,
55
MessagePattern,
6+
RpcException,
67
Transport,
78
} from '@nestjs/microservices';
8-
import { from, Observable, of } from 'rxjs';
9-
import { scan } from 'rxjs/operators';
9+
import { from, Observable, of, throwError } from 'rxjs';
10+
import { catchError, scan } from 'rxjs/operators';
1011

1112
@Controller()
1213
export class NatsController {
@@ -71,4 +72,16 @@ export class NatsController {
7172
streaming(data: number[]): Observable<number> {
7273
return from(data);
7374
}
75+
76+
@Get('exception')
77+
async getError() {
78+
return await this.client
79+
.send<number>('exception', {})
80+
.pipe(catchError(err => of(err)));
81+
}
82+
83+
@MessagePattern('exception')
84+
throwError(): Observable<number> {
85+
return throwError(new RpcException('test'));
86+
}
7487
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { INestApplication } from '@nestjs/common';
2+
import { Test } from '@nestjs/testing';
3+
import { expect } from 'chai';
4+
import * as io from 'socket.io-client';
5+
import { ErrorGateway } from '../src/error.gateway';
6+
7+
describe('ErrorGateway', () => {
8+
let app: INestApplication;
9+
10+
beforeEach(async () => {
11+
const testingModule = await Test.createTestingModule({
12+
providers: [ErrorGateway],
13+
}).compile();
14+
app = await testingModule.createNestApplication();
15+
await app.listenAsync(3000);
16+
});
17+
18+
it(`should handle error`, async () => {
19+
const ws = io.connect('http://localhost:8080');
20+
ws.emit('push', {
21+
test: 'test',
22+
});
23+
await new Promise(resolve =>
24+
ws.on('exception', data => {
25+
expect(data).to.be.eql({
26+
status: 'error',
27+
message: 'test',
28+
});
29+
resolve();
30+
}),
31+
);
32+
});
33+
34+
afterEach(() => app.close());
35+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import {
2+
SubscribeMessage,
3+
WebSocketGateway,
4+
WsException,
5+
} from '@nestjs/websockets';
6+
import { throwError } from 'rxjs';
7+
8+
@WebSocketGateway(8080)
9+
export class ErrorGateway {
10+
@SubscribeMessage('push')
11+
onPush(client, data) {
12+
return throwError(new WsException('test'));
13+
}
14+
}

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
"packages": [
44
"packages/*"
55
],
6-
"version": "5.4.1"
6+
"version": "5.5.0"
77
}

packages/common/cache/cache.module.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ export class CacheModule {
2424
return {
2525
module: CacheModule,
2626
imports: options.imports,
27-
providers: this.createAsyncProviders(options),
27+
providers: [
28+
...this.createAsyncProviders(options),
29+
...(options.extraProviders || []),
30+
],
2831
};
2932
}
3033

@@ -55,7 +58,8 @@ export class CacheModule {
5558
}
5659
return {
5760
provide: CACHE_MODULE_OPTIONS,
58-
useFactory: async (optionsFactory: CacheOptionsFactory) => optionsFactory.createCacheOptions(),
61+
useFactory: async (optionsFactory: CacheOptionsFactory) =>
62+
optionsFactory.createCacheOptions(),
5963
inject: [options.useExisting || options.useClass],
6064
};
6165
}

packages/common/cache/interfaces/cache-module.interface.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ModuleMetadata, Type } from '../../interfaces';
1+
import { ModuleMetadata, Provider, Type } from '../../interfaces';
22
import { CacheManagerOptions } from './cache-manager.interface';
33

44
export interface CacheModuleOptions extends CacheManagerOptions {
@@ -17,4 +17,5 @@ export interface CacheModuleAsyncOptions
1717
...args: any[]
1818
) => Promise<CacheModuleOptions> | CacheModuleOptions;
1919
inject?: any[];
20+
extraProviders?: Provider[];
2021
}

packages/common/decorators/core/inject.decorator.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,17 @@ export function Inject<T = any>(token?: T) {
1515
token && isFunction(token) ? ((token as any) as Function).name : token;
1616

1717
if (!isUndefined(index)) {
18-
const dependencies =
18+
let dependencies =
1919
Reflect.getMetadata(SELF_DECLARED_DEPS_METADATA, target) || [];
2020

21-
dependencies.push({ index, param: type });
21+
dependencies = [...dependencies, { index, param: type }];
2222
Reflect.defineMetadata(SELF_DECLARED_DEPS_METADATA, dependencies, target);
2323
return;
2424
}
25-
const properties =
25+
let properties =
2626
Reflect.getMetadata(PROPERTY_DEPS_METADATA, target.constructor) || [];
2727

28-
properties.push({ key, type });
28+
properties = [...properties, { key, type }];
2929
Reflect.defineMetadata(
3030
PROPERTY_DEPS_METADATA,
3131
properties,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export const AXIOS_INSTANCE_TOKEN = 'AXIOS_INSTANCE_TOKEN';
22
export const HTTP_MODULE_ID = 'HTTP_MODULE_ID';
3+
export const HTTP_MODULE_OPTIONS = 'HTTP_MODULE_OPTIONS';

packages/common/http/http.module.ts

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1-
import Axios, { AxiosRequestConfig } from 'axios';
1+
import Axios from 'axios';
22
import { Module } from '../decorators/modules/module.decorator';
3-
import { DynamicModule } from '../interfaces';
3+
import { DynamicModule, Provider } from '../interfaces';
44
import { randomStringGenerator } from '../utils/random-string-generator.util';
5-
import { AXIOS_INSTANCE_TOKEN, HTTP_MODULE_ID } from './http.constants';
5+
import {
6+
AXIOS_INSTANCE_TOKEN,
7+
HTTP_MODULE_ID,
8+
HTTP_MODULE_OPTIONS,
9+
} from './http.constants';
610
import { HttpService } from './http.service';
11+
import {
12+
HttpModuleAsyncOptions,
13+
HttpModuleOptions,
14+
HttpModuleOptionsFactory,
15+
} from './interfaces';
716

817
@Module({
918
providers: [
@@ -16,7 +25,7 @@ import { HttpService } from './http.service';
1625
exports: [HttpService],
1726
})
1827
export class HttpModule {
19-
static register(config: AxiosRequestConfig): DynamicModule {
28+
static register(config: HttpModuleOptions): DynamicModule {
2029
return {
2130
module: HttpModule,
2231
providers: [
@@ -31,4 +40,52 @@ export class HttpModule {
3140
],
3241
};
3342
}
43+
44+
static registerAsync(options: HttpModuleAsyncOptions): DynamicModule {
45+
return {
46+
module: HttpModule,
47+
imports: options.imports,
48+
providers: [
49+
...this.createAsyncProviders(options),
50+
{
51+
provide: HTTP_MODULE_ID,
52+
useValue: randomStringGenerator(),
53+
},
54+
...(options.extraProviders || []),
55+
],
56+
};
57+
}
58+
59+
private static createAsyncProviders(
60+
options: HttpModuleAsyncOptions,
61+
): Provider[] {
62+
if (options.useExisting || options.useFactory) {
63+
return [this.createAsyncOptionsProvider(options)];
64+
}
65+
return [
66+
this.createAsyncOptionsProvider(options),
67+
{
68+
provide: options.useClass,
69+
useClass: options.useClass,
70+
},
71+
];
72+
}
73+
74+
private static createAsyncOptionsProvider(
75+
options: HttpModuleAsyncOptions,
76+
): Provider {
77+
if (options.useFactory) {
78+
return {
79+
provide: HTTP_MODULE_OPTIONS,
80+
useFactory: options.useFactory,
81+
inject: options.inject || [],
82+
};
83+
}
84+
return {
85+
provide: HTTP_MODULE_OPTIONS,
86+
useFactory: async (optionsFactory: HttpModuleOptionsFactory) =>
87+
optionsFactory.createHttpOptions(),
88+
inject: [options.useExisting || options.useClass],
89+
};
90+
}
3491
}

0 commit comments

Comments
 (0)