UNPKG

@tsclean/core

Version:

Plugin for API Rest Full development, based on Clean Architecture, IoC and Dependency Injection.

167 lines 32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MiddlewareModule = void 0; const utils_1 = require("../router/utils"); const invalid_middleware_1 = require("../errors/exceptions/invalid-middleware"); const runtime_1 = require("../errors/exceptions/runtime"); const helpers_1 = require("../helpers"); const execution_context_host_1 = require("../helpers/execution-context-host"); const constants_1 = require("../core/injector/constants"); const request_constants_1 = require("../router/request/request-constants"); const router_exception_filters_1 = require("../router/router-exception-filters"); const router_proxy_1 = require("../router/router-proxy"); const builder_1 = require("./builder"); const resolver_1 = require("./resolver"); const routes_mapper_1 = require("./routes-mapper"); const utils_2 = require("../utils"); const enums_1 = require("../enums"); const services_1 = require("../services"); const route_info_path_extractor_1 = require("./route-info-path-extractor"); class MiddlewareModule { constructor() { this.routerProxy = new router_proxy_1.RouterProxy(); this.exceptionFiltersCache = new WeakMap(); this.logger = new services_1.Logger(MiddlewareModule.name); } async register(middlewareContainer, container, config, injector, httpAdapter, graphInspector, options) { this.appOptions = options; const appRef = container.getHttpAdapterRef(); this.routerExceptionFilter = new router_exception_filters_1.RouterExceptionFilters(container, config, appRef); this.routesMapper = new routes_mapper_1.RoutesMapper(container, config); this.resolver = new resolver_1.MiddlewareResolver(middlewareContainer); this.routeInfoPathExtractor = new route_info_path_extractor_1.RouteInfoPathExtractor(config); this.injector = injector; this.container = container; this.httpAdapter = httpAdapter; this.graphInspector = graphInspector; const modules = container.getModules(); await this.resolveMiddleware(middlewareContainer, modules); } async resolveMiddleware(middlewareContainer, modules) { const moduleEntries = [...modules.entries()]; const loadMiddlewareConfiguration = async ([moduleName, moduleRef]) => { await this.loadConfiguration(middlewareContainer, moduleRef, moduleName); await this.resolver.resolveInstances(moduleRef, moduleName); }; await Promise.all(moduleEntries.map(loadMiddlewareConfiguration)); } async loadConfiguration(middlewareContainer, moduleRef, moduleKey) { const { instance } = moduleRef; if (!instance.configure) { return; } const middlewareBuilder = new builder_1.MiddlewareBuilder(this.routesMapper, this.httpAdapter); await instance.configure(middlewareBuilder); if (!(middlewareBuilder instanceof builder_1.MiddlewareBuilder)) { return; } const config = middlewareBuilder.build(); middlewareContainer.insertConfig(config, moduleKey); } async registerMiddleware(middlewareContainer, applicationRef) { const configs = middlewareContainer.getConfigurations(); const registerAllConfigs = async (moduleKey, middlewareConfig) => { for (const config of middlewareConfig) { await this.registerMiddlewareConfig(middlewareContainer, config, moduleKey, applicationRef); } }; const entriesSortedByDistance = [...configs.entries()].sort(([moduleA], [moduleB]) => { return (this.container.getModuleByKey(moduleA).distance - this.container.getModuleByKey(moduleB).distance); }); for (const [moduleRef, moduleConfigurations] of entriesSortedByDistance) { await registerAllConfigs(moduleRef, [...moduleConfigurations]); } } async registerMiddlewareConfig(middlewareContainer, config, moduleKey, applicationRef) { const { forRoutes } = config; for (const routeInfo of forRoutes) { await this.registerRouteMiddleware(middlewareContainer, routeInfo, config, moduleKey, applicationRef); } } async registerRouteMiddleware(middlewareContainer, routeInfo, config, moduleKey, applicationRef) { const middlewareCollection = [].concat(config.middleware); const moduleRef = this.container.getModuleByKey(moduleKey); for (const metatype of middlewareCollection) { const collection = middlewareContainer.getMiddlewareCollection(moduleKey); const instanceWrapper = collection.get(metatype); if ((0, utils_2.isUndefined)(instanceWrapper)) { throw new runtime_1.RuntimeException(); } if (instanceWrapper.isTransient) { return; } await this.bindHandler(instanceWrapper, applicationRef, routeInfo, moduleRef, collection); } } async bindHandler(wrapper, applicationRef, routeInfo, moduleRef, collection) { const { instance, metaType } = wrapper; if ((0, utils_2.isUndefined)(instance === null || instance === void 0 ? void 0 : instance.use)) { throw new invalid_middleware_1.InvalidMiddlewareException(metaType.name); } const isStatic = wrapper.isDependencyTreeStatic(); if (isStatic) { const proxy = await this.createProxy(instance); return this.registerHandler(applicationRef, routeInfo, proxy); } const isTreeDurable = wrapper.isDependencyTreeDurable(); await this.registerHandler(applicationRef, routeInfo, async (req, res, next) => { try { const contextId = this.getContextId(req, isTreeDurable); const contextInstance = await this.injector.loadPerContext(instance, moduleRef, collection, contextId); const proxy = await this.createProxy(contextInstance, contextId); return proxy(req, res, next); } catch (err) { let exceptionsHandler = this.exceptionFiltersCache.get(instance.use); if (!exceptionsHandler) { exceptionsHandler = this.routerExceptionFilter.create(instance, instance.use, undefined); this.exceptionFiltersCache.set(instance.use, exceptionsHandler); } const host = new execution_context_host_1.ExecutionContextHost([req, res, next]); exceptionsHandler.next(err, host); } }); } async createProxy(instance, contextId = constants_1.STATIC_CONTEXT) { const exceptionsHandler = this.routerExceptionFilter.create(instance, instance.use, undefined, contextId); const middleware = instance.use.bind(instance); return this.routerProxy.createProxy(middleware, exceptionsHandler); } async registerHandler(applicationRef, routeInfo, proxy) { const { method } = routeInfo; const paths = this.routeInfoPathExtractor.extractPathsFrom(routeInfo); const isMethodAll = (0, utils_1.isRequestMethodAll)(method); const requestMethod = enums_1.RequestMethod[method]; const router = await applicationRef.createMiddlewareFactory(method); const middlewareFunction = isMethodAll ? proxy : (req, res, next) => { if (applicationRef.getRequestMethod(req) === requestMethod) { return proxy(req, res, next); } return next(); }; const pathsToApplyMiddleware = []; paths.some(path => path.match(/^\/?$/)) ? pathsToApplyMiddleware.push('/') : pathsToApplyMiddleware.push(...paths); pathsToApplyMiddleware.forEach(path => router(path, middlewareFunction)); } getContextId(request, isTreeDurable) { const contextId = helpers_1.ContextIdFactory.getByRequest(request); if (!request[request_constants_1.REQUEST_CONTEXT_ID]) { Object.defineProperty(request, request_constants_1.REQUEST_CONTEXT_ID, { value: contextId, enumerable: false, writable: false, configurable: false }); const requestProviderValue = isTreeDurable ? contextId.payload : request; this.container.registerRequestProvider(requestProviderValue, contextId); } return contextId; } } exports.MiddlewareModule = MiddlewareModule; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlkZGxld2FyZS1tb2R1bGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWlkZGxld2FyZS9taWRkbGV3YXJlLW1vZHVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwyQ0FBb0Q7QUFFcEQsZ0ZBQW9GO0FBQ3BGLDBEQUErRDtBQUMvRCx3Q0FBNkM7QUFDN0MsOEVBQXdFO0FBQ3hFLDBEQUEyRDtBQUszRCwyRUFBd0U7QUFDeEUsaUZBQTJFO0FBQzNFLHlEQUFvRDtBQUNwRCx1Q0FBNkM7QUFFN0MseUNBQStDO0FBQy9DLG1EQUE4QztBQVE5QyxvQ0FBdUQ7QUFDdkQsb0NBQXdDO0FBRXhDLDBDQUFvQztBQUVwQywyRUFBb0U7QUFFcEUsTUFBYSxnQkFBZ0I7SUFBN0I7UUFHbUIsZ0JBQVcsR0FBRyxJQUFJLDBCQUFXLEVBQUUsQ0FBQTtRQUMvQiwwQkFBcUIsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFBO1FBQ3JDLFdBQU0sR0FBRyxJQUFJLGlCQUFNLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUE7SUFxUjdELENBQUM7SUF6UVEsS0FBSyxDQUFDLFFBQVEsQ0FDbkIsbUJBQXdDLEVBQ3hDLFNBQXVCLEVBQ3ZCLE1BQXlCLEVBQ3pCLFFBQWtCLEVBQ2xCLFdBQXVCLEVBQ3ZCLGNBQThCLEVBQzlCLE9BQW9CO1FBRXBCLElBQUksQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFBO1FBRXpCLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxpQkFBaUIsRUFBRSxDQUFBO1FBQzVDLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLGlEQUFzQixDQUNyRCxTQUFTLEVBQ1QsTUFBTSxFQUNOLE1BQU0sQ0FDUCxDQUFBO1FBQ0QsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLDRCQUFZLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBQ3ZELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSw2QkFBa0IsQ0FBQyxt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QUNsQyxDQUFDLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUE7UUFDekMsc0JBQXNCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxrQkFBa0IsQ0FBQyxDQUFDLENBQUE7SUFDMUUsQ0FBQztJQUVPLFlBQVksQ0FBRSxPQUFnQixFQUFFLGFBQXNCO1FBQzVELE1BQU0sU0FBUyxHQUFHLDBCQUFnQixDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUN4RCxJQUFJLENBQUMsT0FBTyxDQUFDLHNDQUFrQixDQUFDLEVBQUUsQ0FBQztZQUNqQyxNQUFNLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxzQ0FBa0IsRUFBRTtnQkFDakQsS0FBSyxFQUFFLFNBQVM7Z0JBQ2hCLFVBQVUsRUFBRSxLQUFLO2dCQUNqQixRQUFRLEVBQUUsS0FBSztnQkFDZixZQUFZLEVBQUUsS0FBSzthQUNwQixDQUFDLENBQUE7WUFFRixNQUFNLG9CQUFvQixHQUFHLGFBQWEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFBO1lBQ3hFLElBQUksQ0FBQyxTQUFTLENBQUMsdUJBQXVCLENBQUMsb0JBQW9CLEVBQUUsU0FBUyxDQUFDLENBQUE7UUFDekUsQ0FBQztRQUNELE9BQU8sU0FBUyxDQUFBO0lBQ2xCLENBQUM7Q0FDRjtBQTFSRCw0Q0EwUkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpc1JlcXVlc3RNZXRob2RBbGwgfSBmcm9tICcuLi9yb3V0ZXIvdXRpbHMnXG5pbXBvcnQgeyBBcHBsaWNhdGlvbkNvbmZpZyB9IGZyb20gJy4uL2FwcC9hcHBsaWNhdGlvbi1jb25maWcnXG5pbXBvcnQgeyBJbnZhbGlkTWlkZGxld2FyZUV4Y2VwdGlvbiB9IGZyb20gJy4uL2Vycm9ycy9leGNlcHRpb25zL2ludmFsaWQtbWlkZGxld2FyZSdcbmltcG9ydCB7IFJ1bnRpbWVFeGNlcHRpb24gfSBmcm9tICcuLi9lcnJvcnMvZXhjZXB0aW9ucy9ydW50aW1lJ1xuaW1wb3J0IHsgQ29udGV4dElkRmFjdG9yeSB9IGZyb20gJy4uL2hlbHBlcnMnXG5pbXBvcnQgeyBFeGVjdXRpb25Db250ZXh0SG9zdCB9IGZyb20gJy4uL2hlbHBlcnMvZXhlY3V0aW9uLWNvbnRleHQtaG9zdCdcbmltcG9ydCB7IFNUQVRJQ19DT05URVhUIH0gZnJvbSAnLi4vY29yZS9pbmplY3Rvci9jb25zdGFudHMnXG5pbXBvcnQgeyBDb250YWluZXJJb0MsIENvbnRleHRJZCB9IGZyb20gJy4uL2NvcmUvaW5qZWN0b3InXG5pbXBvcnQgeyBJbmplY3RvciB9IGZyb20gJy4uL2NvcmUvaW5qZWN0b3IvaW5qZWN0b3InXG5pbXBvcnQgeyBJbnN0YW5jZVdyYXBwZXIgfSBmcm9tICcuLi9jb3JlL2luamVjdG9yL2luc3RhbmNlLXdyYXBwZXInXG5pbXBvcnQgeyBNb2R1bGUgfSBmcm9tICcuLi9jb3JlL2luamVjdG9yL21vZHVsZSdcbmltcG9ydCB7IFJFUVVFU1RfQ09OVEVYVF9JRCB9IGZyb20gJy4uL3JvdXRlci9yZXF1ZXN0L3JlcXVlc3QtY29uc3RhbnRzJ1xuaW1wb3J0IHsgUm91dGVyRXhjZXB0aW9uRmlsdGVycyB9IGZyb20gJy4uL3JvdXRlci9yb3V0ZXItZXhjZXB0aW9uLWZpbHRlcnMnXG5pbXBvcnQgeyBSb3V0ZXJQcm94eSB9IGZyb20gJy4uL3JvdXRlci9yb3V0ZXItcHJveHknXG5pbXBvcnQgeyBNaWRkbGV3YXJlQnVpbGRlciB9IGZyb20gJy4vYnVpbGRlcidcbmltcG9ydCB7IE1pZGRsZXdhcmVDb250YWluZXIgfSBmcm9tICcuL2NvbnRhaW5lcidcbmltcG9ydCB7IE1pZGRsZXdhcmVSZXNvbHZlciB9IGZyb20gJy4vcmVzb2x2ZXInXG5pbXBvcnQgeyBSb3V0ZXNNYXBwZXIgfSBmcm9tICcuL3JvdXRlcy1tYXBwZXInXG5pbXBvcnQge1xuICBBcHBsaWNhdGlvbkNvbnRleHRPcHRpb25zSW50ZXJmYWNlLFxuICBIdHRwU2VydmVyLFxuICBNaWRkbGV3YXJlQ29uZmlndXJhdGlvbkludGVyZmFjZSxcbiAgTWlkZGxld2FyZUludGVyZmFjZSxcbiAgUm91dGVJbmZvXG59IGZyb20gJy4uL2NvbnRyYWN0cydcbmltcG9ydCB7IGFkZExlYWRpbmdTbGFzaCwgaXNVbmRlZmluZWQgfSBmcm9tICcuLi91dGlscydcbmltcG9ydCB7IFJlcXVlc3RNZXRob2QgfSBmcm9tICcuLi9lbnVtcydcbmltcG9ydCB7IEluc3RhbmNlVG9rZW5UeXBlIH0gZnJvbSAnLi4vdHlwZXMnXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi9zZXJ2aWNlcydcbmltcG9ydCB7IEdyYXBoSW5zcGVjdG9yIH0gZnJvbSAnLi4vaW5zcGVjdG9yJ1xuaW1wb3J0IHsgUm91dGVJbmZvUGF0aEV4dHJhY3RvciB9IGZyb20gJy4vcm91dGUtaW5mby1wYXRoLWV4dHJhY3RvcidcblxuZXhwb3J0IGNsYXNzIE1pZGRsZXdhcmVNb2R1bGU8XG4gIFRBcHBPcHRpb25zIGV4dGVuZHMgQXBwbGljYXRpb25Db250ZXh0T3B0aW9uc0ludGVyZmFjZSA9IEFwcGxpY2F0aW9uQ29udGV4dE9wdGlvbnNJbnRlcmZhY2Vcbj4ge1xuICBwcml2YXRlIHJlYWRvbmx5IHJvdXRlclByb3h5ID0gbmV3IFJvdXRlclByb3h5KClcbiAgcHJpdmF0ZSByZWFkb25seSBleGNlcHRpb25GaWx0ZXJzQ2FjaGUgPSBuZXcgV2Vha01hcCgpXG4gIHByaXZhdGUgcmVhZG9ubHkgbG9nZ2VyID0gbmV3IExvZ2dlcihNaWRkbGV3YXJlTW9kdWxlLm5hbWUpXG5cbiAgcHJpdmF0ZSBpbmplY3RvcjogSW5qZWN0b3JcbiAgcHJpdmF0ZSByb3V0ZXJFeGNlcHRpb25GaWx0ZXI6IFJvdXRlckV4Y2VwdGlvbkZpbHRlcnNcbiAgcHJpdmF0ZSByb3V0ZXNNYXBwZXI6IFJvdXRlc01hcHBlclxuICBwcml2YXRlIHJlc29sdmVyOiBNaWRkbGV3YXJlUmVzb2x2ZXJcbiAgcHJpdmF0ZSBjb250YWluZXI6IENvbnRhaW5lcklvQ1xuICBwcml2YXRlIGh0dHBBZGFwdGVyOiBIdHRwU2VydmVyXG4gIHByaXZhdGUgZ3JhcGhJbnNwZWN0b3I6IEdyYXBoSW5zcGVjdG9yXG4gIHByaXZhdGUgYXBwT3B0aW9uczogVEFwcE9wdGlvbnNcbiAgcHJpdmF0ZSByb3V0ZUluZm9QYXRoRXh0cmFjdG9yOiBSb3V0ZUluZm9QYXRoRXh0cmFjdG9yXG5cbiAgcHVibGljIGFzeW5jIHJlZ2lzdGVyIChcbiAgICBtaWRkbGV3YXJlQ29udGFpbmVyOiBNaWRkbGV3YXJlQ29udGFpbmVyLFxuICAgIGNvbnRhaW5lcjogQ29udGFpbmVySW9DLFxuICAgIGNvbmZpZzogQXBwbGljYXRpb25Db25maWcsXG4gICAgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgIGh0dHBBZGFwdGVyOiBIdHRwU2VydmVyLFxuICAgIGdyYXBoSW5zcGVjdG9yOiBHcmFwaEluc3BlY3RvcixcbiAgICBvcHRpb25zOiBUQXBwT3B0aW9uc1xuICApIHtcbiAgICB0aGlzLmFwcE9wdGlvbnMgPSBvcHRpb25zXG5cbiAgICBjb25zdCBhcHBSZWYgPSBjb250YWluZXIuZ2V0SHR0cEFkYXB0ZXJSZWYoKVxuICAgIHRoaXMucm91dGVyRXhjZXB0aW9uRmlsdGVyID0gbmV3IFJvdXRlckV4Y2VwdGlvbkZpbHRlcnMoXG4gICAgICBjb250YWluZXIsXG4gICAgICBjb25maWcsXG4gICAgICBhcHBSZWZcbiAgICApXG4gICAgdGhpcy5yb3V0ZXNNYXBwZXIgPSBuZXcgUm91dGVzTWFwcGVyKGNvbnRhaW5lciwgY29uZmlnKVxuICAgIHRoaXMucmVzb2x2ZXIgPSBuZXcgTWlkZGxld2FyZVJlc29sdmVyKG1pZGRsZXdhcmVDb250YWluZXIpXG4gICAgdGhpcy5yb3V0ZUluZm9QYXRoRXh0cmFjdG9yID0gbmV3IFJvdXRlSW5mb1BhdGhFeHRyYWN0b3IoY29uZmlnKVxuXG4gICAgdGhpcy5pbmplY3RvciA9IGluamVjdG9yXG4gICAgdGhpcy5jb250YWluZXIgPSBjb250YWluZXJcbiAgICB0aGlzLmh0dHBBZGFwdGVyID0gaHR0cEFkYXB0ZXJcbiAgICB0aGlzLmdyYXBoSW5zcGVjdG9yID0gZ3JhcGhJbnNwZWN0b3JcblxuICAgIGNvbnN0IG1vZHVsZXMgPSBjb250YWluZXIuZ2V0TW9kdWxlcygpXG4gICAgYXdhaXQgdGhpcy5yZXNvbHZlTWlkZGxld2FyZShtaWRkbGV3YXJlQ29udGFpbmVyLCBtb2R1bGVzKVxuICB9XG5cbiAgcHVibGljIGFzeW5jIHJlc29sdmVNaWRkbGV3YXJlIChcbiAgICBtaWRkbGV3YXJlQ29udGFpbmVyOiBNaWRkbGV3YXJlQ29udGFpbmVyLFxuICAgIG1vZHVsZXM6IE1hcDxzdHJpbmcsIE1vZHVsZT5cbiAgKSB7XG4gICAgY29uc3QgbW9kdWxlRW50cmllcyA9IFsuLi5tb2R1bGVzLmVudHJpZXMoKV1cbiAgICBjb25zdCBsb2FkTWlkZGxld2FyZUNvbmZpZ3VyYXRpb24gPSBhc3luYyAoW21vZHVsZU5hbWUsIG1vZHVsZVJlZl06IFtcbiAgICAgIHN0cmluZyxcbiAgICAgIE1vZHVsZVxuICAgIF0pID0+IHtcbiAgICAgIGF3YWl0IHRoaXMubG9hZENvbmZpZ3VyYXRpb24obWlkZGxld2FyZUNvbnRhaW5lciwgbW9kdWxlUmVmLCBtb2R1bGVOYW1lKVxuICAgICAgYXdhaXQgdGhpcy5yZXNvbHZlci5yZXNvbHZlSW5zdGFuY2VzKG1vZHVsZVJlZiwgbW9kdWxlTmFtZSlcbiAgICB9XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwobW9kdWxlRW50cmllcy5tYXAobG9hZE1pZGRsZXdhcmVDb25maWd1cmF0aW9uKSlcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBsb2FkQ29uZmlndXJhdGlvbiAoXG4gICAgbWlkZGxld2FyZUNvbnRhaW5lcjogTWlkZGxld2FyZUNvbnRhaW5lcixcbiAgICBtb2R1bGVSZWY6IE1vZHVsZSxcbiAgICBtb2R1bGVLZXk6IHN0cmluZ1xuICApIHtcbiAgICBjb25zdCB7IGluc3RhbmNlIH0gPSBtb2R1bGVSZWZcbiAgICBpZiAoIWluc3RhbmNlLmNvbmZpZ3VyZSkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGNvbnN0IG1pZGRsZXdhcmVCdWlsZGVyID0gbmV3IE1pZGRsZXdhcmVCdWlsZGVyKFxuICAgICAgdGhpcy5yb3V0ZXNNYXBwZXIsXG4gICAgICB0aGlzLmh0dHBBZGFwdGVyXG4gICAgKVxuICAgIGF3YWl0IGluc3RhbmNlLmNvbmZpZ3VyZShtaWRkbGV3YXJlQnVpbGRlcilcblxuICAgIGlmICghKG1pZGRsZXdhcmVCdWlsZGVyIGluc3RhbmNlb2YgTWlkZGxld2FyZUJ1aWxkZXIpKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgY29uc3QgY29uZmlnID0gbWlkZGxld2FyZUJ1aWxkZXIuYnVpbGQoKVxuICAgIG1pZGRsZXdhcmVDb250YWluZXIuaW5zZXJ0Q29uZmlnKGNvbmZpZywgbW9kdWxlS2V5KVxuICB9XG5cbiAgcHVibGljIGFzeW5jIHJlZ2lzdGVyTWlkZGxld2FyZSAoXG4gICAgbWlkZGxld2FyZUNvbnRhaW5lcjogTWlkZGxld2FyZUNvbnRhaW5lcixcbiAgICBhcHBsaWNhdGlvblJlZjogYW55XG4gICkge1xuICAgIGNvbnN0IGNvbmZpZ3MgPSBtaWRkbGV3YXJlQ29udGFpbmVyLmdldENvbmZpZ3VyYXRpb25zKClcbiAgICBjb25zdCByZWdpc3RlckFsbENvbmZpZ3MgPSBhc3luYyAoXG4gICAgICBtb2R1bGVLZXk6IHN0cmluZyxcbiAgICAgIG1pZGRsZXdhcmVDb25maWc6IE1pZGRsZXdhcmVDb25maWd1cmF0aW9uSW50ZXJmYWNlW11cbiAgICApID0+IHtcbiAgICAgIGZvciAoY29uc3QgY29uZmlnIG9mIG1pZGRsZXdhcmVDb25maWcpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5yZWdpc3Rlck1pZGRsZXdhcmVDb25maWcoXG4gICAgICAgICAgbWlkZGxld2FyZUNvbnRhaW5lcixcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgbW9kdWxlS2V5LFxuICAgICAgICAgIGFwcGxpY2F0aW9uUmVmXG4gICAgICAgIClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBlbnRyaWVzU29ydGVkQnlEaXN0YW5jZSA9IFsuLi5jb25maWdzLmVudHJpZXMoKV0uc29ydChcbiAgICAgIChbbW9kdWxlQV0sIFttb2R1bGVCXSkgPT4ge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIHRoaXMuY29udGFpbmVyLmdldE1vZHVsZUJ5S2V5KG1vZHVsZUEpLmRpc3RhbmNlIC1cbiAgICAgICAgICB0aGlzLmNvbnRhaW5lci5nZXRNb2R1bGVCeUtleShtb2R1bGVCKS5kaXN0YW5jZVxuICAgICAgICApXG4gICAgICB9XG4gICAgKVxuICAgIGZvciAoY29uc3QgW21vZHVsZVJlZiwgbW9kdWxlQ29uZmlndXJhdGlvbnNdIG9mIGVudHJpZXNTb3J0ZWRCeURpc3RhbmNlKSB7XG4gICAgICBhd2FpdCByZWdpc3RlckFsbENvbmZpZ3MobW9kdWxlUmVmLCBbLi4ubW9kdWxlQ29uZmlndXJhdGlvbnNdKVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyByZWdpc3Rlck1pZGRsZXdhcmVDb25maWcgKFxuICAgIG1pZGRsZXdhcmVDb250YWluZXI6IE1pZGRsZXdhcmVDb250YWluZXIsXG4gICAgY29uZmlnOiBNaWRkbGV3YXJlQ29uZmlndXJhdGlvbkludGVyZmFjZSxcbiAgICBtb2R1bGVLZXk6IHN0cmluZyxcbiAgICBhcHBsaWNhdGlvblJlZjogYW55XG4gICkge1xuICAgIGNvbnN0IHsgZm9yUm91dGVzIH0gPSBjb25maWdcbiAgICBmb3IgKGNvbnN0IHJvdXRlSW5mbyBvZiBmb3JSb3V0ZXMpIHtcbiAgICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJSb3V0ZU1pZGRsZXdhcmUoXG4gICAgICAgIG1pZGRsZXdhcmVDb250YWluZXIsXG4gICAgICAgIHJvdXRlSW5mbyBhcyBSb3V0ZUluZm8sXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgbW9kdWxlS2V5LFxuICAgICAgICBhcHBsaWNhdGlvblJlZlxuICAgICAgKVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyByZWdpc3RlclJvdXRlTWlkZGxld2FyZSAoXG4gICAgbWlkZGxld2FyZUNvbnRhaW5lcjogTWlkZGxld2FyZUNvbnRhaW5lcixcbiAgICByb3V0ZUluZm86IFJvdXRlSW5mbyxcbiAgICBjb25maWc6IE1pZGRsZXdhcmVDb25maWd1cmF0aW9uSW50ZXJmYWNlLFxuICAgIG1vZHVsZUtleTogc3RyaW5nLFxuICAgIGFwcGxpY2F0aW9uUmVmOiBhbnlcbiAgKSB7XG4gICAgY29uc3QgbWlkZGxld2FyZUNvbGxlY3Rpb24gPSBbXS5jb25jYXQoY29uZmlnLm1pZGRsZXdhcmUpXG4gICAgY29uc3QgbW9kdWxlUmVmID0gdGhpcy5jb250YWluZXIuZ2V0TW9kdWxlQnlLZXkobW9kdWxlS2V5KVxuXG4gICAgZm9yIChjb25zdCBtZXRhdHlwZSBvZiBtaWRkbGV3YXJlQ29sbGVjdGlvbikge1xuICAgICAgY29uc3QgY29sbGVjdGlvbiA9IG1pZGRsZXdhcmVDb250YWluZXIuZ2V0TWlkZGxld2FyZUNvbGxlY3Rpb24obW9kdWxlS2V5KVxuICAgICAgY29uc3QgaW5zdGFuY2VXcmFwcGVyID0gY29sbGVjdGlvbi5nZXQobWV0YXR5cGUpXG4gICAgICBpZiAoaXNVbmRlZmluZWQoaW5zdGFuY2VXcmFwcGVyKSkge1xuICAgICAgICB0aHJvdyBuZXcgUnVudGltZUV4Y2VwdGlvbigpXG4gICAgICB9XG4gICAgICBpZiAoaW5zdGFuY2VXcmFwcGVyLmlzVHJhbnNpZW50KSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgYXdhaXQgdGhpcy5iaW5kSGFuZGxlcihcbiAgICAgICAgaW5zdGFuY2VXcmFwcGVyLFxuICAgICAgICBhcHBsaWNhdGlvblJlZixcbiAgICAgICAgcm91dGVJbmZvLFxuICAgICAgICBtb2R1bGVSZWYsXG4gICAgICAgIGNvbGxlY3Rpb25cbiAgICAgIClcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJpbmRIYW5kbGVyIChcbiAgICB3cmFwcGVyOiBJbnN0YW5jZVdyYXBwZXI8TWlkZGxld2FyZUludGVyZmFjZT4sXG4gICAgYXBwbGljYXRpb25SZWY6IEh0dHBTZXJ2ZXIsXG4gICAgcm91dGVJbmZvOiBSb3V0ZUluZm8sXG4gICAgbW9kdWxlUmVmOiBNb2R1bGUsXG4gICAgY29sbGVjdGlvbjogTWFwPEluc3RhbmNlVG9rZW5UeXBlLCBJbnN0YW5jZVdyYXBwZXI+XG4gICkge1xuICAgIGNvbnN0IHsgaW5zdGFuY2UsIG1ldGFUeXBlIH0gPSB3cmFwcGVyXG4gICAgaWYgKGlzVW5kZWZpbmVkKGluc3RhbmNlPy51c2UpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZE1pZGRsZXdhcmVFeGNlcHRpb24obWV0YVR5cGUubmFtZSlcbiAgICB9XG4gICAgY29uc3QgaXNTdGF0aWMgPSB3cmFwcGVyLmlzRGVwZW5kZW5jeVRyZWVTdGF0aWMoKVxuICAgIGlmIChpc1N0YXRpYykge1xuICAgICAgY29uc3QgcHJveHkgPSBhd2FpdCB0aGlzLmNyZWF0ZVByb3h5KGluc3RhbmNlKVxuICAgICAgcmV0dXJuIHRoaXMucmVnaXN0ZXJIYW5kbGVyKGFwcGxpY2F0aW9uUmVmLCByb3V0ZUluZm8sIHByb3h5KVxuICAgIH1cblxuICAgIGNvbnN0IGlzVHJlZUR1cmFibGUgPSB3cmFwcGVyLmlzRGVwZW5kZW5jeVRyZWVEdXJhYmxlKClcblxuICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJIYW5kbGVyKFxuICAgICAgYXBwbGljYXRpb25SZWYsXG4gICAgICByb3V0ZUluZm8sXG4gICAgICBhc3luYyA8VFJlcXVlc3QsIFRSZXNwb25zZT4oXG4gICAgICAgIHJlcTogVFJlcXVlc3QsXG4gICAgICAgIHJlczogVFJlc3BvbnNlLFxuICAgICAgICBuZXh0OiAoKSA9PiB2b2lkXG4gICAgICApID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCBjb250ZXh0SWQgPSB0aGlzLmdldENvbnRleHRJZChyZXEsIGlzVHJlZUR1cmFibGUpXG4gICAgICAgICAgY29uc3QgY29udGV4dEluc3RhbmNlID0gYXdhaXQgdGhpcy5pbmplY3Rvci5sb2FkUGVyQ29udGV4dChcbiAgICAgICAgICAgIGluc3RhbmNlLFxuICAgICAgICAgICAgbW9kdWxlUmVmLFxuICAgICAgICAgICAgY29sbGVjdGlvbixcbiAgICAgICAgICAgIGNvbnRleHRJZFxuICAgICAgICAgIClcbiAgICAgICAgICBjb25zdCBwcm94eSA9IGF3YWl0IHRoaXMuY3JlYXRlUHJveHk8VFJlcXVlc3QsIFRSZXNwb25zZT4oXG4gICAgICAgICAgICBjb250ZXh0SW5zdGFuY2UsXG4gICAgICAgICAgICBjb250ZXh0SWRcbiAgICAgICAgICApXG4gICAgICAgICAgcmV0dXJuIHByb3h5KHJlcSwgcmVzLCBuZXh0KVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBsZXQgZXhjZXB0aW9uc0hhbmRsZXIgPSB0aGlzLmV4Y2VwdGlvbkZpbHRlcnNDYWNoZS5nZXQoaW5zdGFuY2UudXNlKVxuICAgICAgICAgIGlmICghZXhjZXB0aW9uc0hhbmRsZXIpIHtcbiAgICAgICAgICAgIGV4Y2VwdGlvbnNIYW5kbGVyID0gdGhpcy5yb3V0ZXJFeGNlcHRpb25GaWx0ZXIuY3JlYXRlKFxuICAgICAgICAgICAgICBpbnN0YW5jZSxcbiAgICAgICAgICAgICAgaW5zdGFuY2UudXNlLFxuICAgICAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIHRoaXMuZXhjZXB0aW9uRmlsdGVyc0NhY2hlLnNldChpbnN0YW5jZS51c2UsIGV4Y2VwdGlvbnNIYW5kbGVyKVxuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBob3N0ID0gbmV3IEV4ZWN1dGlvbkNvbnRleHRIb3N0KFtyZXEsIHJlcywgbmV4dF0pXG4gICAgICAgICAgZXhjZXB0aW9uc0hhbmRsZXIubmV4dChlcnIsIGhvc3QpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICApXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNyZWF0ZVByb3h5PFRSZXF1ZXN0ID0gdW5rbm93biwgVFJlc3BvbnNlID0gdW5rbm93bj4gKFxuICAgIGluc3RhbmNlOiBNaWRkbGV3YXJlSW50ZXJmYWNlLFxuICAgIGNvbnRleHRJZCA9IFNUQVRJQ19DT05URVhUXG4gICk6IFByb21pc2U8KHJlcTogVFJlcXVlc3QsIHJlczogVFJlc3BvbnNlLCBuZXh0OiAoKSA9PiB2b2lkKSA9PiB2b2lkPiB7XG4gICAgY29uc3QgZXhjZXB0aW9uc0hhbmRsZXIgPSB0aGlzLnJvdXRlckV4Y2VwdGlvbkZpbHRlci5jcmVhdGUoXG4gICAgICBpbnN0YW5jZSxcbiAgICAgIGluc3RhbmNlLnVzZSxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIGNvbnRleHRJZFxuICAgIClcbiAgICBjb25zdCBtaWRkbGV3YXJlID0gaW5zdGFuY2UudXNlLmJpbmQoaW5zdGFuY2UpXG4gICAgcmV0dXJuIHRoaXMucm91dGVyUHJveHkuY3JlYXRlUHJveHkobWlkZGxld2FyZSwgZXhjZXB0aW9uc0hhbmRsZXIpXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlZ2lzdGVySGFuZGxlciAoXG4gICAgYXBwbGljYXRpb25SZWY6IEh0dHBTZXJ2ZXIsXG4gICAgcm91dGVJbmZvOiBSb3V0ZUluZm8sXG4gICAgcHJveHk6IDxUUmVxdWVzdCwgVFJlc3BvbnNlPihcbiAgICAgIHJlcTogVFJlcXVlc3QsXG4gICAgICByZXM6IFRSZXNwb25zZSxcbiAgICAgIG5leHQ6ICgpID0+IHZvaWRcbiAgICApID0+IHZvaWRcbiAgKSB7XG4gICAgY29uc3QgeyBtZXRob2QgfSA9IHJvdXRlSW5mb1xuICAgIGNvbnN0IHBhdGhzID0gdGhpcy5yb3V0ZUluZm9QYXRoRXh0cmFjdG9yLmV4dHJhY3RQYXRoc0Zyb20ocm91dGVJbmZvKVxuICAgIGNvbnN0IGlzTWV0aG9kQWxsID0gaXNSZXF1ZXN0TWV0aG9kQWxsKG1ldGhvZClcbiAgICBjb25zdCByZXF1ZXN0TWV0aG9kID0gUmVxdWVzdE1ldGhvZFttZXRob2RdXG4gICAgY29uc3Qgcm91dGVyID0gYXdhaXQgYXBwbGljYXRpb25SZWYuY3JlYXRlTWlkZGxld2FyZUZhY3RvcnkobWV0aG9kKVxuICAgIGNvbnN0IG1pZGRsZXdhcmVGdW5jdGlvbiA9IGlzTWV0aG9kQWxsXG4gICAgICA/IHByb3h5XG4gICAgICA6IDxUUmVxdWVzdCwgVFJlc3BvbnNlPihcbiAgICAgICAgICByZXE6IFRSZXF1ZXN0LFxuICAgICAgICAgIHJlczogVFJlc3BvbnNlLFxuICAgICAgICAgIG5leHQ6ICgpID0+IHZvaWRcbiAgICAgICAgKSA9PiB7XG4gICAgICAgICAgaWYgKGFwcGxpY2F0aW9uUmVmLmdldFJlcXVlc3RNZXRob2QocmVxKSA9PT0gcmVxdWVzdE1ldGhvZCkge1xuICAgICAgICAgICAgcmV0dXJuIHByb3h5KHJlcSwgcmVzLCBuZXh0KVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbmV4dCgpXG4gICAgICAgIH1cbiAgICBjb25zdCBwYXRoc1RvQXBwbHlNaWRkbGV3YXJlID0gW11cbiAgICBwYXRocy5zb21lKHBhdGggPT4gcGF0aC5tYXRjaCgvXlxcLz8kLykpXG4gICAgICA/IHBhdGhzVG9BcHBseU1pZGRsZXdhcmUucHVzaCgnLycpXG4gICAgICA6IHBhdGhzVG9BcHBseU1pZGRsZXdhcmUucHVzaCguLi5wYXRocylcbiAgICBwYXRoc1RvQXBwbHlNaWRkbGV3YXJlLmZvckVhY2gocGF0aCA9PiByb3V0ZXIocGF0aCwgbWlkZGxld2FyZUZ1bmN0aW9uKSlcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Q29udGV4dElkIChyZXF1ZXN0OiB1bmtub3duLCBpc1RyZWVEdXJhYmxlOiBib29sZWFuKTogQ29udGV4dElkIHtcbiAgICBjb25zdCBjb250ZXh0SWQgPSBDb250ZXh0SWRGYWN0b3J5LmdldEJ5UmVxdWVzdChyZXF1ZXN0KVxuICAgIGlmICghcmVxdWVzdFtSRVFVRVNUX0NPTlRFWFRfSURdKSB7XG4gICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocmVxdWVzdCwgUkVRVUVTVF9DT05URVhUX0lELCB7XG4gICAgICAgIHZhbHVlOiBjb250ZXh0SWQsXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2VcbiAgICAgIH0pXG5cbiAgICAgIGNvbnN0IHJlcXVlc3RQcm92aWRlclZhbHVlID0gaXNUcmVlRHVyYWJsZSA/IGNvbnRleHRJZC5wYXlsb2FkIDogcmVxdWVzdFxuICAgICAgdGhpcy5jb250YWluZXIucmVnaXN0ZXJSZXF1ZXN0UHJvdmlkZXIocmVxdWVzdFByb3ZpZGVyVmFsdWUsIGNvbnRleHRJZClcbiAgICB9XG4gICAgcmV0dXJuIGNvbnRleHRJZFxuICB9XG59XG4iXX0=