UNPKG

@tsclean/core

Version:

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

168 lines 38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RouterExecutionContext = void 0; const context_utils_1 = require("../helpers/context-utils"); const helpers_1 = require("../helpers"); const router_response_controller_1 = require("./router-response-controller"); const enums_1 = require("../enums"); const core_1 = require("../core"); const access_1 = require("../access"); const utils_1 = require("../utils"); const exceptions_1 = require("../exceptions"); class RouterExecutionContext { constructor(paramsFactory, handlersContextCreator, handlersConsumer, accessResourceContextCreator, accessResourceConsumer, interceptorsContextCreator, interceptorsConsumer, applicationRef) { this.paramsFactory = paramsFactory; this.handlersContextCreator = handlersContextCreator; this.handlersConsumer = handlersConsumer; this.accessResourceContextCreator = accessResourceContextCreator; this.accessResourceConsumer = accessResourceConsumer; this.interceptorsContextCreator = interceptorsContextCreator; this.interceptorsConsumer = interceptorsConsumer; this.applicationRef = applicationRef; this.handlerMetadataStorage = new helpers_1.HandlerMetadataStorage(); this.contextUtils = new context_utils_1.ContextUtils(); this.responseController = new router_response_controller_1.RouterResponseController(applicationRef); } create(instance, callback, methodName, moduleKey, requestMethod, contextId = core_1.STATIC_CONTEXT, inquirerId) { const contextType = 'http'; const { argsLength, fnHandleResponse, paramTypes, getParamsMetadata, httpStatusCode, responseHeaders, hasCustomHeaders, } = this.getMetadata(instance, callback, methodName, moduleKey, requestMethod, contextType); const paramsOptions = this.contextUtils.mergeParamsMetaTypes(getParamsMetadata(moduleKey, contextId, inquirerId), paramTypes); const handlers = this.handlersContextCreator.create(instance, callback, moduleKey, contextId, inquirerId); const resources = this.accessResourceContextCreator.create(instance, callback, moduleKey, contextId, inquirerId); const interceptors = this.interceptorsContextCreator.create(instance, callback, moduleKey, contextId, inquirerId); const fnAccessResource = this.createAccessResourceFn(resources, instance, callback, contextType); const fnApplyHandlers = this.createHandlerFn(handlers, paramsOptions); const handler = (args, req, res, next) => async () => { fnApplyHandlers && (await fnApplyHandlers(args, req, res, next)); return callback.apply(instance, args); }; return async (req, res, next) => { const args = this.contextUtils.createNullArray(argsLength); fnAccessResource && (await fnAccessResource([req, res, next])); this.responseController.setStatus(res, httpStatusCode); hasCustomHeaders && this.responseController.setHeaders(res, responseHeaders); const result = await this.interceptorsConsumer.intercept(interceptors, [req, res, next], instance, callback, handler(args, req, res, next), contextType); await fnHandleResponse(result, res, req); }; } getMetadata(instance, callback, methodName, moduleKey, requestMethod, contextType) { const cacheMetadata = this.handlerMetadataStorage.get(instance, methodName); if (cacheMetadata) return cacheMetadata; const metadata = this.contextUtils.reflectCallbackMetadata(instance, methodName, helpers_1.ROUTE_ARGS_METADATA) || {}; const keys = Object.keys(metadata); const argsLength = this.contextUtils.getArgumentsLength(keys, metadata); const paramTypes = this.contextUtils.reflectCallbackParamTypes(instance, methodName); const contextFactory = this.contextUtils.getContextFactory(contextType, instance, callback); const getParamsMetadata = (moduleKey, contextId = core_1.STATIC_CONTEXT, inquirerId) => this.exchangeKeysForValues(keys, metadata, moduleKey, contextId, inquirerId, contextFactory); const paramsMetadata = getParamsMetadata(moduleKey); const isResponseHandled = this.isResponseHandled(instance, methodName, paramsMetadata); const httpRedirectResponse = this.reflectRedirect(callback); const fnHandleResponse = this.createHandleResponseFn(callback, isResponseHandled, httpRedirectResponse); const httpCode = this.reflectHttpStatusCode(callback); const httpStatusCode = httpCode ? httpCode : this.responseController.getStatusByMethod(requestMethod); const responseHeaders = this.reflectResponseHeaders(callback); const hasCustomHeaders = !(0, utils_1.isEmpty)(responseHeaders); const handlerMetadata = { argsLength, fnHandleResponse, paramTypes, getParamsMetadata, httpStatusCode, hasCustomHeaders, responseHeaders, }; this.handlerMetadataStorage.set(instance, methodName, handlerMetadata); return handlerMetadata; } reflectRedirect(callback) { return Reflect.getMetadata(helpers_1.REDIRECT_METADATA, callback); } reflectHttpStatusCode(callback) { return Reflect.getMetadata(helpers_1.HTTP_CODE_METADATA, callback); } reflectRenderTemplate(callback) { return Reflect.getMetadata(helpers_1.RENDER_METADATA, callback); } reflectResponseHeaders(callback) { return Reflect.getMetadata(helpers_1.HEADERS_METADATA, callback) || []; } exchangeKeysForValues(keys, metadata, moduleContext, contextId = core_1.STATIC_CONTEXT, inquirerId, contextFactory) { this.handlersContextCreator.setModuleContext(moduleContext); return keys.map(key => { const { index, data, handlers: handlersCollection } = metadata[key]; const handlers = this.handlersContextCreator.createConcreteContext(handlersCollection, contextId, inquirerId); const type = this.contextUtils.mapParamType(key); if (key.includes(helpers_1.CUSTOM_ROUTE_AGRS_METADATA)) { const { factory } = metadata[key]; const customExtractValue = this.contextUtils.getCustomFactory(factory, data, contextFactory); return { index, extractValue: customExtractValue, type, data, handlers }; } const numericType = Number(type); const extractValue = (req, res, next) => this.paramsFactory.exchangeKeyForValue(numericType, data, { req, res, next, }); return { index, extractValue, type: numericType, data, handlers }; }); } async getParamValue(value, { metaType, type, data }, handlers) { if (!(0, utils_1.isEmpty)(handlers)) { return this.handlersConsumer.apply(value, { metaType, type, data }, handlers); } return value; } isHandlers(type) { return (type === enums_1.RouteParamTypes.BODY || type === enums_1.RouteParamTypes.QUERY || type === enums_1.RouteParamTypes.PARAM || type === enums_1.RouteParamTypes.FILE || type === enums_1.RouteParamTypes.FILES || (0, utils_1.isString)(type)); } createAccessResourceFn(resources, instance, callback, contextType) { const accessResourceFn = async (args) => { const accessResource = await this.accessResourceConsumer.tryAccess(resources, args, instance, callback, contextType); if (!accessResource) throw new exceptions_1.ForbiddenException(access_1.FORBIDDEN_MESSAGE); }; return resources.length ? accessResourceFn : null; } createHandlerFn(handlers, paramsOptions) { const handlersFn = async (args, req, res, next) => { const resolveParamValue = async (param) => { const { index, extractValue, type, data, metaType, handlers: paramHandler, } = param; const value = extractValue(req, res, next); args[index] = this.isHandlers(type) ? await this.getParamValue(value, { metaType, type, data }, handlers.concat(paramHandler)) : value; }; await Promise.all(paramsOptions.map(resolveParamValue)); }; return paramsOptions.length ? handlersFn : null; } createHandleResponseFn(callback, isResponseHandled, redirectResponse, httpStatusCode) { const renderTemplate = this.reflectRenderTemplate(callback); if (renderTemplate) { return async (result, res) => { return await this.responseController.render(result, res, renderTemplate); }; } if (redirectResponse && typeof redirectResponse.url === 'string') { return async (result, res) => { await this.responseController.redirect(result, res, redirectResponse); }; } return async (result, res) => { result = await this.responseController.transformToResult(result); !isResponseHandled && (await this.responseController.apply(result, res, httpStatusCode)); }; } isResponseHandled(instance, methodName, paramsMetadata) { const hasResponseOrNextDecorator = paramsMetadata.some(({ type }) => type === enums_1.RouteParamTypes.RESPONSE || type === enums_1.RouteParamTypes.NEXT); const isPassthroughsEnabled = this.contextUtils.reflectPassThrough(instance, methodName); return hasResponseOrNextDecorator && !isPassthroughsEnabled; } } exports.RouterExecutionContext = RouterExecutionContext; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLWV4ZWN1dGlvbi1jb250ZXh0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JvdXRlci9yb3V0ZXItZXhlY3V0aW9uLWNvbnRleHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNERBQXNEO0FBQ3RELHdDQVNvQjtBQUVwQiw2RUFJc0M7QUFDdEMsb0NBQXdEO0FBVXhELGtDQUlpQjtBQUNqQixzQ0FJbUI7QUFFbkIsb0NBQTJDO0FBQzNDLDhDQUFpRDtBQUVqRCxNQUFhLHNCQUFzQjtJQUsvQixZQUNxQixhQUEwQyxFQUMxQyxzQkFBOEMsRUFDOUMsZ0JBQWtDLEVBQ2xDLDRCQUEwRCxFQUMxRCxzQkFBOEMsRUFDOUMsMEJBQXNELEVBQ3RELG9CQUEwQyxFQUNsRCxjQUEwQjtRQVBsQixrQkFBYSxHQUFiLGFBQWEsQ0FBNkI7UUFDMUMsMkJBQXNCLEdBQXRCLHNCQUFzQixDQUF3QjtRQUM5QyxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWtCO1FBQ2xDLGlDQUE0QixHQUE1Qiw0QkFBNEIsQ0FBOEI7UUFDMUQsMkJBQXNCLEdBQXRCLHNCQUFzQixDQUF3QjtRQUM5QywrQkFBMEIsR0FBMUIsMEJBQTBCLENBQTRCO1FBQ3RELHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBc0I7UUFDbEQsbUJBQWMsR0FBZCxjQUFjLENBQVk7UUFadEIsMkJBQXNCLEdBQUcsSUFBSSxnQ0FBc0IsRUFBRSxDQUFDO1FBQ3RELGlCQUFZLEdBQUcsSUFBSSw0QkFBWSxFQUFFLENBQUM7UUFhL0MsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUkscURBQXdCLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDM0UsQ0FBQztJQUVNLE1BQU0sQ0FBQyxRQUF3QixFQUN4QixRQUFxQyxFQUNyQyxVQUFrQixFQUNsQixTQUFpQixFQUNqQixhQUE0QixFQUM1QixTQUFTLEdBQUcscUJBQWMsRUFDMUIsVUFBbUI7UUFDN0IsTUFBTSxXQUFXLEdBQWdC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Q0FBQyxRQUFRLElBQUksSUFBSSxLQUFLLHVCQUFlLENBQUMsSUFBSSxDQUNqRixDQUFDO1FBQ0YsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLGtCQUFrQixDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUN6RixPQUFPLDBCQUEwQixJQUFJLENBQUMscUJBQXFCLENBQUM7SUFDaEUsQ0FBQztDQUNKO0FBMVFELHdEQTBRQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Q29udGV4dFV0aWxzfSBmcm9tICcuLi9oZWxwZXJzL2NvbnRleHQtdXRpbHMnO1xuaW1wb3J0IHtcbiAgICBIYW5kbGVyTWV0YWRhdGFTdG9yYWdlLFxuICAgIEV4ZWN1dGlvbkNvbnRleHRIb3N0LFxuICAgIFJPVVRFX0FSR1NfTUVUQURBVEEsXG4gICAgUkVESVJFQ1RfTUVUQURBVEEsXG4gICAgSFRUUF9DT0RFX01FVEFEQVRBLFxuICAgIFJFTkRFUl9NRVRBREFUQSxcbiAgICBIRUFERVJTX01FVEFEQVRBLFxuICAgIENVU1RPTV9ST1VURV9BR1JTX01FVEFEQVRBLFxufSBmcm9tICcuLi9oZWxwZXJzJztcbmltcG9ydCB7SW50ZXJjZXB0b3JzQ29uc3VtZXIsIEludGVyY2VwdG9yc0NvbnRleHRDcmVhdG9yfSBmcm9tICcuLi9pbnRlcmNlcHRvcnMnO1xuaW1wb3J0IHtcbiAgICBDdXN0b21IZWFkZXIsXG4gICAgUmVkaXJlY3RSZXNwb25zZSxcbiAgICBSb3V0ZXJSZXNwb25zZUNvbnRyb2xsZXIsXG59IGZyb20gJy4vcm91dGVyLXJlc3BvbnNlLWNvbnRyb2xsZXInO1xuaW1wb3J0IHtSZXF1ZXN0TWV0aG9kLCBSb3V0ZVBhcmFtVHlwZXN9IGZyb20gXCIuLi9lbnVtc1wiO1xuaW1wb3J0IHtSb3V0ZVBhcmFtTWV0YWRhdGF9IGZyb20gXCIuLi9kZWNvcmF0b3JzXCI7XG5pbXBvcnQge1xuICAgIEFjY2Vzc1Jlc291cmNlSW50ZXJmYWNlLFxuICAgIEhhbmRsZXJNZXRhZGF0YUludGVyZmFjZSxcbiAgICBIdHRwU2VydmVyLFxuICAgIFBhcmFtUHJvcGVydGllc0ludGVyZmFjZSxcbiAgICBIYW5kbGVyVHJhbnNmb3JtLFxuICAgIFJvdXRlUGFyYW1zRmFjdG9yeUludGVyZmFjZVxufSBmcm9tIFwiLi4vY29udHJhY3RzXCI7XG5pbXBvcnQge1xuICAgIEhhbmRsZXJzQ29uc3VtZXIsXG4gICAgSGFuZGxlcnNDb250ZXh0Q3JlYXRvcixcbiAgICBTVEFUSUNfQ09OVEVYVFxufSBmcm9tIFwiLi4vY29yZVwiO1xuaW1wb3J0IHtcbiAgICBBY2Nlc3NSZXNvdXJjZUNvbnN1bWVyLFxuICAgIEFjY2Vzc1Jlc291cmNlQ29udGV4dENyZWF0b3IsXG4gICAgRk9SQklEREVOX01FU1NBR0Vcbn0gZnJvbSBcIi4uL2FjY2Vzc1wiO1xuaW1wb3J0IHtDb250ZXh0VHlwZSwgQ29udHJvbGxlclR5cGUsIEhhbmRsZXJSZXNwb25zZVR5cGV9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHtpc0VtcHR5LCBpc1N0cmluZ30gZnJvbSBcIi4uL3V0aWxzXCI7XG5pbXBvcnQge0ZvcmJpZGRlbkV4Y2VwdGlvbn0gZnJvbSBcIi4uL2V4Y2VwdGlvbnNcIjtcblxuZXhwb3J0IGNsYXNzIFJvdXRlckV4ZWN1dGlvbkNvbnRleHQge1xuICAgIHByaXZhdGUgcmVhZG9ubHkgaGFuZGxlck1ldGFkYXRhU3RvcmFnZSA9IG5ldyBIYW5kbGVyTWV0YWRhdGFTdG9yYWdlKCk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBjb250ZXh0VXRpbHMgPSBuZXcgQ29udGV4dFV0aWxzKCk7XG4gICAgcHJpdmF0ZSByZWFkb25seSByZXNwb25zZUNvbnRyb2xsZXI6IFJvdXRlclJlc3BvbnNlQ29udHJvbGxlcjtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIHJlYWRvbmx5IHBhcmFtc0ZhY3Rvcnk6IFJvdXRlUGFyYW1zRmFjdG9yeUludGVyZmFjZSxcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBoYW5kbGVyc0NvbnRleHRDcmVhdG9yOiBIYW5kbGVyc0NvbnRleHRDcmVhdG9yLFxuICAgICAgICBwcml2YXRlIHJlYWRvbmx5IGhhbmRsZXJzQ29uc3VtZXI6IEhhbmRsZXJzQ29uc3VtZXIsXG4gICAgICAgIHByaXZhdGUgcmVhZG9ubHkgYWNjZXNzUmVzb3VyY2VDb250ZXh0Q3JlYXRvcjogQWNjZXNzUmVzb3VyY2VDb250ZXh0Q3JlYXRvcixcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBhY2Nlc3NSZXNvdXJjZUNvbnN1bWVyOiBBY2Nlc3NSZXNvdXJjZUNvbnN1bWVyLFxuICAgICAgICBwcml2YXRlIHJlYWRvbmx5IGludGVyY2VwdG9yc0NvbnRleHRDcmVhdG9yOiBJbnRlcmNlcHRvcnNDb250ZXh0Q3JlYXRvcixcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBpbnRlcmNlcHRvcnNDb25zdW1lcjogSW50ZXJjZXB0b3JzQ29uc3VtZXIsXG4gICAgICAgIHJlYWRvbmx5IGFwcGxpY2F0aW9uUmVmOiBIdHRwU2VydmVyLFxuICAgICkge1xuICAgICAgICB0aGlzLnJlc3BvbnNlQ29udHJvbGxlciA9IG5ldyBSb3V0ZXJSZXNwb25zZUNvbnRyb2xsZXIoYXBwbGljYXRpb25SZWYpO1xuICAgIH1cblxuICAgIHB1YmxpYyBjcmVhdGUoaW5zdGFuY2U6IENvbnRyb2xsZXJUeXBlLFxuICAgICAgICAgICAgICAgICAgY2FsbGJhY2s6ICguLi5hcmdzOiBhbnlbXSkgPT4gdW5rbm93bixcbiAgICAgICAgICAgICAgICAgIG1ldGhvZE5hbWU6IHN0cmluZyxcbiAgICAgICAgICAgICAgICAgIG1vZHVsZUtleTogc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgcmVxdWVzdE1ldGhvZDogUmVxdWVzdE1ldGhvZCxcbiAgICAgICAgICAgICAgICAgIGNvbnRleHRJZCA9IFNUQVRJQ19DT05URVhULFxuICAgICAgICAgICAgICAgICAgaW5xdWlyZXJJZD86IHN0cmluZykge1xuICAgICAgICBjb25zdCBjb250ZXh0VHlwZTogQ29udGV4dFR5cGUgPSAnaHR0cCc7XG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICAgIGFyZ3NMZW5ndGgsXG4gICAgICAgICAgICBmbkhhbmRsZVJlc3BvbnNlLFxuICAgICAgICAgICAgcGFyYW1UeXBlcyxcbiAgICAgICAgICAgIGdldFBhcmFtc01ldGFkYXRhLFxuICAgICAgICAgICAgaHR0cFN0YXR1c0NvZGUsXG4gICAgICAgICAgICByZXNwb25zZUhlYWRlcnMsXG4gICAgICAgICAgICBoYXNDdXN0b21IZWFkZXJzLFxuICAgICAgICB9ID0gdGhpcy5nZXRNZXRhZGF0YShpbnN0YW5jZSwgY2FsbGJhY2ssIG1ldGhvZE5hbWUsIG1vZHVsZUtleSwgcmVxdWVzdE1ldGhvZCwgY29udGV4dFR5cGUpO1xuXG4gICAgICAgIGNvbnN0IHBhcmFtc09wdGlvbnMgPSB0aGlzLmNvbnRleHRVdGlscy5tZXJnZVBhcmFtc01ldGFUeXBlcyhcbiAgICAgICAgICAgIGdldFBhcmFtc01ldGFkYXRhKG1vZHVsZUtleSwgY29udGV4dElkLCBpbnF1aXJlcklkKSwgcGFyYW1UeXBlcyk7XG5cbiAgICAgICAgY29uc3QgaGFuZGxlcnMgPSB0aGlzLmhhbmRsZXJzQ29udGV4dENyZWF0b3IuY3JlYXRlKFxuICAgICAgICAgICAgaW5zdGFuY2UsIGNhbGxiYWNrLCBtb2R1bGVLZXksIGNvbnRleHRJZCwgaW5xdWlyZXJJZCk7XG5cbiAgICAgICAgY29uc3QgcmVzb3VyY2VzID0gdGhpcy5hY2Nlc3NSZXNvdXJjZUNvbnRleHRDcmVhdG9yLmNyZWF0ZShcbiAgICAgICAgICAgIGluc3RhbmNlLCBjYWxsYmFjaywgbW9kdWxlS2V5LCBjb250ZXh0SWQsIGlucXVpcmVySWQpO1xuXG4gICAgICAgIGNvbnN0IGludGVyY2VwdG9ycyA9IHRoaXMuaW50ZXJjZXB0b3JzQ29udGV4dENyZWF0b3IuY3JlYXRlKFxuICAgICAgICAgICAgaW5zdGFuY2UsIGNhbGxiYWNrLCBtb2R1bGVLZXksIGNvbnRleHRJZCwgaW5xdWlyZXJJZCk7XG5cbiAgICAgICAgY29uc3QgZm5BY2Nlc3NSZXNvdXJjZSA9IHRoaXMuY3JlYXRlQWNjZXNzUmVzb3VyY2VGbihcbiAgICAgICAgICAgIHJlc291cmNlcywgaW5zdGFuY2UsIGNhbGxiYWNrLCBjb250ZXh0VHlwZSk7XG5cbiAgICAgICAgY29uc3QgZm5BcHBseUhhbmRsZXJzID0gdGhpcy5jcmVhdGVIYW5kbGVyRm4oaGFuZGxlcnMsIHBhcmFtc09wdGlvbnMpO1xuXG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSA8VCwgUj4oYXJnczogYW55W10sIHJlcTogVCwgcmVzOiBSLCBuZXh0OiBGdW5jdGlvbikgPT5cbiAgICAgICAgICAgIGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICBmbkFwcGx5SGFuZGxlcnMgJiYgKGF3YWl0IGZuQXBwbHlIYW5kbGVycyhhcmdzLCByZXEsIHJlcywgbmV4dCkpO1xuICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjay5hcHBseShpbnN0YW5jZSwgYXJncyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBhc3luYyA8VCwgUj4ocmVxOiBULCByZXM6IFIsIG5leHQ6IEZ1bmN0aW9uKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBhcmdzID0gdGhpcy5jb250ZXh0VXRpbHMuY3JlYXRlTnVsbEFycmF5KGFyZ3NMZW5ndGgpO1xuICAgICAgICAgICAgZm5BY2Nlc3NSZXNvdXJjZSAmJiAoYXdhaXQgZm5BY2Nlc3NSZXNvdXJjZShbcmVxLCByZXMsIG5leHRdKSk7XG5cbiAgICAgICAgICAgIHRoaXMucmVzcG9uc2VDb250cm9sbGVyLnNldFN0YXR1cyhyZXMsIGh0dHBTdGF0dXNDb2RlKTtcbiAgICAgICAgICAgIGhhc0N1c3RvbUhlYWRlcnMgJiYgdGhpcy5yZXNwb25zZUNvbnRyb2xsZXIuc2V0SGVhZGVycyhyZXMsIHJlc3BvbnNlSGVhZGVycyk7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuaW50ZXJjZXB0b3JzQ29uc3VtZXIuaW50ZXJjZXB0KFxuICAgICAgICAgICAgICAgIGludGVyY2VwdG9ycywgW3JlcSwgcmVzLCBuZXh0XSwgaW5zdGFuY2UsIGNhbGxiYWNrLCBoYW5kbGVyKGFyZ3MsIHJlcSwgcmVzLCBuZXh0KSwgY29udGV4dFR5cGUpO1xuICAgICAgICAgICAgYXdhaXQgKGZuSGFuZGxlUmVzcG9uc2UgYXMgSGFuZGxlclJlc3BvbnNlVHlwZSkocmVzdWx0LCByZXMsIHJlcSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcHVibGljIGdldE1ldGFkYXRhPFQgZXh0ZW5kcyBDb250ZXh0VHlwZSA9IENvbnRleHRUeXBlPihcbiAgICAgICAgaW5zdGFuY2U6IENvbnRyb2xsZXJUeXBlLFxuICAgICAgICBjYWxsYmFjazogKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnksXG4gICAgICAgIG1ldGhvZE5hbWU6IHN0cmluZyxcbiAgICAgICAgbW9kdWxlS2V5OiBzdHJpbmcsXG4gICAgICAgIHJlcXVlc3RNZXRob2Q6IFJlcXVlc3RNZXRob2QsXG4gICAgICAgIGNvbnRleHRUeXBlOiBUKTogSGFuZGxlck1ldGFkYXRhSW50ZXJmYWNlIHtcblxuICAgICAgICBjb25zdCBjYWNoZU1ldGFkYXRhID0gdGhpcy5oYW5kbGVyTWV0YWRhdGFTdG9yYWdlLmdldChpbnN0YW5jZSwgbWV0aG9kTmFtZSk7XG4gICAgICAgIGlmIChjYWNoZU1ldGFkYXRhKSByZXR1cm4gY2FjaGVNZXRhZGF0YTtcblxuICAgICAgICBjb25zdCBtZXRhZGF0YSA9IHRoaXMuY29udGV4dFV0aWxzLnJlZmxlY3RDYWxsYmFja01ldGFkYXRhKFxuICAgICAgICAgICAgaW5zdGFuY2UsIG1ldGhvZE5hbWUsIFJPVVRFX0FSR1NfTUVUQURBVEEpIHx8IHt9O1xuXG4gICAgICAgIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhtZXRhZGF0YSk7XG4gICAgICAgIGNvbnN0IGFyZ3NMZW5ndGggPSB0aGlzLmNvbnRleHRVdGlscy5nZXRBcmd1bWVudHNMZW5ndGgoa2V5cywgbWV0YWRhdGEpO1xuICAgICAgICBjb25zdCBwYXJhbVR5cGVzID0gdGhpcy5jb250ZXh0VXRpbHMucmVmbGVjdENhbGxiYWNrUGFyYW1UeXBlcyhpbnN0YW5jZSwgbWV0aG9kTmFtZSk7XG4gICAgICAgIGNvbnN0IGNvbnRleHRGYWN0b3J5ID0gdGhpcy5jb250ZXh0VXRpbHMuZ2V0Q29udGV4dEZhY3RvcnkoY29udGV4dFR5cGUsIGluc3RhbmNlLCBjYWxsYmFjayk7XG4gICAgICAgIGNvbnN0IGdldFBhcmFtc01ldGFkYXRhID0gKFxuICAgICAgICAgICAgbW9kdWxlS2V5OiBzdHJpbmcsXG4gICAgICAgICAgICBjb250ZXh0SWQgPSBTVEFUSUNfQ09OVEVYVCxcbiAgICAgICAgICAgIGlucXVpcmVySWQ/OiBzdHJpbmcpID0+IHRoaXMuZXhjaGFuZ2VLZXlzRm9yVmFsdWVzKFxuICAgICAgICAgICAga2V5cywgbWV0YWRhdGEsIG1vZHVsZUtleSwgY29udGV4dElkLCBpbnF1aXJlcklkLCBjb250ZXh0RmFjdG9yeSk7XG5cbiAgICAgICAgY29uc3QgcGFyYW1zTWV0YWRhdGEgPSBnZXRQYXJhbXNNZXRhZGF0YShtb2R1bGVLZXkpO1xuICAgICAgICBjb25zdCBpc1Jlc3BvbnNlSGFuZGxlZCA9IHRoaXMuaXNSZXNwb25zZUhhbmRsZWQoaW5zdGFuY2UsIG1ldGhvZE5hbWUsIHBhcmFtc01ldGFkYXRhKTtcblxuICAgICAgICBjb25zdCBodHRwUmVkaXJlY3RSZXNwb25zZSA9IHRoaXMucmVmbGVjdFJlZGlyZWN0KGNhbGxiYWNrKTtcbiAgICAgICAgY29uc3QgZm5IYW5kbGVSZXNwb25zZSA9IHRoaXMuY3JlYXRlSGFuZGxlUmVzcG9uc2VGbihjYWxsYmFjaywgaXNSZXNwb25zZUhhbmRsZWQsIGh0dHBSZWRpcmVjdFJlc3BvbnNlKTtcblxuICAgICAgICBjb25zdCBodHRwQ29kZSA9IHRoaXMucmVmbGVjdEh0dHBTdGF0dXNDb2RlKGNhbGxiYWNrKTtcbiAgICAgICAgY29uc3QgaHR0cFN0YXR1c0NvZGUgPSBodHRwQ29kZVxuICAgICAgICAgICAgPyBodHRwQ29kZSA6IHRoaXMucmVzcG9uc2VDb250cm9sbGVyLmdldFN0YXR1c0J5TWV0aG9kKHJlcXVlc3RNZXRob2QpO1xuXG4gICAgICAgIGNvbnN0IHJlc3BvbnNlSGVhZGVycyA9IHRoaXMucmVmbGVjdFJlc3BvbnNlSGVhZGVycyhjYWxsYmFjayk7XG4gICAgICAgIGNvbnN0IGhhc0N1c3RvbUhlYWRlcnMgPSAhaXNFbXB0eShyZXNwb25zZUhlYWRlcnMpO1xuICAgICAgICBjb25zdCBoYW5kbGVyTWV0YWRhdGE6IEhhbmRsZXJNZXRhZGF0YUludGVyZmFjZSA9IHtcbiAgICAgICAgICAgIGFyZ3NMZW5ndGgsXG4gICAgICAgICAgICBmbkhhbmRsZVJlc3BvbnNlLFxuICAgICAgICAgICAgcGFyYW1UeXBlcyxcbiAgICAgICAgICAgIGdldFBhcmFtc01ldGFkYXRhLFxuICAgICAgICAgICAgaHR0cFN0YXR1c0NvZGUsXG4gICAgICAgICAgICBoYXNDdXN0b21IZWFkZXJzLFxuICAgICAgICAgICAgcmVzcG9uc2VIZWFkZXJzLFxuICAgICAgICB9O1xuICAgICAgICB0aGlzLmhhbmRsZXJNZXRhZGF0YVN0b3JhZ2Uuc2V0KGluc3RhbmNlLCBtZXRob2ROYW1lLCBoYW5kbGVyTWV0YWRhdGEpO1xuICAgICAgICByZXR1cm4gaGFuZGxlck1ldGFkYXRhO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWZsZWN0UmVkaXJlY3QoY2FsbGJhY2s6ICguLi5hcmdzOiB1bmtub3duW10pID0+IHVua25vd24pOiBSZWRpcmVjdFJlc3BvbnNlIHtcbiAgICAgICAgcmV0dXJuIFJlZmxlY3QuZ2V0TWV0YWRhdGEoUkVESVJFQ1RfTUVUQURBVEEsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVmbGVjdEh0dHBTdGF0dXNDb2RlKGNhbGxiYWNrOiAoLi4uYXJnczogdW5rbm93bltdKSA9PiB1bmtub3duKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIFJlZmxlY3QuZ2V0TWV0YWRhdGEoSFRUUF9DT0RFX01FVEFEQVRBLCBjYWxsYmFjayk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlZmxlY3RSZW5kZXJUZW1wbGF0ZShjYWxsYmFjazogKC4uLmFyZ3M6IHVua25vd25bXSkgPT4gdW5rbm93bik6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBSZWZsZWN0LmdldE1ldGFkYXRhKFJFTkRFUl9NRVRBREFUQSwgY2FsbGJhY2spO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWZsZWN0UmVzcG9uc2VIZWFkZXJzKGNhbGxiYWNrOiAoLi4uYXJnczogdW5rbm93bltdKSA9PiB1bmtub3duKTogQ3VzdG9tSGVhZGVyW10ge1xuICAgICAgICByZXR1cm4gUmVmbGVjdC5nZXRNZXRhZGF0YShIRUFERVJTX01FVEFEQVRBLCBjYWxsYmFjaykgfHwgW107XG4gICAgfVxuXG4gICAgcHVibGljIGV4Y2hhbmdlS2V5c0ZvclZhbHVlcyhcbiAgICAgICAga2V5czogc3RyaW5nW10sXG4gICAgICAgIG1ldGFkYXRhOiBSZWNvcmQ8bnVtYmVyLCBSb3V0ZVBhcmFtTWV0YWRhdGE+LFxuICAgICAgICBtb2R1bGVDb250ZXh0OiBzdHJpbmcsXG4gICAgICAgIGNvbnRleHRJZCA9IFNUQVRJQ19DT05URVhULFxuICAgICAgICBpbnF1aXJlcklkPzogc3RyaW5nLFxuICAgICAgICBjb250ZXh0RmFjdG9yeT86IChhcmdzOiB1bmtub3duW10pID0+IEV4ZWN1dGlvbkNvbnRleHRIb3N0KTogUGFyYW1Qcm9wZXJ0aWVzSW50ZXJmYWNlW10ge1xuXG4gICAgICAgIHRoaXMuaGFuZGxlcnNDb250ZXh0Q3JlYXRvci5zZXRNb2R1bGVDb250ZXh0KG1vZHVsZUNvbnRleHQpO1xuXG4gICAgICAgIHJldHVybiBrZXlzLm1hcChrZXkgPT4ge1xuICAgICAgICAgICAgY29uc3Qge2luZGV4LCBkYXRhLCBoYW5kbGVyczogaGFuZGxlcnNDb2xsZWN0aW9ufSA9IG1ldGFkYXRhW2tleV07XG4gICAgICAgICAgICBjb25zdCBoYW5kbGVycyA9IHRoaXMuaGFuZGxlcnNDb250ZXh0Q3JlYXRvci5jcmVhdGVDb25jcmV0ZUNvbnRleHQoXG4gICAgICAgICAgICAgICAgaGFuZGxlcnNDb2xsZWN0aW9uLCBjb250ZXh0SWQsIGlucXVpcmVySWRcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCB0eXBlID0gdGhpcy5jb250ZXh0VXRpbHMubWFwUGFyYW1UeXBlKGtleSk7XG5cbiAgICAgICAgICAgIGlmIChrZXkuaW5jbHVkZXMoQ1VTVE9NX1JPVVRFX0FHUlNfTUVUQURBVEEpKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qge2ZhY3Rvcnl9ID0gbWV0YWRhdGFba2V5XTtcbiAgICAgICAgICAgICAgICBjb25zdCBjdXN0b21FeHRyYWN0VmFsdWUgPSB0aGlzLmNvbnRleHRVdGlscy5nZXRDdXN0b21GYWN0b3J5KFxuICAgICAgICAgICAgICAgICAgICBmYWN0b3J5LCBkYXRhLCBjb250ZXh0RmFjdG9yeSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtpbmRleCwgZXh0cmFjdFZhbHVlOiBjdXN0b21FeHRyYWN0VmFsdWUsIHR5cGUsIGRhdGEsIGhhbmRsZXJzfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgbnVtZXJpY1R5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICBjb25zdCBleHRyYWN0VmFsdWUgPSA8VCwgUj4ocmVxOiBULCByZXM6IFIsIG5leHQ6IEZ1bmN0aW9uKSA9PlxuICAgICAgICAgICAgICAgIHRoaXMucGFyYW1zRmFjdG9yeS5leGNoYW5nZUtleUZvclZhbHVlKG51bWVyaWNUeXBlLCBkYXRhLCB7XG4gICAgICAgICAgICAgICAgICAgIHJlcSwgcmVzLCBuZXh0LFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHtpbmRleCwgZXh0cmFjdFZhbHVlLCB0eXBlOiBudW1lcmljVHlwZSwgZGF0YSwgaGFuZGxlcnN9O1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZ2V0UGFyYW1WYWx1ZTxUPihcbiAgICAgICAgdmFsdWU6IFQsXG4gICAgICAgIHtcbiAgICAgICAgICAgIG1ldGFUeXBlLCB0eXBlLCBkYXRhXG4gICAgICAgIH06IHsgbWV0YVR5cGU6IHVua25vd247IHR5cGU6IFJvdXRlUGFyYW1UeXBlczsgZGF0YTogdW5rbm93biB9LFxuICAgICAgICBoYW5kbGVyczogSGFuZGxlclRyYW5zZm9ybVtdKTogUHJvbWlzZTx1bmtub3duPiB7XG5cbiAgICAgICAgaWYgKCFpc0VtcHR5KGhhbmRsZXJzKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlcnNDb25zdW1lci5hcHBseSh2YWx1ZSwge21ldGFUeXBlLCB0eXBlLCBkYXRhfSBhcyBhbnksIGhhbmRsZXJzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgcHVibGljIGlzSGFuZGxlcnModHlwZTogbnVtYmVyIHwgc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0eXBlID09PSBSb3V0ZVBhcmFtVHlwZXMuQk9EWSB8fFxuICAgICAgICAgICAgdHlwZSA9PT0gUm91dGVQYXJhbVR5cGVzLlFVRVJZIHx8XG4gICAgICAgICAgICB0eXBlID09PSBSb3V0ZVBhcmFtVHlwZXMuUEFSQU0gfHxcbiAgICAgICAgICAgIHR5cGUgPT09IFJvdXRlUGFyYW1UeXBlcy5GSUxFIHx8XG4gICAgICAgICAgICB0eXBlID09PSBSb3V0ZVBhcmFtVHlwZXMuRklMRVMgfHxcbiAgICAgICAgICAgIGlzU3RyaW5nKHR5cGUpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGNyZWF0ZUFjY2Vzc1Jlc291cmNlRm48VCBleHRlbmRzIHN0cmluZyA9IENvbnRleHRUeXBlPihcbiAgICAgICAgcmVzb3VyY2VzOiBBY2Nlc3NSZXNvdXJjZUludGVyZmFjZVtdLFxuICAgICAgICBpbnN0YW5jZTogQ29udHJvbGxlclR5cGUsXG4gICAgICAgIGNhbGxiYWNrOiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgICAgICAgY29udGV4dFR5cGU/OiBUKTogKGFyZ3M6IGFueVtdKSA9PiBQcm9taXNlPHZvaWQ+IHwgbnVsbCB7XG4gICAgICAgIGNvbnN0IGFjY2Vzc1Jlc291cmNlRm4gPSBhc3luYyAoYXJnczogYW55W10pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGFjY2Vzc1Jlc291cmNlID0gYXdhaXQgdGhpcy5hY2Nlc3NSZXNvdXJjZUNvbnN1bWVyLnRyeUFjY2VzczxUPihcbiAgICAgICAgICAgICAgICByZXNvdXJjZXMsIGFyZ3MsIGluc3RhbmNlLCBjYWxsYmFjaywgY29udGV4dFR5cGUpO1xuICAgICAgICAgICAgaWYgKCFhY2Nlc3NSZXNvdXJjZSkgdGhyb3cgbmV3IEZvcmJpZGRlbkV4Y2VwdGlvbihGT1JCSURERU5fTUVTU0FHRSlcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHJlc291cmNlcy5sZW5ndGggPyBhY2Nlc3NSZXNvdXJjZUZuIDogbnVsbDtcbiAgICB9XG5cbiAgICBwdWJsaWMgY3JlYXRlSGFuZGxlckZuKGhhbmRsZXJzOiBIYW5kbGVyVHJhbnNmb3JtW10sIHBhcmFtc09wdGlvbnM6IChQYXJhbVByb3BlcnRpZXNJbnRlcmZhY2UgJiB7IG1ldGFUeXBlPzogYW55IH0pW10pIHtcbiAgICAgICAgY29uc3QgaGFuZGxlcnNGbiA9IGFzeW5jIDxULCBSPihhcmdzOiBhbnlbXSwgcmVxOiBULCByZXM6IFIsIG5leHQ6IEZ1bmN0aW9uKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZXNvbHZlUGFyYW1WYWx1ZSA9IGFzeW5jIChwYXJhbTogUGFyYW1Qcm9wZXJ0aWVzSW50ZXJmYWNlICYgeyBtZXRhVHlwZT86IGFueSB9KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qge1xuICAgICAgICAgICAgICAgICAgICBpbmRleCxcbiAgICAgICAgICAgICAgICAgICAgZXh0cmFjdFZhbHVlLFxuICAgICAgICAgICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgICAgICAgICBtZXRhVHlwZSxcbiAgICAgICAgICAgICAgICAgICAgaGFuZGxlcnM6IHBhcmFtSGFuZGxlcixcbiAgICAgICAgICAgICAgICB9ID0gcGFyYW07XG5cbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGV4dHJhY3RWYWx1ZShyZXEsIHJlcywgbmV4dCk7XG5cbiAgICAgICAgICAgICAgICBhcmdzW2luZGV4XSA9IHRoaXMuaXNIYW5kbGVycyh0eXBlKVxuICAgICAgICAgICAgICAgICAgICA/IGF3YWl0IHRoaXMuZ2V0UGFyYW1WYWx1ZShcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLCB7bWV0YVR5cGUsIHR5cGUsIGRhdGF9IGFzIGFueSwgaGFuZGxlcnMuY29uY2F0KHBhcmFtSGFuZGxlcikpXG4gICAgICAgICAgICAgICAgICAgIDogdmFsdWU7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocGFyYW1zT3B0aW9ucy5tYXAocmVzb2x2ZVBhcmFtVmFsdWUpKTtcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHBhcmFtc09wdGlvbnMubGVuZ3RoID8gaGFuZGxlcnNGbiA6IG51bGw7XG4gICAgfVxuXG4gICAgcHVibGljIGNyZWF0ZUhhbmRsZVJlc3BvbnNlRm4oXG4gICAgICAgIGNhbGxiYWNrOiAoLi4uYXJnczogdW5rbm93bltdKSA9PiB1bmtub3duLFxuICAgICAgICBpc1Jlc3BvbnNlSGFuZGxlZDogYm9vbGVhbixcbiAgICAgICAgcmVkaXJlY3RSZXNwb25zZT86IFJlZGlyZWN0UmVzcG9uc2UsXG4gICAgICAgIGh0dHBTdGF0dXNDb2RlPzogbnVtYmVyLFxuICAgICk6IEhhbmRsZXJSZXNwb25zZVR5cGUge1xuICAgICAgICBjb25zdCByZW5kZXJUZW1wbGF0ZSA9IHRoaXMucmVmbGVjdFJlbmRlclRlbXBsYXRlKGNhbGxiYWNrKTtcbiAgICAgICAgaWYgKHJlbmRlclRlbXBsYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gYXN5bmMgPFQsIFI+KHJlc3VsdDogVCwgcmVzOiBSKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMucmVzcG9uc2VDb250cm9sbGVyLnJlbmRlcihyZXN1bHQsIHJlcywgcmVuZGVyVGVtcGxhdGUpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVkaXJlY3RSZXNwb25zZSAmJiB0eXBlb2YgcmVkaXJlY3RSZXNwb25zZS51cmwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gYXN5bmMgPFQsIFI+KHJlc3VsdDogVCwgcmVzOiBSKSA9PiB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5yZXNwb25zZUNvbnRyb2xsZXIucmVkaXJlY3QocmVzdWx0LCByZXMsIHJlZGlyZWN0UmVzcG9uc2UpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhc3luYyA8VCwgUj4ocmVzdWx0OiBULCByZXM6IFIpID0+IHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGF3YWl0IHRoaXMucmVzcG9uc2VDb250cm9sbGVyLnRyYW5zZm9ybVRvUmVzdWx0KHJlc3VsdCk7XG4gICAgICAgICAgICAhaXNSZXNwb25zZUhhbmRsZWQgJiYgKGF3YWl0IHRoaXMucmVzcG9uc2VDb250cm9sbGVyLmFwcGx5KHJlc3VsdCwgcmVzLCBodHRwU3RhdHVzQ29kZSkpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgaXNSZXNwb25zZUhhbmRsZWQoXG4gICAgICAgIGluc3RhbmNlOiBDb250cm9sbGVyVHlwZSxcbiAgICAgICAgbWV0aG9kTmFtZTogc3RyaW5nLFxuICAgICAgICBwYXJhbXNNZXRhZGF0YTogUGFyYW1Qcm9wZXJ0aWVzSW50ZXJmYWNlW10sXG4gICAgKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IGhhc1Jlc3BvbnNlT3JOZXh0RGVjb3JhdG9yID0gcGFyYW1zTWV0YWRhdGEuc29tZShcbiAgICAgICAgICAgICh7dHlwZX0pID0+IHR5cGUgPT09IFJvdXRlUGFyYW1UeXBlcy5SRVNQT05TRSB8fCB0eXBlID09PSBSb3V0ZVBhcmFtVHlwZXMuTkVYVCxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgaXNQYXNzdGhyb3VnaHNFbmFibGVkID0gdGhpcy5jb250ZXh0VXRpbHMucmVmbGVjdFBhc3NUaHJvdWdoKGluc3RhbmNlLCBtZXRob2ROYW1lKTtcbiAgICAgICAgcmV0dXJuIGhhc1Jlc3BvbnNlT3JOZXh0RGVjb3JhdG9yICYmICFpc1Bhc3N0aHJvdWdoc0VuYWJsZWQ7XG4gICAgfVxufVxuIl19