1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.RpcContextCreator = void 0;
|
4 | const constants_1 = require("@nestjs/common/constants");
|
5 | const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
|
6 | const constants_2 = require("@nestjs/core/guards/constants");
|
7 | const context_utils_1 = require("@nestjs/core/helpers/context-utils");
|
8 | const handler_metadata_storage_1 = require("@nestjs/core/helpers/handler-metadata-storage");
|
9 | const constants_3 = require("@nestjs/core/injector/constants");
|
10 | const constants_4 = require("../constants");
|
11 | const exceptions_1 = require("../exceptions");
|
12 | const rpc_params_factory_1 = require("../factories/rpc-params-factory");
|
13 | const rpc_metadata_constants_1 = require("./rpc-metadata-constants");
|
14 | class RpcContextCreator {
|
15 | constructor(rpcProxy, exceptionFiltersContext, pipesContextCreator, pipesConsumer, guardsContextCreator, guardsConsumer, interceptorsContextCreator, interceptorsConsumer) {
|
16 | this.rpcProxy = rpcProxy;
|
17 | this.exceptionFiltersContext = exceptionFiltersContext;
|
18 | this.pipesContextCreator = pipesContextCreator;
|
19 | this.pipesConsumer = pipesConsumer;
|
20 | this.guardsContextCreator = guardsContextCreator;
|
21 | this.guardsConsumer = guardsConsumer;
|
22 | this.interceptorsContextCreator = interceptorsContextCreator;
|
23 | this.interceptorsConsumer = interceptorsConsumer;
|
24 | this.contextUtils = new context_utils_1.ContextUtils();
|
25 | this.rpcParamsFactory = new rpc_params_factory_1.RpcParamsFactory();
|
26 | this.handlerMetadataStorage = new handler_metadata_storage_1.HandlerMetadataStorage();
|
27 | }
|
28 | create(instance, callback, moduleKey, methodName, contextId = constants_3.STATIC_CONTEXT, inquirerId, defaultCallMetadata = rpc_metadata_constants_1.DEFAULT_CALLBACK_METADATA) {
|
29 | const contextType = 'rpc';
|
30 | const { argsLength, paramtypes, getParamsMetadata } = this.getMetadata(instance, methodName, defaultCallMetadata, contextType);
|
31 | const exceptionHandler = this.exceptionFiltersContext.create(instance, callback, moduleKey, contextId, inquirerId);
|
32 | const pipes = this.pipesContextCreator.create(instance, callback, moduleKey, contextId, inquirerId);
|
33 | const guards = this.guardsContextCreator.create(instance, callback, moduleKey, contextId, inquirerId);
|
34 | const interceptors = this.interceptorsContextCreator.create(instance, callback, moduleKey, contextId, inquirerId);
|
35 | const paramsMetadata = getParamsMetadata(moduleKey);
|
36 | const paramsOptions = paramsMetadata
|
37 | ? this.contextUtils.mergeParamsMetatypes(paramsMetadata, paramtypes)
|
38 | : [];
|
39 | const fnApplyPipes = this.createPipesFn(pipes, paramsOptions);
|
40 | const fnCanActivate = this.createGuardsFn(guards, instance, callback, contextType);
|
41 | const handler = (initialArgs, args) => async () => {
|
42 | if (fnApplyPipes) {
|
43 | await fnApplyPipes(initialArgs, ...args);
|
44 | return callback.apply(instance, initialArgs);
|
45 | }
|
46 | return callback.apply(instance, args);
|
47 | };
|
48 | return this.rpcProxy.create(async (...args) => {
|
49 | const initialArgs = this.contextUtils.createNullArray(argsLength);
|
50 | fnCanActivate && (await fnCanActivate(args));
|
51 | return this.interceptorsConsumer.intercept(interceptors, args, instance, callback, handler(initialArgs, args), contextType);
|
52 | }, exceptionHandler);
|
53 | }
|
54 | reflectCallbackParamtypes(instance, callback) {
|
55 | return Reflect.getMetadata(constants_1.PARAMTYPES_METADATA, instance, callback.name);
|
56 | }
|
57 | createGuardsFn(guards, instance, callback, contextType) {
|
58 | const canActivateFn = async (args) => {
|
59 | const canActivate = await this.guardsConsumer.tryActivate(guards, args, instance, callback, contextType);
|
60 | if (!canActivate) {
|
61 | throw new exceptions_1.RpcException(constants_2.FORBIDDEN_MESSAGE);
|
62 | }
|
63 | };
|
64 | return guards.length ? canActivateFn : null;
|
65 | }
|
66 | getMetadata(instance, methodName, defaultCallMetadata, contextType) {
|
67 | const cacheMetadata = this.handlerMetadataStorage.get(instance, methodName);
|
68 | if (cacheMetadata) {
|
69 | return cacheMetadata;
|
70 | }
|
71 | const metadata = this.contextUtils.reflectCallbackMetadata(instance, methodName, constants_4.PARAM_ARGS_METADATA) || defaultCallMetadata;
|
72 | const keys = Object.keys(metadata);
|
73 | const argsLength = this.contextUtils.getArgumentsLength(keys, metadata);
|
74 | const paramtypes = this.contextUtils.reflectCallbackParamtypes(instance, methodName);
|
75 | const contextFactory = this.contextUtils.getContextFactory(contextType, instance, instance[methodName]);
|
76 | const getParamsMetadata = (moduleKey) => this.exchangeKeysForValues(keys, metadata, moduleKey, this.rpcParamsFactory, contextFactory);
|
77 | const handlerMetadata = {
|
78 | argsLength,
|
79 | paramtypes,
|
80 | getParamsMetadata,
|
81 | };
|
82 | this.handlerMetadataStorage.set(instance, methodName, handlerMetadata);
|
83 | return handlerMetadata;
|
84 | }
|
85 | exchangeKeysForValues(keys, metadata, moduleContext, paramsFactory, contextFactory) {
|
86 | this.pipesContextCreator.setModuleContext(moduleContext);
|
87 | return keys.map(key => {
|
88 | const { index, data, pipes: pipesCollection } = metadata[key];
|
89 | const pipes = this.pipesContextCreator.createConcreteContext(pipesCollection);
|
90 | const type = this.contextUtils.mapParamType(key);
|
91 | if (key.includes(constants_1.CUSTOM_ROUTE_ARGS_METADATA)) {
|
92 | const { factory } = metadata[key];
|
93 | const customExtractValue = this.contextUtils.getCustomFactory(factory, data, contextFactory);
|
94 | return { index, extractValue: customExtractValue, type, data, pipes };
|
95 | }
|
96 | const numericType = Number(type);
|
97 | const extractValue = (...args) => paramsFactory.exchangeKeyForValue(numericType, data, args);
|
98 | return { index, extractValue, type: numericType, data, pipes };
|
99 | });
|
100 | }
|
101 | createPipesFn(pipes, paramsOptions) {
|
102 | const pipesFn = async (args, ...params) => {
|
103 | const resolveParamValue = async (param) => {
|
104 | const { index, extractValue, type, data, metatype, pipes: paramPipes, } = param;
|
105 | const value = extractValue(...params);
|
106 | args[index] = await this.getParamValue(value, { metatype, type, data }, pipes.concat(paramPipes));
|
107 | };
|
108 | await Promise.all(paramsOptions.map(resolveParamValue));
|
109 | };
|
110 | return paramsOptions.length ? pipesFn : null;
|
111 | }
|
112 | async getParamValue(value, { metatype, type, data }, pipes) {
|
113 | return (0, shared_utils_1.isEmpty)(pipes)
|
114 | ? value
|
115 | : this.pipesConsumer.apply(value, { metatype, type, data }, pipes);
|
116 | }
|
117 | }
|
118 | exports.RpcContextCreator = RpcContextCreator;
|