UNPKG

@versatiledatakit/shared

Version:

Versatile Data Kit Shared library enables reusability of shared features like: NgRx Redux, Error Handlers, Utils, Generic Components, etc.

263 lines 40.6 kB
import { __decorate } from "tslib"; /* * Copyright 2023-2025 Broadcom * SPDX-License-Identifier: Apache-2.0 */ import { Injectable } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { take } from 'rxjs/operators'; import { CollectionsUtil } from '../../../utils'; import { SE_NAVIGATE, SystemEventHandler, SystemEventHandlerClass } from '../../system-events'; import { RouteState } from '../../router'; import { RouteStateFactory } from '../../router/factory'; import * as i0 from "@angular/core"; import * as i1 from "@angular/router"; import * as i2 from "../../router"; /** * ** Service should be provided from the Root injector in Application. */ let NavigationService = class NavigationService { /** * ** Constructor. */ constructor(router, routerService) { this.router = router; this.routerService = routerService; this._routeStateFactory = new RouteStateFactory(); } /** * ** Intercept SE_NAVIGATE Event and handle (react) on it. */ _navigationSystemEventHandler_(payload) { if (CollectionsUtil.isNil(payload)) { return Promise.resolve(false); } return this.navigate(payload.url, payload.extras); } /** * ** Navigate to url with provided extras. */ navigate(url, extras) { let urlChunks; if (CollectionsUtil.isArray(url)) { urlChunks = url.map((v, i) => (i === 0 ? `/${v.replace(/^\//, '')}` : v)); } else if (CollectionsUtil.isString(url)) { if (url.trim() === '/') { urlChunks = ['/']; } else { urlChunks = url .split('/') .filter((v) => !!v) .map((v, i) => (i === 0 ? `/${v}` : v)); } } else { return Promise.resolve(false); } return CollectionsUtil.isLiteralObject(extras) ? this.router.navigate(urlChunks, extras) : this.router.navigate(urlChunks); } /** * ** Navigate to using Route config, RouteState and leveraging provided optional replaceValueResolver. * * @param replaceValues is Object with mapping between Replacer.replaceValue key pointer to dynamic value specific for the Page. * - What does it mean? * Replacer has searchValue and replaceValue. When searchValue match, it replace with replaceValue, but * replaceValue could be something like '$.team', '$.job', '{0}', '{1}' etc... dynamic params, so those params * could be key in this Map to construct correct url depending of the logic in RouteConfig. * <p> * Important!!! * - If replaceValues is not provided or some key doesn't exist there, replaceValue would be use as it is in the RouteConfig. * </p> * <p></p> * @param activatedRoute is optional and could be provided if you want those state to be used to extract RouteConfig and NavigationAction. */ navigateTo(replaceValues, activatedRoute) { return this._navigateWithAction(replaceValues, activatedRoute, 'navigateTo'); } /** * ** Navigate back using Route config, RouteState and leveraging provided optional replaceValueResolver. * * @param replaceValues is Object with mapping between Replacer.replaceValue key pointer to dynamic value specific for the Page. * - What does it mean? * Replacer has searchValue and replaceValue. When searchValue match, it replace with replaceValue, but * replaceValue could be something like '$.team', '$.job', '{0}', '{1}' etc... dynamic params, so those params * could be key in this Map to construct correct url depending of the logic in RouteConfig. * <p> * Important!!! * - If replaceValues is not provided or some key doesn't exist there, replaceValue would be use as it is in the RouteConfig. * </p> * <p></p> * @param activatedRoute is optional and could be provided if you want those state to be used to extract RouteConfig and NavigationAction. */ navigateBack(replaceValues, activatedRoute) { return this._navigateWithAction(replaceValues, activatedRoute, 'navigateBack'); } /** * ** Redirect using Route config, RouteState and leveraging provided optional replaceValueResolver. * * @param replaceValues is Object with mapping between Replacer.replaceValue key pointer to dynamic value specific for the Page. * - What does it mean? * Replacer has searchValue and replaceValue. When searchValue match, it replace with replaceValue, but * replaceValue could be something like '$.team', '$.job', '{0}', '{1}' etc... dynamic params, so those params * could be key in this Map to construct correct url depending of the logic in RouteConfig. * <p> * Important!!! * - If replaceValues is not provided or some key doesn't exist there, replaceValue would be use as it is in the RouteConfig. * </p> * <p></p> * @param activatedRoute is optional and could be provided if you want those state to be used to extract RouteConfig and NavigationAction. */ redirect(replaceValues, activatedRoute) { return this._navigateWithAction(replaceValues, activatedRoute, 'redirect'); } /** * ** Resolve NavigationAction using Route config, RouteState and leveraging provided optional replaceValueResolver. * @param navigateActionType is the type of the NavigationAction we want to resolve from Route config. * @param replaceValues is Object with mapping between Replacer.replaceValue key pointer to dynamic value specific for the Page. * - What does it mean? * Replacer has searchValue and replaceValue. When searchValue match, it replace with replaceValue, but * replaceValue could be something like '$.team', '$.job', '{0}', '{1}' etc... dynamic params, so those params * could be key in this Map to construct correct url depending of the logic in RouteConfig. * <p> * Important!!! * - If replaceValues is not provided or some key doesn't exist there, replaceValue would be use as it is in the RouteConfig. * </p> * <p></p> * @param activatedRoute is optional and could be provided if you want those state to be used to extract RouteConfig and NavigationAction. */ resolveNavigateActionUrl(navigateActionType, replaceValues, activatedRoute) { const _replaceValues = CollectionsUtil.isLiteralObject(replaceValues) ? replaceValues : {}; return this._extractRouteState(activatedRoute) .then((state) => this._constructNavigateParameters(state, navigateActionType)) .then((params) => this._resolveNavigateValues(params.url, params.replacers, _replaceValues, params.navigationExtras)); } /** * ** Initialize the Service without any operation, just to create singleton Service instance. * * - It should be done in the root of the project only once. * - Possible place is AppComponent or some root initializer guard. */ initialize() { this.routerService.initialize(); } _navigateWithAction(replaceValues, activatedRoute, dataKey) { return this.resolveNavigateActionUrl(dataKey, replaceValues, activatedRoute) .then() .then(([url, navigationExtras]) => this.navigate(url, navigationExtras)) .catch((error) => { console.error(error); return false; }); } _extractRouteState(activatedRoute) { // NOTICE // this piece of code is needed for Guards cases usage. // Use params and data from Guard RouteState instead from RouterService because // RouterService state is populated after all guards are resolved if (CollectionsUtil.isDefined(activatedRoute)) { if (activatedRoute instanceof RouteState) { return Promise.resolve(activatedRoute); } return Promise.resolve(this._routeStateFactory.create(activatedRoute instanceof ActivatedRoute ? activatedRoute.snapshot : activatedRoute, null)); } return this.routerService .getState() .pipe(take(1)) .toPromise() .then((state) => state); } // eslint-disable-next-line max-len _constructNavigateParameters(state, dataKey) { const navigateAction = state.getData(dataKey); const navigationExtras = { queryParamsHandling: 'merge' }; let url; let replacers = []; if (CollectionsUtil.isDefined(navigateAction)) { url = this._resolveNavigateUrl(state, dataKey, navigateAction); if (CollectionsUtil.isArray(navigateAction.replacers)) { replacers = navigateAction.replacers; } this._appendNavigateExtras(state, navigationExtras, navigateAction); } else if (dataKey === 'navigateBack') { url = state.getParentAbsoluteRoutePath(); } else { return Promise.reject('Cannot navigate without NavigationAction'); } return Promise.resolve({ url, replacers, navigationExtras }); } _resolveNavigateUrl(state, dataKey, navigateAction) { if (dataKey === 'redirect' || dataKey === 'navigateBack') { if (navigateAction.path === '$.parent' || navigateAction.path === '$.requested') { return navigateAction.useConfigPath ? state.getParentAbsoluteConfigPath() : state.getParentAbsoluteRoutePath(); } if (navigateAction.path === '$.current') { return navigateAction.useConfigPath ? state.getAbsoluteConfigPath() : state.getAbsoluteRoutePath(); } return navigateAction.path; } if (navigateAction.path === '$.current') { return navigateAction.useConfigPath ? state.getAbsoluteConfigPath() : state.getAbsoluteRoutePath(); } return navigateAction.path; } // eslint-disable-next-line max-len _appendNavigateExtras(state, navigationExtras, navigateAction) { if (CollectionsUtil.isString(navigateAction.queryParamsHandling)) { navigationExtras.queryParamsHandling = navigateAction.queryParamsHandling; if (navigationExtras.queryParamsHandling === 'merge') { navigationExtras.queryParams = { ...state.queryParams, ...(navigateAction.queryParams ?? {}) }; } else if (navigationExtras.queryParamsHandling !== 'preserve') { navigationExtras.queryParams = navigateAction.queryParams ?? {}; } } else if (CollectionsUtil.isNull(navigateAction.queryParamsHandling)) { delete navigationExtras.queryParamsHandling; } else { navigationExtras.queryParams = { ...state.queryParams, ...(navigateAction.queryParams ?? {}) }; } } _resolveNavigateValues(path, replacers, replaceValues, navigationExtras) { let resolvedPath; if (CollectionsUtil.isString(path)) { resolvedPath = path; } else { resolvedPath = '/'; console.error(`RouteConfig error! NavigationAction config, "path" property is missing.`); } for (const replacer of replacers) { const replaceValue = replaceValues[replacer.replaceValue] ?? replacer.replaceValue; resolvedPath = resolvedPath.replace(replacer.searchValue, replaceValue); } return Promise.resolve([resolvedPath, navigationExtras]); } }; NavigationService.ɵfac = function NavigationService_Factory(t) { return new (t || NavigationService)(i0.ɵɵinject(i1.Router), i0.ɵɵinject(i2.RouterService)); }; NavigationService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: NavigationService, factory: NavigationService.ɵfac }); __decorate([ SystemEventHandler(SE_NAVIGATE) ], NavigationService.prototype, "_navigationSystemEventHandler_", null); NavigationService = __decorate([ SystemEventHandlerClass() ], NavigationService); export { NavigationService }; (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(NavigationService, [{ type: Injectable }], function () { return [{ type: i1.Router }, { type: i2.RouterService }]; }, { _navigationSystemEventHandler_: [] }); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF2aWdhdGlvbi5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc2hhcmVkL3NyYy9saWIvY29yZS9uYXZpZ2F0aW9uL3NlcnZpY2VzL25hdmlnYXRpb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHO0FBRUgsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQUUsY0FBYyxFQUFvRCxNQUFNLGlCQUFpQixDQUFDO0FBRW5HLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV0QyxPQUFPLEVBQWdCLGVBQWUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBSS9ELE9BQU8sRUFBRSxXQUFXLEVBQUUsa0JBQWtCLEVBQUUsdUJBQXVCLEVBQThCLE1BQU0scUJBQXFCLENBQUM7QUFFM0gsT0FBTyxFQUFpQixVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDekQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7Ozs7QUFFekQ7O0dBRUc7SUFHVSxpQkFBaUIsU0FBakIsaUJBQWlCO0lBRzFCOztPQUVHO0lBQ0gsWUFDcUIsTUFBYyxFQUNkLGFBQTRCO1FBRDVCLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxrQkFBYSxHQUFiLGFBQWEsQ0FBZTtRQUU3QyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxpQkFBaUIsRUFBRSxDQUFDO0lBQ3RELENBQUM7SUFFRDs7T0FFRztJQUVILDhCQUE4QixDQUFDLE9BQW1DO1FBQzlELElBQUksZUFBZSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUNoQyxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDakM7UUFFRCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFB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akIsaUJBQWlCLFdBQWpCLGlCQUFpQjtBQWlCMUI7SUFEQyxrQkFBa0IsQ0FBQyxXQUFXLENBQUM7dUVBTy9CO0FBdkJRLGlCQUFpQjtJQUQ3Qix1QkFBdUIsRUFBRTtHQUNiLGlCQUFpQixDQW9TN0I7U0FwU1ksaUJBQWlCO3VGQUFqQixpQkFBaUI7Y0FGN0IsVUFBVTtxRkFtQlAsOEJBQThCIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAyMDIzLTIwMjUgQnJvYWRjb21cbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cblxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUsIEFjdGl2YXRlZFJvdXRlU25hcHNob3QsIE5hdmlnYXRpb25FeHRyYXMsIFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5cbmltcG9ydCB7IHRha2UgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IEFycmF5RWxlbWVudCwgQ29sbGVjdGlvbnNVdGlsIH0gZnJvbSAnLi4vLi4vLi4vdXRpbHMnO1xuXG5pbXBvcnQgeyBSZXBsYWNlciwgVGF1cnVzTmF2aWdhdGVBY3Rpb24gfSBmcm9tICcuLi8uLi8uLi9jb21tb24nO1xuXG5pbXBvcnQgeyBTRV9OQVZJR0FURSwgU3lzdGVtRXZlbnRIYW5kbGVyLCBTeXN0ZW1FdmVudEhhbmRsZXJDbGFzcywgU3lzdGVtRXZlbnROYXZpZ2F0ZVBheWxvYWQgfSBmcm9tICcuLi8uLi9zeXN0ZW0tZXZlbnRzJztcblxuaW1wb3J0IHsgUm91dGVyU2VydmljZSwgUm91dGVTdGF0ZSB9IGZyb20gJy4uLy4uL3JvdXRlcic7XG5pbXBvcnQgeyBSb3V0ZVN0YXRlRmFjdG9yeSB9IGZyb20gJy4uLy4uL3JvdXRlci9mYWN0b3J5JztcblxuLyoqXG4gKiAqKiBTZXJ2aWNlIHNob3VsZCBiZSBwcm92aWRlZCBmcm9tIHRoZSBSb290IGluamVjdG9yIGluIEFwcGxpY2F0aW9uLlxuICovXG5ASW5qZWN0YWJsZSgpXG5AU3lzdGVtRXZlbnRIYW5kbGVyQ2xhc3MoKVxuZXhwb3J0IGNsYXNzIE5hdmlnYXRpb25TZXJ2aWNlIHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9yb3V0ZVN0YXRlRmFjdG9yeTogUm91dGVTdGF0ZUZhY3Rvcnk7XG5cbiAgICAvKipcbiAgICAgKiAqKiBDb25zdHJ1Y3Rvci5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSByb3V0ZXI6IFJvdXRlcixcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSByb3V0ZXJTZXJ2aWNlOiBSb3V0ZXJTZXJ2aWNlXG4gICAgKSB7XG4gICAgICAgIHRoaXMuX3JvdXRlU3RhdGVGYWN0b3J5ID0gbmV3IFJvdXRlU3RhdGVGYWN0b3J5KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogKiogSW50ZXJjZXB0IFNFX05BVklHQVRFIEV2ZW50IGFuZCBoYW5kbGUgKHJlYWN0KSBvbiBpdC5cbiAgICAgKi9cbiAgICBAU3lzdGVtRXZlbnRIYW5kbGVyKFNFX05BVklHQVRFKVxuICAgIF9uYXZpZ2F0aW9uU3lzdGVtRXZlbnRIYW5kbGVyXyhwYXlsb2FkOiBTeXN0ZW1FdmVudE5hdmlnYXRlUGF5bG9hZCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICBpZiAoQ29sbGVjdGlvbnNVdGlsLmlzTmlsKHBheWxvYWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGZhbHNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLm5hdmlnYXRlKHBheWxvYWQudXJsLCBwYXlsb2FkLmV4dHJhcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogKiogTmF2aWdhdGUgdG8gdXJsIHdpdGggcHJvdmlkZWQgZXh0cmFzLlxuICAgICAqL1xuICAgIG5hdmlnYXRlKHVybDogc3RyaW5nIHwgc3RyaW5nW10sIGV4dHJhcz86IE5hdmlnYXRpb25FeHRyYXMpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgbGV0IHVybENodW5rczogc3RyaW5nW107XG5cbiAgICAgICAgaWYgKENvbGxlY3Rpb25zVXRpbC5pc0FycmF5KHVybCkpIHtcbiAgICAgICAgICAgIHVybENodW5rcyA9IHVybC5tYXAoKHYsIGkpID0+IChpID09PSAwID8gYC8ke3YucmVwbGFjZSgvXlxcLy8sICcnKX1gIDogdikpO1xuICAgICAgICB9IGVsc2UgaWYgKENvbGxlY3Rpb25zVXRpbC5pc1N0cmluZyh1cmwpKSB7XG4gICAgICAgICAgICBpZiAodXJsLnRyaW0oKSA9PT0gJy8nKSB7XG4gICAgICAgICAgICAgICAgdXJsQ2h1bmtzID0gWycvJ107XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHVybENodW5rcyA9IHVybFxuICAgICAgICAgICAgICAgICAgICAuc3BsaXQoJy8nKVxuICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKCh2KSA9PiAhIXYpXG4gICAgICAgICAgICAgICAgICAgIC5tYXAoKHYsIGkpID0+IChpID09PSAwID8gYC8ke3Z9YCA6IHYpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIENvbGxlY3Rpb25zVXRpbC5pc0xpdGVyYWxPYmplY3QoZXh0cmFzKSA/IHRoaXMucm91dGVyLm5hdmlnYXRlKHVybENodW5rcywgZXh0cmFzKSA6IHRoaXMucm91dGVyLm5hdmlnYXRlKHVybENodW5rcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogKiogTmF2aWdhdGUgdG8gdXNpbmcgUm91dGUgY29uZmlnLCBSb3V0ZVN0YXRlIGFuZCBsZXZlcmFnaW5nIHByb3ZpZGVkIG9wdGlvbmFsIHJlcGxhY2VWYWx1ZVJlc29sdmVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHJlcGxhY2VWYWx1ZXMgaXMgT2JqZWN0IHdpdGggbWFwcGluZyBiZXR3ZWVuIFJlcGxhY2VyLnJlcGxhY2VWYWx1ZSBrZXkgcG9pbnRlciB0byBkeW5hbWljIHZhbHVlIHNwZWNpZmljIGZvciB0aGUgUGFnZS5cbiAgICAgKiAgICAgIC0gV2hhdCBkb2VzIGl0IG1lYW4/XG4gICAgICogICAgICAgICAgUmVwbGFjZXIgaGFzIHNlYXJjaFZhbHVlIGFuZCByZXBsYWNlVmFsdWUuIFdoZW4gc2VhcmNoVmFsdWUgbWF0Y2gsIGl0IHJlcGxhY2Ugd2l0aCByZXBsYWNlVmFsdWUsIGJ1dFxuICAgICAqICAgICAgICAgICAgICByZXBsYWNlVmFsdWUgY291bGQgYmUgc29tZXRoaW5nIGxpa2UgJyQudGVhbScsICckLmpvYicsICd7MH0nLCAnezF9JyBldGMuLi4gZHluYW1pYyBwYXJhbXMsIHNvIHRob3NlIHBhcmFtc1xuICAgICAqICAgICAgICAgICAgICBjb3VsZCBiZSBrZXkgaW4gdGhpcyBNYXAgdG8gY29uc3RydWN0IGNvcnJlY3QgdXJsIGRlcGVuZGluZyBvZiB0aGUgbG9naWMgaW4gUm91dGVDb25maWcuXG4gICAgICogPHA+XG4gICAgICogSW1wb3J0YW50ISEhXG4gICAgICogICAgICAtIElmIHJlcGxhY2VWYWx1ZXMgaXMgbm90IHByb3ZpZGVkIG9yIHNvbWUga2V5IGRvZXNuJ3QgZXhpc3QgdGhlcmUsIHJlcGxhY2VWYWx1ZSB3b3VsZCBiZSB1c2UgYXMgaXQgaXMgaW4gdGhlIFJvdXRlQ29uZmlnLlxuICAgICAqIDwvcD5cbiAgICAgKiA8cD48L3A+XG4gICAgICogQHBhcmFtIGFjdGl2YXRlZFJvdXRlIGlzIG9wdGlvbmFsIGFuZCBjb3VsZCBiZSBwcm92aWRlZCBpZiB5b3Ugd2FudCB0aG9zZSBzdGF0ZSB0byBiZSB1c2VkIHRvIGV4dHJhY3QgUm91dGVDb25maWcgYW5kIE5hdmlnYXRpb25BY3Rpb24uXG4gICAgICovXG4gICAgbmF2aWdhdGVUbyhcbiAgICAgICAgcmVwbGFjZVZhbHVlcz86IHsgW2tleTogc3RyaW5nXTogQXJyYXlFbGVtZW50PFRhdXJ1c05hdmlnYXRlQWN0aW9uWydyZXBsYWNlcnMnXT5bJ3JlcGxhY2VWYWx1ZSddIH0sXG4gICAgICAgIGFjdGl2YXRlZFJvdXRlPzogQWN0aXZhdGVkUm91dGUgfCBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90XG4gICAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9uYXZpZ2F0ZVdpdGhBY3Rpb24ocmVwbGFjZVZhbHVlcywgYWN0aXZhdGVkUm91dGUsICduYXZpZ2F0ZVRvJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogKiogTmF2aWdhdGUgYmFjayB1c2luZyBSb3V0ZSBjb25maWcsIFJvdXRlU3RhdGUgYW5kIGxldmVyYWdpbmcgcHJvdmlkZWQgb3B0aW9uYWwgcmVwbGFjZVZhbHVlUmVzb2x2ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcmVwbGFjZVZhbHVlcyBpcyBPYmplY3Qgd2l0aCBtYXBwaW5nIGJldHdlZW4gUmVwbGFjZXIucmVwbGFjZVZhbHVlIGtleSBwb2ludGVyIHRvIGR5bmFtaWMgdmFsdWUgc3BlY2lmaWMgZm9yIHRoZSBQYWdlLlxuICAgICAqICAgICAgLSBXaGF0IGRvZXMgaXQgbWVhbj9cbiAgICAgKiAgICAgICAgICBSZXBsYWNlciBoYXMgc2VhcmNoVmFsdWUgYW5kIHJlcGxhY2VWYWx1ZS4gV2hlbiBzZWFyY2hWYWx1ZSBtYXRjaCwgaXQgcmVwbGFjZSB3aXRoIHJlcGxhY2VWYWx1ZSwgYnV0XG4gICAgICogICAgICAgICAgICAgIHJlcGxhY2VWYWx1ZSBjb3VsZCBiZSBzb21ldGhpbmcgbGlrZSAnJC50ZWFtJywgJyQuam9iJywgJ3swfScsICd7MX0nIGV0Yy4uLiBkeW5hbWljIHBhcmFtcywgc28gdGhvc2UgcGFyYW1zXG4gICAgICogICAgICAgICAgICAgIGNvdWxkIGJlIGtleSBpbiB0aGlzIE1hcCB0byBjb25zdHJ1Y3QgY29ycmVjdCB1cmwgZGVwZW5kaW5nIG9mIHRoZSBsb2dpYyBpbiBSb3V0ZUNvbmZpZy5cbiAgICAgKiA8cD5cbiAgICAgKiBJbXBvcnRhbnQhISFcbiAgICAgKiAgICAgIC0gSWYgcmVwbGFjZVZhbHVlcyBpcyBub3QgcHJvdmlkZWQgb3Igc29tZSBrZXkgZG9lc24ndCBleGlzdCB0aGVyZSwgcmVwbGFjZVZhbHVlIHdvdWxkIGJlIHVzZSBhcyBpdCBpcyBpbiB0aGUgUm91dGVDb25maWcuXG4gICAgICogPC9wPlxuICAgICAqIDxwPjwvcD5cbiAgICAgKiBAcGFyYW0gYWN0aXZhdGVkUm91dGUgaXMgb3B0aW9uYWwgYW5kIGNvdWxkIGJlIHByb3ZpZGVkIGlmIHlvdSB3YW50IHRob3NlIHN0YXRlIHRvIGJlIHVzZWQgdG8gZXh0cmFjdCBSb3V0ZUNvbmZpZyBhbmQgTmF2aWdhdGlvbkFjdGlvbi5cbiAgICAgKi9cbiAgICBuYXZpZ2F0ZUJhY2soXG4gICAgICAgIHJlcGxhY2VWYWx1ZXM/OiB7IFtrZXk6IHN0cmluZ106IEFycmF5RWxlbWVudDxUYXVydXNOYXZpZ2F0ZUFjdGlvblsncmVwbGFjZXJzJ10+WydyZXBsYWNlVmFsdWUnXSB9LFxuICAgICAgICBhY3RpdmF0ZWRSb3V0ZT86IEFjdGl2YXRlZFJvdXRlIHwgQWN0aXZhdGVkUm91dGVTbmFwc2hvdFxuICAgICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fbmF2aWdhdGVXaXRoQWN0aW9uKHJlcGxhY2VWYWx1ZXMsIGFjdGl2YXRlZFJvdXRlLCAnbmF2aWdhdGVCYWNrJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogKiogUmVkaXJlY3QgdXNpbmcgUm91dGUgY29uZmlnLCBSb3V0ZVN0YXRlIGFuZCBsZXZlcmFnaW5nIHByb3ZpZGVkIG9wdGlvbmFsIHJlcGxhY2VWYWx1ZVJlc29sdmVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHJlcGxhY2VWYWx1ZXMgaXMgT2JqZWN0IHdpdGggbWFwcGluZyBiZXR3ZWVuIFJlcGxhY2VyLnJlcGxhY2VWYWx1ZSBrZXkgcG9pbnRlciB0byBkeW5hbWljIHZhbHVlIHNwZWNpZmljIGZvciB0aGUgUGFnZS5cbiAgICAgKiAgICAgIC0gV2hhdCBkb2VzIGl0IG1lYW4/XG4gICAgICogICAgICAgICAgUmVwbGFjZXIgaGFzIHNlYXJjaFZhbHVlIGFuZCByZXBsYWNlVmFsdWUuIFdoZW4gc2VhcmNoVmFsdWUgbWF0Y2gsIGl0IHJlcGxhY2Ugd2l0aCByZXBsYWNlVmFsdWUsIGJ1dFxuICAgICAqICAgICAgICAgICAgICByZXBsYWNlVmFsdWUgY291bGQgYmUgc29tZXRoaW5nIGxpa2UgJyQudGVhbScsICckLmpvYicsICd7MH0nLCAnezF9JyBldGMuLi4gZHluYW1pYyBwYXJhbXMsIHNvIHRob3NlIHBhcmFtc1xuICAgICAqICAgICAgICAgICAgICBjb3VsZCBiZSBrZXkgaW4gdGhpcyBNYXAgdG8gY29uc3RydWN0IGNvcnJlY3QgdXJsIGRlcGVuZGluZyBvZiB0aGUgbG9naWMgaW4gUm91dGVDb25maWcuXG4gICAgICogPHA+XG4gICAgICogSW1wb3J0YW50ISEhXG4gICAgICogICAgICAtIElmIHJlcGxhY2VWYWx1ZXMgaXMgbm90IHByb3ZpZGVkIG9yIHNvbWUga2V5IGRvZXNuJ3QgZXhpc3QgdGhlcmUsIHJlcGxhY2VWYWx1ZSB3b3VsZCBiZSB1c2UgYXMgaXQgaXMgaW4gdGhlIFJvdXRlQ29uZmlnLlxuICAgICAqIDwvcD5cbiAgICAgKiA8cD48L3A+XG4gICAgICogQHBhcmFtIGFjdGl2YXRlZFJvdXRlIGlzIG9wdGlvbmFsIGFuZCBjb3VsZCBiZSBwcm92aWRlZCBpZiB5b3Ugd2FudCB0aG9zZSBzdGF0ZSB0byBiZSB1c2VkIHRvIGV4dHJhY3QgUm91dGVDb25maWcgYW5kIE5hdmlnYXRpb25BY3Rpb24uXG4gICAgICovXG4gICAgcmVkaXJlY3QoXG4gICAgICAgIHJlcGxhY2VWYWx1ZXM/OiB7IFtrZXk6IHN0cmluZ106IEFycmF5RWxlbWVudDxUYXVydXNOYXZpZ2F0ZUFjdGlvblsncmVwbGFjZXJzJ10+WydyZXBsYWNlVmFsdWUnXSB9LFxuICAgICAgICBhY3RpdmF0ZWRSb3V0ZT86IEFjdGl2YXRlZFJvdXRlIHwgQWN0aXZhdGVkUm91dGVTbmFwc2hvdFxuICAgICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fbmF2aWdhdGVXaXRoQWN0aW9uKHJlcGxhY2VWYWx1ZXMsIGFjdGl2YXRlZFJvdXRlLCAncmVkaXJlY3QnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAqKiBSZXNvbHZlIE5hdmlnYXRpb25BY3Rpb24gdXNpbmcgUm91dGUgY29uZmlnLCBSb3V0ZVN0YXRlIGFuZCBsZXZlcmFnaW5nIHByb3ZpZGVkIG9wdGlvbmFsIHJlcGxhY2VWYWx1ZVJlc29sdmVyLlxuICAgICAqIEBwYXJhbSBuYXZpZ2F0ZUFjdGlvblR5cGUgaXMgdGhlIHR5cGUgb2YgdGhlIE5hdmlnYXRpb25BY3Rpb24gd2Ugd2FudCB0byByZXNvbHZlIGZyb20gUm91dGUgY29uZmlnLlxuICAgICAqIEBwYXJhbSByZXBsYWNlVmFsdWVzIGlzIE9iamVjdCB3aXRoIG1hcHBpbmcgYmV0d2VlbiBSZXBsYWNlci5yZXBsYWNlVmFsdWUga2V5IHBvaW50ZXIgdG8gZHluYW1pYyB2YWx1ZSBzcGVjaWZpYyBmb3IgdGhlIFBhZ2UuXG4gICAgICogICAgICAtIFdoYXQgZG9lcyBpdCBtZWFuP1xuICAgICAqICAgICAgICAgIFJlcGxhY2VyIGhhcyBzZWFyY2hWYWx1ZSBhbmQgcmVwbGFjZVZhbHVlLiBXaGVuIHNlYXJjaFZhbHVlIG1hdGNoLCBpdCByZXBsYWNlIHdpdGggcmVwbGFjZVZhbHVlLCBidXRcbiAgICAgKiAgICAgICAgICAgICAgcmVwbGFjZVZhbHVlIGNvdWxkIGJlIHNvbWV0aGluZyBsaWtlICckLnRlYW0nLCAnJC5qb2InLCAnezB9JywgJ3sxfScgZXRjLi4uIGR5bmFtaWMgcGFyYW1zLCBzbyB0aG9zZSBwYXJhbXNcbiAgICAgKiAgICAgICAgICAgICAgY291bGQgYmUga2V5IGluIHRoaXMgTWFwIHRvIGNvbnN0cnVjdCBjb3JyZWN0IHVybCBkZXBlbmRpbmcgb2YgdGhlIGxvZ2ljIGluIFJvdXRlQ29uZmlnLlxuICAgICAqIDxwPlxuICAgICAqIEltcG9ydGFudCEhIVxuICAgICAqICAgICAgLSBJZiByZXBsYWNlVmFsdWVzIGlzIG5vdCBwcm92aWRlZCBvciBzb21lIGtleSBkb2Vzbid0IGV4aXN0IHRoZXJlLCByZXBsYWNlVmFsdWUgd291bGQgYmUgdXNlIGFzIGl0IGlzIGluIHRoZSBSb3V0ZUNvbmZpZy5cbiAgICAgKiA8L3A+XG4gICAgICogPHA+PC9wPlxuICAgICAqIEBwYXJhbSBhY3RpdmF0ZWRSb3V0ZSBpcyBvcHRpb25hbCBhbmQgY291bGQgYmUgcHJvdmlkZWQgaWYgeW91IHdhbnQgdGhvc2Ugc3RhdGUgdG8gYmUgdXNlZCB0byBleHRyYWN0IFJvdXRlQ29uZmlnIGFuZCBOYXZpZ2F0aW9uQWN0aW9uLlxuICAgICAqL1xuICAgIHJlc29sdmVOYXZpZ2F0ZUFjdGlvblVybChcbiAgICAgICAgbmF2aWdhdGVBY3Rpb25UeXBlOiAnbmF2aWdhdGVUbycgfCAnbmF2aWdhdGVCYWNrJyB8ICdyZWRpcmVjdCcsXG4gICAgICAgIHJlcGxhY2VWYWx1ZXM/OiB7IFtrZXk6IHN0cmluZ106IEFycmF5RWxlbWVudDxUYXVydXNOYXZpZ2F0ZUFjdGlvblsncmVwbGFjZXJzJ10+WydyZXBsYWNlVmFsdWUnXSB9LFxuICAgICAgICBhY3RpdmF0ZWRSb3V0ZT86IEFjdGl2YXRlZFJvdXRlIHwgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCB8IFJvdXRlU3RhdGVcbiAgICApOiBQcm9taXNlPFtzdHJpbmcsIE5hdmlnYXRpb25FeHRyYXNdPiB7XG4gICAgICAgIGNvbnN0IF9yZXBsYWNlVmFsdWVzID0gQ29sbGVjdGlvbnNVdGlsLmlzTGl0ZXJhbE9iamVjdChyZXBsYWNlVmFsdWVzKSA/IHJlcGxhY2VWYWx1ZXMgOiB7fTtcblxuICAgICAgICByZXR1cm4gdGhpcy5fZXh0cmFjdFJvdXRlU3RhdGUoYWN0aXZhdGVkUm91dGUpXG4gICAgICAgICAgICAudGhlbigoc3RhdGUpID0+IHRoaXMuX2NvbnN0cnVjdE5hdmlnYXRlUGFyYW1ldGVycyhzdGF0ZSwgbmF2aWdhdGVBY3Rpb25UeXBlKSlcbiAgICAgICAgICAgIC50aGVuKChwYXJhbXMpID0+IHRoaXMuX3Jlc29sdmVOYXZpZ2F0ZVZhbHVlcyhwYXJhbXMudXJsLCBwYXJhbXMucmVwbGFjZXJzLCBfcmVwbGFjZVZhbHVlcywgcGFyYW1zLm5hdmlnYXRpb25FeHRyYXMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAqKiBJbml0aWFsaXplIHRoZSBTZXJ2aWNlIHdpdGhvdXQgYW55IG9wZXJhdGlvbiwganVzdCB0byBjcmVhdGUgc2luZ2xldG9uIFNlcnZpY2UgaW5zdGFuY2UuXG4gICAgICpcbiAgICAgKiAgIC0gSXQgc2hvdWxkIGJlIGRvbmUgaW4gdGhlIHJvb3Qgb2YgdGhlIHByb2plY3Qgb25seSBvbmNlLlxuICAgICAqICAgLSBQb3NzaWJsZSBwbGFjZSBpcyBBcHBDb21wb25lbnQgb3Igc29tZSByb290IGluaXRpYWxpemVyIGd1YXJkLlxuICAgICAqL1xuICAgIGluaXRpYWxpemUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMucm91dGVyU2VydmljZS5pbml0aWFsaXplKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfbmF2aWdhdGVXaXRoQWN0aW9uKFxuICAgICAgICByZXBsYWNlVmFsdWVzOiB7IFtrZXk6IHN0cmluZ106IEFycmF5RWxlbWVudDxUYXVydXNOYXZpZ2F0ZUFjdGlvblsncmVwbGFjZXJzJ10+WydyZXBsYWNlVmFsdWUnXSB9LFxuICAgICAgICBhY3RpdmF0ZWRSb3V0ZTogQWN0aXZhdGVkUm91dGUgfCBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LFxuICAgICAgICBkYXRhS2V5OiAnbmF2aWdhdGVUbycgfCAnbmF2aWdhdGVCYWNrJyB8ICdyZWRpcmVjdCdcbiAgICApOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZU5hdmlnYXRlQWN0aW9uVXJsKGRhdGFLZXksIHJlcGxhY2VWYWx1ZXMsIGFjdGl2YXRlZFJvdXRlKVxuICAgICAgICAgICAgLnRoZW4oKVxuICAgICAgICAgICAgLnRoZW4oKFt1cmwsIG5hdmlnYXRpb25FeHRyYXNdKSA9PiB0aGlzLm5hdmlnYXRlKHVybCwgbmF2aWdhdGlvbkV4dHJhcykpXG4gICAgICAgICAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9leHRyYWN0Um91dGVTdGF0ZShhY3RpdmF0ZWRSb3V0ZTogQWN0aXZhdGVkUm91dGUgfCBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90IHwgUm91dGVTdGF0ZSk6IFByb21pc2U8Um91dGVTdGF0ZT4ge1xuICAgICAgICAvLyBOT1RJQ0VcbiAgICAgICAgLy8gdGhpcyBwaWVjZSBvZiBjb2RlIGlzIG5lZWRlZCBmb3IgR3VhcmRzIGNhc2VzIHVzYWdlLlxuICAgICAgICAvLyBVc2UgcGFyYW1zIGFuZCBkYXRhIGZyb20gR3VhcmQgUm91dGVTdGF0ZSBpbnN0ZWFkIGZyb20gUm91dGVyU2VydmljZSBiZWNhdXNlXG4gICAgICAgIC8vIFJvdXRlclNlcnZpY2Ugc3RhdGUgaXMgcG9wdWxhdGVkIGFmdGVyIGFsbCBndWFyZHMgYXJlIHJlc29sdmVkXG4gICAgICAgIGlmIChDb2xsZWN0aW9uc1V0aWwuaXNEZWZpbmVkKGFjdGl2YXRlZFJvdXRlKSkge1xuICAgICAgICAgICAgaWYgKGFjdGl2YXRlZFJvdXRlIGluc3RhbmNlb2YgUm91dGVTdGF0ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoYWN0aXZhdGVkUm91dGUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICAgICAgICAgIHRoaXMuX3JvdXRlU3RhdGVGYWN0b3J5LmNyZWF0ZShhY3RpdmF0ZWRSb3V0ZSBpbnN0YW5jZW9mIEFjdGl2YXRlZFJvdXRlID8gYWN0aXZhdGVkUm91dGUuc25hcHNob3QgOiBhY3RpdmF0ZWRSb3V0ZSwgbnVsbClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5yb3V0ZXJTZXJ2aWNlXG4gICAgICAgICAgICAuZ2V0U3RhdGUoKVxuICAgICAgICAgICAgLnBpcGUodGFrZSgxKSlcbiAgICAgICAgICAgIC50b1Byb21pc2UoKVxuICAgICAgICAgICAgLnRoZW4oKHN0YXRlKSA9PiBzdGF0ZSk7XG4gICAgfVxuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgICBwcml2YXRlIF9jb25zdHJ1Y3ROYXZpZ2F0ZVBhcmFtZXRlcnMoXG4gICAgICAgIHN0YXRlOiBSb3V0ZVN0YXRlLFxuICAgICAgICBkYXRhS2V5OiAnbmF2aWdhdGVUbycgfCAnbmF2aWdhdGVCYWNrJyB8ICdyZWRpcmVjdCdcbiAgICApOiBQcm9taXNlPE5hdmlnYXRpb25QYXJhbWV0ZXJzPiB7XG4gICAgICAgIGNvbnN0IG5hdmlnYXRlQWN0aW9uID0gc3RhdGUuZ2V0RGF0YTxUYXVydXNOYXZpZ2F0ZUFjdGlvbj4oZGF0YUtleSk7XG4gICAgICAgIGNvbnN0IG5hdmlnYXRpb25FeHRyYXM6IE5hdmlnYXRpb25FeHRyYXMgPSB7IHF1ZXJ5UGFyYW1zSGFuZGxpbmc6ICdtZXJnZScgfTtcblxuICAgICAgICBsZXQgdXJsOiBzdHJpbmc7XG4gICAgICAgIGxldCByZXBsYWNlcnM6IEFycmF5PFJlcGxhY2VyPHN0cmluZz4+ID0gW107XG5cbiAgICAgICAgaWYgKENvbGxlY3Rpb25zVXRpbC5pc0RlZmluZWQobmF2aWdhdGVBY3Rpb24pKSB7XG4gICAgICAgICAgICB1cmwgPSB0aGlzLl9yZXNvbHZlTmF2aWdhdGVVcmwoc3RhdGUsIGRhdGFLZXksIG5hdmlnYXRlQWN0aW9uKTtcblxuICAgICAgICAgICAgaWYgKENvbGxlY3Rpb25zVXRpbC5pc0FycmF5KG5hdmlnYXRlQWN0aW9uLnJlcGxhY2VycykpIHtcbiAgICAgICAgICAgICAgICByZXBsYWNlcnMgPSBuYXZpZ2F0ZUFjdGlvbi5yZXBsYWNlcnM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX2FwcGVuZE5hdmlnYXRlRXh0cmFzKHN0YXRlLCBuYXZpZ2F0aW9uRXh0cmFzLCBuYXZpZ2F0ZUFjdGlvbik7XG4gICAgICAgIH0gZWxzZSBpZiAoZGF0YUtleSA9PT0gJ25hdmlnYXRlQmFjaycpIHtcbiAgICAgICAgICAgIHVybCA9IHN0YXRlLmdldFBhcmVudEFic29sdXRlUm91dGVQYXRoKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0Nhbm5vdCBuYXZpZ2F0ZSB3aXRob3V0IE5hdmlnYXRpb25BY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgICAgdXJsLFxuICAgICAgICAgICAgcmVwbGFjZXJzLFxuICAgICAgICAgICAgbmF2aWdhdGlvbkV4dHJhc1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9yZXNvbHZlTmF2aWdhdGVVcmwoXG4gICAgICAgIHN0YXRlOiBSb3V0ZVN0YXRlLFxuICAgICAgICBkYXRhS2V5OiAnbmF2aWdhdGVUbycgfCAnbmF2aWdhdGVCYWNrJyB8ICdyZWRpcmVjdCcsXG4gICAgICAgIG5hdmlnYXRlQWN0aW9uOiBUYXVydXNOYXZpZ2F0ZUFjdGlvblxuICAgICk6IHN0cmluZyB7XG4gICAgICAgIGlmIChkYXRhS2V5ID09PSAncmVkaXJlY3QnIHx8IGRhdGFLZXkgPT09ICduYXZpZ2F0ZUJhY2snKSB7XG4gICAgICAgICAgICBpZiAobmF2aWdhdGVBY3Rpb24ucGF0aCA9PT0gJyQucGFyZW50JyB8fCBuYXZpZ2F0ZUFjdGlvbi5wYXRoID09PSAnJC5yZXF1ZXN0ZWQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5hdmlnYXRlQWN0aW9uLnVzZUNvbmZpZ1BhdGggPyBzdGF0ZS5nZXRQYXJlbnRBYnNvbHV0ZUNvbmZpZ1BhdGgoKSA6IHN0YXRlLmdldFBhcmVudEFic29sdXRlUm91dGVQYXRoKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChuYXZpZ2F0ZUFjdGlvbi5wYXRoID09PSAnJC5jdXJyZW50Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiBuYXZpZ2F0ZUFjdGlvbi51c2VDb25maWdQYXRoID8gc3RhdGUuZ2V0QWJzb2x1dGVDb25maWdQYXRoKCkgOiBzdGF0ZS5nZXRBYnNvbHV0ZVJvdXRlUGF0aCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gbmF2aWdhdGVBY3Rpb24ucGF0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChuYXZpZ2F0ZUFjdGlvbi5wYXRoID09PSAnJC5jdXJyZW50Jykge1xuICAgICAgICAgICAgcmV0dXJuIG5hdmlnYXRlQWN0aW9uLnVzZUNvbmZpZ1BhdGggPyBzdGF0ZS5nZXRBYnNvbHV0ZUNvbmZpZ1BhdGgoKSA6IHN0YXRlLmdldEFic29sdXRlUm91dGVQYXRoKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmF2aWdhdGVBY3Rpb24ucGF0aDtcbiAgICB9XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuICAgIHByaXZhdGUgX2FwcGVuZE5hdmlnYXRlRXh0cmFzKHN0YXRlOiBSb3V0ZVN0YXRlLCBuYXZpZ2F0aW9uRXh0cmFzOiBOYXZpZ2F0aW9uRXh0cmFzLCBuYXZpZ2F0ZUFjdGlvbjogVGF1cnVzTmF2aWdhdGVBY3Rpb24pOiB2b2lkIHtcbiAgICAgICAgaWYgKENvbGxlY3Rpb25zVXRpbC5pc1N0cmluZyhuYXZpZ2F0ZUFjdGlvbi5xdWVyeVBhcmFtc0hhbmRsaW5nKSkge1xuICAgICAgICAgICAgbmF2aWdhdGlvbkV4dHJhcy5xdWVyeVBhcmFtc0hhbmRsaW5nID0gbmF2aWdhdGVBY3Rpb24ucXVlcnlQYXJhbXNIYW5kbGluZztcblxuICAgICAgICAgICAgaWYgKG5hdmlnYXRpb25FeHRyYXMucXVlcnlQYXJhbXNIYW5kbGluZyA9PT0gJ21lcmdlJykge1xuICAgICAgICAgICAgICAgIG5hdmlnYXRpb25FeHRyYXMucXVlcnlQYXJhbXMgPSB7XG4gICAgICAgICAgICAgICAgICAgIC4uLnN0YXRlLnF1ZXJ5UGFyYW1zLFxuICAgICAgICAgICAgICAgICAgICAuLi4obmF2aWdhdGVBY3Rpb24ucXVlcnlQYXJhbXMgPz8ge30pXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobmF2aWdhdGlvbkV4dHJhcy5xdWVyeVBhcmFtc0hhbmRsaW5nICE9PSAncHJlc2VydmUnKSB7XG4gICAgICAgICAgICAgICAgbmF2aWdhdGlvbkV4dHJhcy5xdWVyeVBhcmFtcyA9IG5hdmlnYXRlQWN0aW9uLnF1ZXJ5UGFyYW1zID8/IHt9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKENvbGxlY3Rpb25zVXRpbC5pc051bGwobmF2aWdhdGVBY3Rpb24ucXVlcnlQYXJhbXNIYW5kbGluZykpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBuYXZpZ2F0aW9uRXh0cmFzLnF1ZXJ5UGFyYW1zSGFuZGxpbmc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuYXZpZ2F0aW9uRXh0cmFzLnF1ZXJ5UGFyYW1zID0ge1xuICAgICAgICAgICAgICAgIC4uLnN0YXRlLnF1ZXJ5UGFyYW1zLFxuICAgICAgICAgICAgICAgIC4uLihuYXZpZ2F0ZUFjdGlvbi5xdWVyeVBhcmFtcyA/PyB7fSlcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIF9yZXNvbHZlTmF2aWdhdGVWYWx1ZXMoXG4gICAgICAgIHBhdGg6IHN0cmluZyxcbiAgICAgICAgcmVwbGFjZXJzOiBBcnJheTxSZXBsYWNlcjxzdHJpbmc+PixcbiAgICAgICAgcmVwbGFjZVZhbHVlczogeyBba2V5OiBzdHJpbmddOiBBcnJheUVsZW1lbnQ8VGF1cnVzTmF2aWdhdGVBY3Rpb25bJ3JlcGxhY2VycyddPlsncmVwbGFjZVZhbHVlJ10gfSxcbiAgICAgICAgbmF2aWdhdGlvbkV4dHJhczogTmF2aWdhdGlvbkV4dHJhc1xuICAgICk6IFByb21pc2U8W3N0cmluZywgTmF2aWdhdGlvbkV4dHJhc10+IHtcbiAgICAgICAgbGV0IHJlc29sdmVkUGF0aDogc3RyaW5nO1xuXG4gICAgICAgIGlmIChDb2xsZWN0aW9uc1V0aWwuaXNTdHJpbmcocGF0aCkpIHtcbiAgICAgICAgICAgIHJlc29sdmVkUGF0aCA9IHBhdGg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNvbHZlZFBhdGggPSAnLyc7XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFJvdXRlQ29uZmlnIGVycm9yISBOYXZpZ2F0aW9uQWN0aW9uIGNvbmZpZywgXCJwYXRoXCIgcHJvcGVydHkgaXMgbWlzc2luZy5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoY29uc3QgcmVwbGFjZXIgb2YgcmVwbGFjZXJzKSB7XG4gICAgICAgICAgICBjb25zdCByZXBsYWNlVmFsdWUgPSByZXBsYWNlVmFsdWVzW3JlcGxhY2VyLnJlcGxhY2VWYWx1ZV0gPz8gcmVwbGFjZXIucmVwbGFjZVZhbHVlO1xuXG4gICAgICAgICAgICByZXNvbHZlZFBhdGggPSByZXNvbHZlZFBhdGgucmVwbGFjZShyZXBsYWNlci5zZWFyY2hWYWx1ZSwgcmVwbGFjZVZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoW3Jlc29sdmVkUGF0aCwgbmF2aWdhdGlvbkV4dHJhc10pO1xuICAgIH1cbn1cblxuaW50ZXJmYWNlIE5hdmlnYXRpb25QYXJhbWV0ZXJzIHtcbiAgICB1cmw6IHN0cmluZztcbiAgICByZXBsYWNlcnM6IEFycmF5PFJlcGxhY2VyPHN0cmluZz4+O1xuICAgIG5hdmlnYXRpb25FeHRyYXM6IE5hdmlnYXRpb25FeHRyYXM7XG59XG4iXX0=