UNPKG

9.8 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.ExternalContextCreator = void 0;
4const common_1 = require("@nestjs/common");
5const constants_1 = require("@nestjs/common/constants");
6const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
7const rxjs_1 = require("rxjs");
8const external_exception_filter_context_1 = require("../exceptions/external-exception-filter-context");
9const constants_2 = require("../guards/constants");
10const guards_consumer_1 = require("../guards/guards-consumer");
11const guards_context_creator_1 = require("../guards/guards-context-creator");
12const constants_3 = require("../injector/constants");
13const interceptors_consumer_1 = require("../interceptors/interceptors-consumer");
14const interceptors_context_creator_1 = require("../interceptors/interceptors-context-creator");
15const pipes_consumer_1 = require("../pipes/pipes-consumer");
16const pipes_context_creator_1 = require("../pipes/pipes-context-creator");
17const context_utils_1 = require("./context-utils");
18const external_proxy_1 = require("./external-proxy");
19const handler_metadata_storage_1 = require("./handler-metadata-storage");
20class ExternalContextCreator {
21 constructor(guardsContextCreator, guardsConsumer, interceptorsContextCreator, interceptorsConsumer, modulesContainer, pipesContextCreator, pipesConsumer, filtersContextCreator) {
22 this.guardsContextCreator = guardsContextCreator;
23 this.guardsConsumer = guardsConsumer;
24 this.interceptorsContextCreator = interceptorsContextCreator;
25 this.interceptorsConsumer = interceptorsConsumer;
26 this.modulesContainer = modulesContainer;
27 this.pipesContextCreator = pipesContextCreator;
28 this.pipesConsumer = pipesConsumer;
29 this.filtersContextCreator = filtersContextCreator;
30 this.contextUtils = new context_utils_1.ContextUtils();
31 this.externalErrorProxy = new external_proxy_1.ExternalErrorProxy();
32 this.handlerMetadataStorage = new handler_metadata_storage_1.HandlerMetadataStorage();
33 }
34 static fromContainer(container) {
35 const guardsContextCreator = new guards_context_creator_1.GuardsContextCreator(container, container.applicationConfig);
36 const guardsConsumer = new guards_consumer_1.GuardsConsumer();
37 const interceptorsContextCreator = new interceptors_context_creator_1.InterceptorsContextCreator(container, container.applicationConfig);
38 const interceptorsConsumer = new interceptors_consumer_1.InterceptorsConsumer();
39 const pipesContextCreator = new pipes_context_creator_1.PipesContextCreator(container, container.applicationConfig);
40 const pipesConsumer = new pipes_consumer_1.PipesConsumer();
41 const filtersContextCreator = new external_exception_filter_context_1.ExternalExceptionFilterContext(container, container.applicationConfig);
42 const externalContextCreator = new ExternalContextCreator(guardsContextCreator, guardsConsumer, interceptorsContextCreator, interceptorsConsumer, container.getModules(), pipesContextCreator, pipesConsumer, filtersContextCreator);
43 externalContextCreator.container = container;
44 return externalContextCreator;
45 }
46 create(instance, callback, methodName, metadataKey, paramsFactory, contextId = constants_3.STATIC_CONTEXT, inquirerId, options = {
47 interceptors: true,
48 guards: true,
49 filters: true,
50 }, contextType = 'http') {
51 const module = this.getContextModuleKey(instance.constructor);
52 const { argsLength, paramtypes, getParamsMetadata } = this.getMetadata(instance, methodName, metadataKey, paramsFactory, contextType);
53 const pipes = this.pipesContextCreator.create(instance, callback, module, contextId, inquirerId);
54 const guards = this.guardsContextCreator.create(instance, callback, module, contextId, inquirerId);
55 const exceptionFilter = this.filtersContextCreator.create(instance, callback, module, contextId, inquirerId);
56 const interceptors = options.interceptors
57 ? this.interceptorsContextCreator.create(instance, callback, module, contextId, inquirerId)
58 : [];
59 const paramsMetadata = getParamsMetadata(module, contextId, inquirerId);
60 const paramsOptions = paramsMetadata
61 ? this.contextUtils.mergeParamsMetatypes(paramsMetadata, paramtypes)
62 : [];
63 const fnCanActivate = options.guards
64 ? this.createGuardsFn(guards, instance, callback, contextType)
65 : null;
66 const fnApplyPipes = this.createPipesFn(pipes, paramsOptions);
67 const handler = (initialArgs, ...args) => async () => {
68 if (fnApplyPipes) {
69 await fnApplyPipes(initialArgs, ...args);
70 return callback.apply(instance, initialArgs);
71 }
72 return callback.apply(instance, args);
73 };
74 const target = async (...args) => {
75 const initialArgs = this.contextUtils.createNullArray(argsLength);
76 fnCanActivate && (await fnCanActivate(args));
77 const result = await this.interceptorsConsumer.intercept(interceptors, args, instance, callback, handler(initialArgs, ...args), contextType);
78 return this.transformToResult(result);
79 };
80 return options.filters
81 ? this.externalErrorProxy.createProxy(target, exceptionFilter, contextType)
82 : target;
83 }
84 getMetadata(instance, methodName, metadataKey, paramsFactory, contextType) {
85 const cacheMetadata = this.handlerMetadataStorage.get(instance, methodName);
86 if (cacheMetadata) {
87 return cacheMetadata;
88 }
89 const metadata = this.contextUtils.reflectCallbackMetadata(instance, methodName, metadataKey || '') || {};
90 const keys = Object.keys(metadata);
91 const argsLength = this.contextUtils.getArgumentsLength(keys, metadata);
92 const paramtypes = this.contextUtils.reflectCallbackParamtypes(instance, methodName);
93 const contextFactory = this.contextUtils.getContextFactory(contextType, instance, instance[methodName]);
94 const getParamsMetadata = (moduleKey, contextId = constants_3.STATIC_CONTEXT, inquirerId) => paramsFactory
95 ? this.exchangeKeysForValues(keys, metadata, moduleKey, paramsFactory, contextId, inquirerId, contextFactory)
96 : null;
97 const handlerMetadata = {
98 argsLength,
99 paramtypes,
100 getParamsMetadata,
101 };
102 this.handlerMetadataStorage.set(instance, methodName, handlerMetadata);
103 return handlerMetadata;
104 }
105 getContextModuleKey(moduleCtor) {
106 const emptyModuleKey = '';
107 if (!moduleCtor) {
108 return emptyModuleKey;
109 }
110 const moduleContainerEntries = this.modulesContainer.entries();
111 for (const [key, moduleRef] of moduleContainerEntries) {
112 if (moduleRef.hasProvider(moduleCtor)) {
113 return key;
114 }
115 }
116 return emptyModuleKey;
117 }
118 exchangeKeysForValues(keys, metadata, moduleContext, paramsFactory, contextId = constants_3.STATIC_CONTEXT, inquirerId, contextFactory = this.contextUtils.getContextFactory('http')) {
119 this.pipesContextCreator.setModuleContext(moduleContext);
120 return keys.map(key => {
121 const { index, data, pipes: pipesCollection } = metadata[key];
122 const pipes = this.pipesContextCreator.createConcreteContext(pipesCollection, contextId, inquirerId);
123 const type = this.contextUtils.mapParamType(key);
124 if (key.includes(constants_1.CUSTOM_ROUTE_AGRS_METADATA)) {
125 const { factory } = metadata[key];
126 const customExtractValue = this.contextUtils.getCustomFactory(factory, data, contextFactory);
127 return { index, extractValue: customExtractValue, type, data, pipes };
128 }
129 const numericType = Number(type);
130 const extractValue = (...args) => paramsFactory.exchangeKeyForValue(numericType, data, args);
131 return { index, extractValue, type: numericType, data, pipes };
132 });
133 }
134 createPipesFn(pipes, paramsOptions) {
135 const pipesFn = async (args, ...params) => {
136 const resolveParamValue = async (param) => {
137 const { index, extractValue, type, data, metatype, pipes: paramPipes, } = param;
138 const value = extractValue(...params);
139 args[index] = await this.getParamValue(value, { metatype, type, data }, pipes.concat(paramPipes));
140 };
141 await Promise.all(paramsOptions.map(resolveParamValue));
142 };
143 return paramsOptions.length ? pipesFn : null;
144 }
145 async getParamValue(value, { metatype, type, data }, pipes) {
146 return (0, shared_utils_1.isEmpty)(pipes)
147 ? value
148 : this.pipesConsumer.apply(value, { metatype, type, data }, pipes);
149 }
150 async transformToResult(resultOrDeferred) {
151 if ((0, rxjs_1.isObservable)(resultOrDeferred)) {
152 return (0, rxjs_1.lastValueFrom)(resultOrDeferred);
153 }
154 return resultOrDeferred;
155 }
156 createGuardsFn(guards, instance, callback, contextType) {
157 const canActivateFn = async (args) => {
158 const canActivate = await this.guardsConsumer.tryActivate(guards, args, instance, callback, contextType);
159 if (!canActivate) {
160 throw new common_1.ForbiddenException(constants_2.FORBIDDEN_MESSAGE);
161 }
162 };
163 return guards.length ? canActivateFn : null;
164 }
165 registerRequestProvider(request, contextId) {
166 this.container.registerRequestProvider(request, contextId);
167 }
168}
169exports.ExternalContextCreator = ExternalContextCreator;