UNPKG

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