1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
|
4 | const invalid_middleware_exception_1 = require("../errors/exceptions/invalid-middleware.exception");
|
5 | const runtime_exception_1 = require("../errors/exceptions/runtime.exception");
|
6 | const context_id_factory_1 = require("../helpers/context-id-factory");
|
7 | const execution_context_host_1 = require("../helpers/execution-context-host");
|
8 | const constants_1 = require("../injector/constants");
|
9 | const request_constants_1 = require("../router/request/request-constants");
|
10 | const router_exception_filters_1 = require("../router/router-exception-filters");
|
11 | const router_proxy_1 = require("../router/router-proxy");
|
12 | const builder_1 = require("./builder");
|
13 | const resolver_1 = require("./resolver");
|
14 | const routes_mapper_1 = require("./routes-mapper");
|
15 | class MiddlewareModule {
|
16 | constructor() {
|
17 | this.routerProxy = new router_proxy_1.RouterProxy();
|
18 | this.exceptionFiltersCache = new WeakMap();
|
19 | }
|
20 | async register(middlewareContainer, container, config, injector) {
|
21 | const appRef = container.getHttpAdapterRef();
|
22 | this.routerExceptionFilter = new router_exception_filters_1.RouterExceptionFilters(container, config, appRef);
|
23 | this.routesMapper = new routes_mapper_1.RoutesMapper(container);
|
24 | this.resolver = new resolver_1.MiddlewareResolver(middlewareContainer);
|
25 | this.config = config;
|
26 | this.injector = injector;
|
27 | this.container = container;
|
28 | const modules = container.getModules();
|
29 | await this.resolveMiddleware(middlewareContainer, modules);
|
30 | }
|
31 | async resolveMiddleware(middlewareContainer, modules) {
|
32 | const moduleEntries = [...modules.entries()];
|
33 | const loadMiddlewareConfiguration = async ([name, module]) => {
|
34 | const instance = module.instance;
|
35 | await this.loadConfiguration(middlewareContainer, instance, name);
|
36 | await this.resolver.resolveInstances(module, name);
|
37 | };
|
38 | await Promise.all(moduleEntries.map(loadMiddlewareConfiguration));
|
39 | }
|
40 | async loadConfiguration(middlewareContainer, instance, moduleKey) {
|
41 | if (!instance.configure) {
|
42 | return;
|
43 | }
|
44 | const middlewareBuilder = new builder_1.MiddlewareBuilder(this.routesMapper);
|
45 | await instance.configure(middlewareBuilder);
|
46 | if (!(middlewareBuilder instanceof builder_1.MiddlewareBuilder)) {
|
47 | return;
|
48 | }
|
49 | const config = middlewareBuilder.build();
|
50 | middlewareContainer.insertConfig(config, moduleKey);
|
51 | }
|
52 | async registerMiddleware(middlewareContainer, applicationRef) {
|
53 | const configs = middlewareContainer.getConfigurations();
|
54 | const registerAllConfigs = (module, middlewareConfig) => middlewareConfig.map(async (config) => {
|
55 | await this.registerMiddlewareConfig(middlewareContainer, config, module, applicationRef);
|
56 | });
|
57 | const entriesSortedByDistance = [...configs.entries()].sort(([moduleA], [moduleB]) => {
|
58 | return (this.container.getModuleByKey(moduleA).distance -
|
59 | this.container.getModuleByKey(moduleB).distance);
|
60 | });
|
61 | const registerModuleConfigs = async ([module, moduleConfigs]) => {
|
62 | await Promise.all(registerAllConfigs(module, [...moduleConfigs]));
|
63 | };
|
64 | await Promise.all(entriesSortedByDistance.map(registerModuleConfigs));
|
65 | }
|
66 | async registerMiddlewareConfig(middlewareContainer, config, module, applicationRef) {
|
67 | const { forRoutes } = config;
|
68 | const registerRouteMiddleware = async (routeInfo) => {
|
69 | await this.registerRouteMiddleware(middlewareContainer, routeInfo, config, module, applicationRef);
|
70 | };
|
71 | await Promise.all(forRoutes.map(registerRouteMiddleware));
|
72 | }
|
73 | async registerRouteMiddleware(middlewareContainer, routeInfo, config, moduleKey, applicationRef) {
|
74 | const middlewareCollection = [].concat(config.middleware);
|
75 | const module = this.container.getModuleByKey(moduleKey);
|
76 | await Promise.all(middlewareCollection.map(async (metatype) => {
|
77 | const collection = middlewareContainer.getMiddlewareCollection(moduleKey);
|
78 | const instanceWrapper = collection.get(metatype.name);
|
79 | if (shared_utils_1.isUndefined(instanceWrapper)) {
|
80 | throw new runtime_exception_1.RuntimeException();
|
81 | }
|
82 | await this.bindHandler(instanceWrapper, applicationRef, routeInfo.method, routeInfo.path, module, collection);
|
83 | }));
|
84 | }
|
85 | async bindHandler(wrapper, applicationRef, method, path, module, collection) {
|
86 | const { instance, metatype } = wrapper;
|
87 | if (shared_utils_1.isUndefined(instance.use)) {
|
88 | throw new invalid_middleware_exception_1.InvalidMiddlewareException(metatype.name);
|
89 | }
|
90 | const router = applicationRef.createMiddlewareFactory(method);
|
91 | const isStatic = wrapper.isDependencyTreeStatic();
|
92 | if (isStatic) {
|
93 | const proxy = await this.createProxy(instance);
|
94 | return this.registerHandler(router, path, proxy);
|
95 | }
|
96 | this.registerHandler(router, path, async (req, res, next) => {
|
97 | try {
|
98 | const contextId = context_id_factory_1.ContextIdFactory.getByRequest(req);
|
99 | if (!req[request_constants_1.REQUEST_CONTEXT_ID]) {
|
100 | Object.defineProperty(req, request_constants_1.REQUEST_CONTEXT_ID, {
|
101 | value: contextId,
|
102 | enumerable: false,
|
103 | writable: false,
|
104 | configurable: false,
|
105 | });
|
106 | this.container.registerRequestProvider(req, contextId);
|
107 | }
|
108 | const contextInstance = await this.injector.loadPerContext(instance, module, collection, contextId);
|
109 | const proxy = await this.createProxy(contextInstance, contextId);
|
110 | return proxy(req, res, next);
|
111 | }
|
112 | catch (err) {
|
113 | let exceptionsHandler = this.exceptionFiltersCache.get(instance.use);
|
114 | if (!exceptionsHandler) {
|
115 | exceptionsHandler = this.routerExceptionFilter.create(instance, instance.use, undefined);
|
116 | this.exceptionFiltersCache.set(instance.use, exceptionsHandler);
|
117 | }
|
118 | const host = new execution_context_host_1.ExecutionContextHost([req, res, next]);
|
119 | exceptionsHandler.next(err, host);
|
120 | }
|
121 | });
|
122 | }
|
123 | async createProxy(instance, contextId = constants_1.STATIC_CONTEXT) {
|
124 | const exceptionsHandler = this.routerExceptionFilter.create(instance, instance.use, undefined, contextId);
|
125 | const middleware = instance.use.bind(instance);
|
126 | return this.routerProxy.createProxy(middleware, exceptionsHandler);
|
127 | }
|
128 | registerHandler(router, path, proxy) {
|
129 | const prefix = this.config.getGlobalPrefix();
|
130 | const basePath = shared_utils_1.validatePath(prefix);
|
131 | if (basePath && path === '/*') {
|
132 |
|
133 |
|
134 | path = '*';
|
135 | }
|
136 | router(basePath + path, proxy);
|
137 | }
|
138 | }
|
139 | exports.MiddlewareModule = MiddlewareModule;
|