UNPKG

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