1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100 | 1x
1x
1x
1x
10x
10x
10x
10x
10x
10x
10x
10x
6x
6x
6x
6x
6x
6x
6x
3x
3x
3x
6x
3x
3x
9x
8x
8x
7x
2x
2x
1x
7x
| import { PARAMTYPES_METADATA } from '@nestjs/common/constants';
import { Controller } from '@nestjs/common/interfaces';
import { FORBIDDEN_MESSAGE } from '@nestjs/core/guards/constants';
import { GuardsConsumer } from '@nestjs/core/guards/guards-consumer';
import { GuardsContextCreator } from '@nestjs/core/guards/guards-context-creator';
import { InterceptorsConsumer } from '@nestjs/core/interceptors/interceptors-consumer';
import { InterceptorsContextCreator } from '@nestjs/core/interceptors/interceptors-context-creator';
import { PipesConsumer } from '@nestjs/core/pipes/pipes-consumer';
import { PipesContextCreator } from '@nestjs/core/pipes/pipes-context-creator';
import { Observable } from 'rxjs';
import { RpcException } from '..';
import { ExceptionFiltersContext } from './exception-filters-context';
import { RpcProxy } from './rpc-proxy';
export class RpcContextCreator {
constructor(
private readonly rpcProxy: RpcProxy,
private readonly exceptionFiltersContext: ExceptionFiltersContext,
private readonly pipesCreator: PipesContextCreator,
private readonly pipesConsumer: PipesConsumer,
private readonly guardsContextCreator: GuardsContextCreator,
private readonly guardsConsumer: GuardsConsumer,
private readonly interceptorsContextCreator: InterceptorsContextCreator,
private readonly interceptorsConsumer: InterceptorsConsumer,
) {}
public create(
instance: Controller,
callback: (data) => Observable<any>,
module,
): (...args) => Promise<Observable<any>> {
const exceptionHandler = this.exceptionFiltersContext.create(
instance,
callback,
module,
);
const pipes = this.pipesCreator.create(instance, callback, module);
const guards = this.guardsContextCreator.create(instance, callback, module);
const metatype = this.getDataMetatype(instance, callback);
const interceptors = this.interceptorsContextCreator.create(
instance,
callback,
module,
);
const fnCanActivate = this.createGuardsFn(guards, instance, callback);
const handler = (args: any[]) => async () => {
const [data, ...params] = args;
const result = await this.pipesConsumer.applyPipes(
data,
{ metatype },
pipes,
);
return callback.call(instance, result, ...params);
};
return this.rpcProxy.create(async (...args) => {
fnCanActivate && (await fnCanActivate(args));
return this.interceptorsConsumer.intercept(
interceptors,
args,
instance,
callback,
handler(args),
);
}, exceptionHandler);
}
public reflectCallbackParamtypes(
instance: Controller,
callback: (...args) => any,
): any[] {
return Reflect.getMetadata(PARAMTYPES_METADATA, instance, callback.name);
}
public getDataMetatype(instance, callback) {
const paramtypes = this.reflectCallbackParamtypes(instance, callback);
return paramtypes && paramtypes.length ? paramtypes[0] : null;
}
public createGuardsFn(
guards: any[],
instance: Controller,
callback: (...args) => any,
): Function | null {
const canActivateFn = async (args: any[]) => {
const canActivate = await this.guardsConsumer.tryActivate(
guards,
args,
instance,
callback,
);
if (!canActivate) {
throw new RpcException(FORBIDDEN_MESSAGE);
}
};
return guards.length ? canActivateFn : null;
}
}
|