Skip to content

Commit f722491

Browse files
Merge pull request nestjs#3039 from nestjs/feat/rpc-ws-decorators
feat() add rpc & ws decorators, add rpc context
2 parents 957bd39 + 1d27dac commit f722491

79 files changed

Lines changed: 1345 additions & 349 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/src/nats/nats.controller.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ import { Body, Controller, Get, HttpCode, Post, Query } from '@nestjs/common';
22
import {
33
Client,
44
ClientProxy,
5+
Ctx,
56
EventPattern,
67
MessagePattern,
8+
NatsContext,
9+
Payload,
710
RpcException,
811
Transport,
912
} from '@nestjs/microservices';
@@ -57,7 +60,7 @@ export class NatsController {
5760
}
5861

5962
@MessagePattern('math.*')
60-
sum(data: number[]): number {
63+
sum(@Payload() data: number[], @Ctx() context: NatsContext): number {
6164
return (data || []).reduce((a, b) => a + b);
6265
}
6366

@@ -94,7 +97,7 @@ export class NatsController {
9497
}
9598

9699
@EventPattern('notification')
97-
eventHandler(data: boolean) {
100+
eventHandler(@Payload() data: boolean) {
98101
NatsController.IS_NOTIFIED = data;
99102
}
100103
}

integration/websockets/src/app.gateway.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
import { WebSocketGateway, SubscribeMessage } from '@nestjs/websockets';
1+
import {
2+
MessageBody,
3+
SubscribeMessage,
4+
WebSocketGateway,
5+
} from '@nestjs/websockets';
26

37
@WebSocketGateway(8080)
48
export class ApplicationGateway {
59
@SubscribeMessage('push')
6-
onPush(client, data) {
10+
onPush(@MessageBody() data) {
711
return {
812
event: 'pop',
913
data,

integration/websockets/src/core.gateway.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
import { SubscribeMessage, WebSocketGateway } from '@nestjs/websockets';
1+
import {
2+
ConnectedSocket,
3+
MessageBody,
4+
SubscribeMessage,
5+
WebSocketGateway,
6+
} from '@nestjs/websockets';
27

38
@WebSocketGateway(8090)
49
export class CoreGateway {
510
@SubscribeMessage('push')
6-
onPush(client, data) {
11+
onPush(@ConnectedSocket() client, @MessageBody() data) {
712
return {
813
event: 'pop',
914
data,

integration/websockets/src/server.gateway.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { WebSocketGateway, SubscribeMessage } from '@nestjs/websockets';
1+
import { SubscribeMessage, WebSocketGateway } from '@nestjs/websockets';
22

33
@WebSocketGateway()
44
export class ServerGateway {

packages/common/decorators/http/create-route-param-metadata.decorator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import { PipeTransform } from '../../index';
77
import { Type } from '../../interfaces';
88
import { CustomParamFactory } from '../../interfaces/features/custom-route-param-factory.interface';
99
import { isFunction, isNil } from '../../utils/shared.utils';
10-
import { ParamData, RouteParamsMetadata } from './route-params.decorator';
10+
import { ParamData, RouteParamMetadata } from './route-params.decorator';
1111

1212
const assignCustomMetadata = (
13-
args: RouteParamsMetadata,
13+
args: Record<number, RouteParamMetadata>,
1414
paramtype: number | string,
1515
index: number,
1616
factory: CustomParamFactory,

packages/common/decorators/http/route-params.decorator.ts

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,40 @@ import { Type } from '../../interfaces';
55
import { isNil, isString } from '../../utils/shared.utils';
66

77
export type ParamData = object | string | number;
8-
export interface RouteParamsMetadata {
9-
[prop: number]: {
10-
index: number;
11-
data?: ParamData;
12-
};
8+
export interface RouteParamMetadata {
9+
index: number;
10+
data?: ParamData;
1311
}
1412

15-
const assignMetadata = (
16-
args: RouteParamsMetadata,
17-
paramtype: RouteParamtypes,
13+
export function assignMetadata<TParamtype = any, TArgs = any>(
14+
args: TArgs,
15+
paramtype: TParamtype,
1816
index: number,
1917
data?: ParamData,
2018
...pipes: (Type<PipeTransform> | PipeTransform)[]
21-
) => ({
22-
...args,
23-
[`${paramtype}:${index}`]: {
24-
index,
25-
data,
26-
pipes,
27-
},
28-
});
19+
) {
20+
return {
21+
...args,
22+
[`${paramtype}:${index}`]: {
23+
index,
24+
data,
25+
pipes,
26+
},
27+
};
28+
}
2929

3030
const createRouteParamDecorator = (paramtype: RouteParamtypes) => {
3131
return (data?: ParamData): ParameterDecorator => (target, key, index) => {
3232
const args =
3333
Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
3434
Reflect.defineMetadata(
3535
ROUTE_ARGS_METADATA,
36-
assignMetadata(args, paramtype, index, data),
36+
assignMetadata<RouteParamtypes, Record<number, RouteParamMetadata>>(
37+
args,
38+
paramtype,
39+
index,
40+
data,
41+
),
3742
target.constructor,
3843
key,
3944
);
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export type CustomParamFactory<TData = any, TRequest = any, TResult = any> = (
1+
export type CustomParamFactory<TData = any, TInput = any, TOutput = any> = (
22
data: TData,
3-
req: TRequest,
4-
) => TResult;
3+
input: TInput,
4+
) => TOutput;

packages/common/test/decorators/global.decorator.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { expect } from 'chai';
22
import { GLOBAL_MODULE_METADATA } from '../../constants';
33
import { Global } from '../../index';
44

5-
describe('Global', () => {
5+
describe('@Global', () => {
66
@Global()
77
class Test {}
88

packages/core/helpers/context-utils.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ParamData } from '@nestjs/common';
22
import { PARAMTYPES_METADATA } from '@nestjs/common/constants';
33
import { Controller, PipeTransform } from '@nestjs/common/interfaces';
4+
import { isFunction } from '@nestjs/common/utils/shared.utils';
45

56
export interface ParamProperties<T = any, IExtractor extends Function = any> {
67
index: number;
@@ -51,4 +52,13 @@ export class ContextUtils {
5152
metatype: paramtypes[param.index],
5253
}));
5354
}
55+
56+
public getCustomFactory(
57+
factory: (...args: unknown[]) => void,
58+
data: unknown,
59+
): (...args: unknown[]) => unknown {
60+
return isFunction(factory)
61+
? (...args: unknown[]) => factory(data, args)
62+
: () => null;
63+
}
5464
}

packages/core/helpers/external-context-creator.ts

Lines changed: 35 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,16 @@ import { PipesConsumer } from '../pipes/pipes-consumer';
1414
import { PipesContextCreator } from '../pipes/pipes-context-creator';
1515
import { ExternalExceptionFilterContext } from './../exceptions/external-exception-filter-context';
1616
import { STATIC_CONTEXT } from './../injector/constants';
17-
import { ContextId } from './../injector/instance-wrapper';
1817
import { ContextUtils, ParamProperties } from './context-utils';
1918
import { ExternalErrorProxy } from './external-proxy';
2019
import { HandlerMetadataStorage } from './handler-metadata-storage';
21-
22-
export interface ParamsMetadata {
23-
[prop: number]: {
24-
index: number;
25-
data?: ParamData;
26-
};
27-
}
20+
import { ExternalHandlerMetadata } from './interfaces/external-handler-metadata.interface';
21+
import { ParamsMetadata } from './interfaces/params-metadata.interface';
2822

2923
export interface ParamsFactory {
3024
exchangeKeyForValue(type: number, data: ParamData, args: any): any;
3125
}
3226

33-
export interface ExternalHandlerMetadata {
34-
argsLength: number;
35-
paramtypes: any[];
36-
getParamsMetadata: (
37-
moduleKey: string,
38-
contextId?: ContextId,
39-
inquirerId?: string,
40-
) => (ParamProperties & { metatype?: any })[];
41-
}
42-
4327
export interface ExternalContextOptions {
4428
guards?: boolean;
4529
interceptors?: boolean;
@@ -110,7 +94,7 @@ export class ExternalContextCreator {
11094
filters: true,
11195
},
11296
) {
113-
const module = this.findContextModuleName(instance.constructor);
97+
const module = this.getContextModuleName(instance.constructor);
11498
const { argsLength, paramtypes, getParamsMetadata } = this.getMetadata<T>(
11599
instance,
116100
methodName,
@@ -230,20 +214,21 @@ export class ExternalContextCreator {
230214
return handlerMetadata;
231215
}
232216

233-
public findContextModuleName(constructor: Function): string {
217+
public getContextModuleName(constructor: Function): string {
218+
const defaultModuleName = '';
234219
const className = constructor.name;
235220
if (!className) {
236-
return '';
221+
return defaultModuleName;
237222
}
238223
for (const [key, module] of [...this.modulesContainer.entries()]) {
239-
if (this.findProviderByClassName(module, className)) {
224+
if (this.getProviderByClassName(module, className)) {
240225
return key;
241226
}
242227
}
243-
return '';
228+
return defaultModuleName;
244229
}
245230

246-
public findProviderByClassName(module: Module, className: string): boolean {
231+
public getProviderByClassName(module: Module, className: string): boolean {
247232
const { providers } = module;
248233
const hasProvider = [...providers.keys()].some(
249234
provider => provider === className,
@@ -271,50 +256,45 @@ export class ExternalContextCreator {
271256

272257
if (key.includes(CUSTOM_ROUTE_AGRS_METADATA)) {
273258
const { factory } = metadata[key];
274-
const customExtractValue = this.getCustomFactory(factory, data);
259+
const customExtractValue = this.contextUtils.getCustomFactory(
260+
factory,
261+
data,
262+
);
275263
return { index, extractValue: customExtractValue, type, data, pipes };
276264
}
277265
const numericType = Number(type);
278-
const extractValue = (...args: any[]) =>
266+
const extractValue = (...args: unknown[]) =>
279267
paramsFactory.exchangeKeyForValue(numericType, data, args);
280268

281269
return { index, extractValue, type: numericType, data, pipes };
282270
});
283271
}
284272

285-
public getCustomFactory(
286-
factory: (...args: any[]) => void,
287-
data: any,
288-
): (...args: any[]) => any {
289-
return isFunction(factory)
290-
? (...args: any[]) => factory(data, args)
291-
: () => null;
292-
}
293-
294273
public createPipesFn(
295274
pipes: PipeTransform[],
296-
paramsOptions: (ParamProperties & { metatype?: any })[],
275+
paramsOptions: (ParamProperties & { metatype?: unknown })[],
297276
) {
298-
const pipesFn = async (args: any[], ...params: any[]) => {
299-
await Promise.all(
300-
paramsOptions.map(async param => {
301-
const {
302-
index,
303-
extractValue,
304-
type,
305-
data,
306-
metatype,
307-
pipes: paramPipes,
308-
} = param;
309-
const value = extractValue(...params);
277+
const pipesFn = async (args: unknown[], ...params: unknown[]) => {
278+
const resolveParamValue = async (
279+
param: ParamProperties & { metatype?: unknown },
280+
) => {
281+
const {
282+
index,
283+
extractValue,
284+
type,
285+
data,
286+
metatype,
287+
pipes: paramPipes,
288+
} = param;
289+
const value = extractValue(...params);
310290

311-
args[index] = await this.getParamValue(
312-
value,
313-
{ metatype, type, data },
314-
pipes.concat(paramPipes),
315-
);
316-
}),
317-
);
291+
args[index] = await this.getParamValue(
292+
value,
293+
{ metatype, type, data },
294+
pipes.concat(paramPipes),
295+
);
296+
};
297+
await Promise.all(paramsOptions.map(resolveParamValue));
318298
};
319299
return paramsOptions.length ? pipesFn : null;
320300
}

0 commit comments

Comments
 (0)