UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

342 lines • 48.7 kB
import { ActionService, AppStateService, EmptyComponent, gettext, PluginsResolveService, RouterService, ViewContext } from '@c8y/ngx-components'; import { isArray } from 'lodash-es'; import { BehaviorSubject, combineLatest, from, fromEventPattern, merge, Observable, of } from 'rxjs'; import { debounceTime, filter, map, startWith, switchMap, take } from 'rxjs/operators'; import { NgZone } from '@angular/core'; import { ActivationEnd, ResolveEnd, Router } from '@angular/router'; import { ViewContextLegacyParameter } from './ng1/views.provider'; export class BridgeService { constructor(injector, appState, router, ngZone, routerService, actionService, plugins) { this.injector = injector; this.appState = appState; this.router = router; this.ngZone = ngZone; this.routerService = routerService; this.actionService = actionService; this.$liveTabs = new BehaviorSubject([]); this.fixE2eIssues(); this.$ng1RouteChangeSuccess = this.fromNg1Event(this.injector.get('$rootScope'), '$routeChangeSuccess'); this.$ng1RouteChangeStart = this.fromNg1Event(this.injector.get('$rootScope'), '$routeChangeStart'); this.hookLanguage(); this.hookTab(); this.hookNavigator(); this.hookUserMenu(); this.hookViewProvider(); this.hookRoute(); plugins.allPluginsLoaded$ .pipe(filter(tmp => !!tmp), take(1)) .subscribe(() => { this.router.initialNavigation(); }); this.ng1Routes(); } /** * Ensure that angularjs routes are not using any * secondary router outlets */ hookRoute() { this.router.events .pipe(filter(event => event instanceof ResolveEnd), map((event) => event.state.root.firstChild), filter(route => route && route.routeConfig && route.routeConfig.path === '**')) .subscribe((event) => { if (event.root.children.length > 1) { window.location.hash = event.root.children[0].url.toString(); } }); } hookViewProvider() { const c8yViews = this.injector.get('c8yViews'); // fix to trigger an angularjs route change success // event on context route match to make legacy // view-providers resolve. c8yViews.when('/device/:id', { template: '' }); c8yViews.when('/group/:id', { template: '' }); c8yViews.contextViews.subscribe(cfg => this.addRoute(cfg)); } addRoute(cfg) { this.routerService.addRoute({ label: cfg.label || cfg.name, path: cfg.path, icon: cfg.icon, context: ViewContext[cfg.contextKey], priority: cfg.priority, component: EmptyComponent, data: { showIf: cfg.showIf ? ngxRoute => { const params = { ...ngxRoute.params, [ViewContextLegacyParameter[cfg.contextKey]]: ngxRoute.params.id }; const showIfResult = this.injector.invoke(cfg.showIf, undefined, { $routeParams: params }); // make sure showIf result is a promise with boolean result: return this.injector.get('$q').when(showIfResult).then(Boolean); } : undefined }, ...(cfg.featureId && { featureId: cfg.featureId }) }); if (cfg.runPhase) { this.routerService.refresh(); } } ng1Routes() { const template = ''; const fallbackRoutes = []; // tslint:disable-next-line: forin for (const context in ViewContext) { const path = ViewContext[context].match(/(\w+)\//)[1]; const regexp = new RegExp(`^/${path}/(?:([^/]+)).*$`); fallbackRoutes.push({ keys: [{ name: ViewContextLegacyParameter[context], optional: false }], regexp, template }); } /** * When asset detail routes (/device/:id, /group/:id) are matched in Angular Router, ngRoute in * angular.js must also have matching generic routes so that the ids can be extracted from the paths and * injected in multiple calls (showIf, c8yActions, etc) as properties of $routeParams. * * The function in src/ngRoute/route.js (angular.js) where the routes are matched is called parseRoute(). This * function calls angular.forEach and in turn this function checks for the presence of a forEach method before * trying object key iteration. * By attaching a non enumerable forEach method to the routes object we guarantee that the fallback generic routes * are only matched after any other registered through $routeProvider.when. */ const $route = this.injector.get('$route'); Object.defineProperty($route.routes, 'forEach', { // make non enumerable value: function forEach(iterator, context) { // tslint:disable-next-line: forin for (const key in this) { iterator.call(context, this[key], key, this); } fallbackRoutes.forEach(r => iterator.call(context, r)); }, configurable: true }); /** * Some functions use the current context. As some parts are upgraded and some not, the following updates the * angularjs getContext function to resolve always the right context. */ const c8yUiUtil = this.injector.get('c8yUiUtil'); const _getContext = c8yUiUtil.getContext; this.router.events .pipe(filter(event => event instanceof ActivationEnd)) .subscribe((event) => { if (event.snapshot.routeConfig.path === '**') { c8yUiUtil.getContext = _getContext; } else if (event.snapshot.data && event.snapshot.data.context) { c8yUiUtil.getContext = () => { return { context: event.snapshot.data.context.replace('/:id', ''), id: event.snapshot.data.contextData.id, contextData: event.snapshot.data.contextData }; }; } else { c8yUiUtil.getContext = () => ({ context: null, id: null }); } }); } fixE2eIssues() { try { const { ngZone } = this; const { Utils } = window.org.cometd; const timeoutFn = Utils.setTimeout; // tslint:disable-next-line:only-arrow-functions Utils.setTimeout = function (...args) { return ngZone.runOutsideAngular(() => timeoutFn.apply(Utils, args)); }; } catch (e) { // do nothing } try { const { ace } = window; const editFn = ace.edit; const { ngZone } = this; // tslint:disable-next-line:only-arrow-functions ace.edit = function (...args) { return ngZone.runOutsideAngular(() => editFn.apply(ace, args)); }; } catch (e) { // do nothing } } hookLanguage() { let first = true; this.appState .map(store => store.lang) .subscribe(lang => { this.injector.get('c8yLocales').switchToLanguage(lang); if (!first) { this.injector.get('$rootScope').$apply(); } first = false; }); } hookTab() { // Just for instantiation of the c8yAction service this.injector.get('c8yActions'); const $location = this.injector.get('$location'); const c8yTabs = this.injector.get('c8yTabs'); let liveTabs = []; c8yTabs.addTab = tab => { liveTabs.push({ ...tab, label: tab.label || tab.name, path: decodeURIComponent(tab.path) }); this.$liveTabs.next(liveTabs); }; this.$ng1RouteChangeStart.subscribe(() => { liveTabs = []; this.$liveTabs.next(liveTabs); }); this.$ng1RouteChangeSuccess.subscribe(() => { const path = $location.path(); if (this.router.url !== path) { this.router.navigate(path === '/' ? '' : path.split('/'), { queryParams: $location.search(), skipLocationChange: true }); } if (this.actionService) { this.actionService.refresh(); } }); this.$routeChanges = merge(this.$ng1RouteChangeSuccess, this.fromNg1Event(c8yTabs, c8yTabs.EVENT_UPDATE), of(1)).pipe(debounceTime(100)); } hookNavigator() { this.navigationNodes$ = this.injector.get('c8yNavigator').rootNodes$; } getTabs() { const onlyVisible = ({ show }) => show; const upgradeTab = tab => ({ ...tab, label: tab.label || tab.name, path: decodeURIComponent(tab.path) }); const routeTabs = this.$routeChanges.pipe(switchMap(() => { const routes = this.injector.get('c8yTabs').routeTabs; const visibilityPromise = Promise.all(routes.map(({ checkingVisibility }) => checkingVisibility)); return visibilityPromise.then(() => routes.filter(onlyVisible).map(upgradeTab)); }), startWith([])); return combineLatest([routeTabs, this.$liveTabs]).pipe(map(([route, live]) => route.concat(live))); } getQuickLinks() { const c8yQuickLinks = this.injector.get('c8yQuickLinks'); return c8yQuickLinks.list(); } getActionBarItems() { const c8yActionBar = this.injector.get('c8yActionBar'); const $rootScope = this.injector.get('$rootScope'); const getActionBarElements = () => c8yActionBar.elements.map(element => ({ priority: element.getAttribute('action-bar-priority') || 0, template: element, placement: element.getAttribute('action-bar-position') || 'right' })); return this.fromNg1Event($rootScope, 'c8yActionBarChanged').pipe(startWith(1), map(getActionBarElements)); } getBreadcrumbs() { const $location = this.injector.get('$location'); const c8yBreadcrumbs = this.injector.get('c8yBreadcrumbs'); const breadcrumbsUpdate$ = new Observable(subscriber => c8yBreadcrumbs.$on('update', () => subscriber.next())); return breadcrumbsUpdate$.pipe(startWith(0), switchMap(() => { const path = $location.path(); const breadcrumbs = c8yBreadcrumbs.get(path) || {}; const breadcrumbsData = this.resolveBreadcrumbsData(breadcrumbs.data); return from(breadcrumbsData).pipe(map((value) => { const liveBreadcrumbs = c8yBreadcrumbs.getLiveBreadcrumbs(); value = value.concat(liveBreadcrumbs); return value.map(items => ({ items: items })); })); })); } resolveBreadcrumbsData(data) { try { return this.injector.invoke(data); } catch (ex) { // empty } if (isArray(data)) { return of([data]); } return of([]); } getSearch() { const c8ySearch = this.injector.get('c8ySearch'); return c8ySearch.list().map(item => { return { icon: 'search', name: item.name, term: '', onSearch() { if (this.term) { c8ySearch.search(this.term); } } }; }); } getActions() { const registeredActions = this.injector.get('c8yActions').registeredActions; return of(registeredActions .filter(action => !action.hidden) .map(action => ({ // The priority was reversed: Aligned it to dashboard, high first, low last. priority: (action.priority || 0) * -1, label: action.text, icon: action.icon, disabled: action.disabled, action: () => { this.injector.invoke(action.action, action); } }))); } fromNg1Event(obj, evt) { let stopListening; function add(handler) { stopListening = obj.$on(evt, handler); } return fromEventPattern(add, () => stopListening()); } hookUserMenu() { const userMenuService = this.injector.get('c8yUserMenuService'); const c8yAccessDenied = this.injector.get('c8yAccessDenied'); userMenuService.add({ icon: 'access', priority: 10, label: gettext('Access denied requests'), click: c8yAccessDenied.showAccessDeniedRequestsList }); } } export function bridgeServiceFactory(injector, appState, router, ngZone, routerService, actionService, plugins) { return new BridgeService(injector, appState, router, ngZone, routerService, actionService, plugins); } export const bridgeServiceProvider = { provide: BridgeService, useFactory: bridgeServiceFactory, deps: [ '$injector', AppStateService, Router, NgZone, RouterService, ActionService, PluginsResolveService ] }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJpZGdlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi91cGdyYWRlL2JyaWRnZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFHTCxhQUFhLEVBQ2IsZUFBZSxFQUlmLGNBQWMsRUFDZCxPQUFPLEVBQ1AscUJBQXFCLEVBQ3JCLGFBQWEsRUFHYixXQUFXLEVBQ1osTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sRUFDTCxlQUFlLEVBQ2YsYUFBYSxFQUNiLElBQUksRUFDSixnQkFBZ0IsRUFDaEIsS0FBSyxFQUNMLFVBQVUsRUFDVixFQUFFLEVBRUgsTUFBTSxNQUFNLENBQUM7QUFDZCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV2RixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZDLE9BQU8sRUFBMEIsYUFBYSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM1RixPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUVsRSxNQUFNLE9BQU8sYUFBYTtJQU14QixZQUNTLFFBQWEsRUFDWixRQUF5QixFQUMxQixNQUFjLEVBQ2IsTUFBYyxFQUNkLGFBQTRCLEVBQzVCLGFBQTRCLEVBQ3BDLE9BQThCO1FBTnZCLGFBQVEsR0FBUixRQUFRLENBQUs7UUFDWixhQUFRLEdBQVIsUUFBUSxDQUFpQjtRQUMxQixXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQ2IsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBQzVCLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBUnRDLGNBQVMsR0FBbUIsSUFB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LENBQUM7SUFDdEQsQ0FBQztJQUVPLFlBQVk7UUFDbEIsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUNoRSxNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQzdELGVBQWUsQ0FBQyxHQUFHLENBQUM7WUFDbEIsSUFBSSxFQUFFLFFBQVE7WUFDZCxRQUFRLEVBQUUsRUFBRTtZQUNaLEtBQUssRUFBRSxPQUFPLENBQUMsd0JBQXdCLENBQUM7WUFDeEMsS0FBSyxFQUFFLGVBQWUsQ0FBQyw0QkFBNEI7U0FDcEQsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGO0FBRUQsTUFBTSxVQUFVLG9CQUFvQixDQUNsQyxRQUFhLEVBQ2IsUUFBeUIsRUFDekIsTUFBYyxFQUNkLE1BQWMsRUFDZCxhQUE0QixFQUM1QixhQUE0QixFQUM1QixPQUE4QjtJQUU5QixPQUFPLElBQUksYUFBYSxDQUN0QixRQUFRLEVBQ1IsUUFBUSxFQUNSLE1BQU0sRUFDTixNQUFNLEVBQ04sYUFBYSxFQUNiLGFBQWEsRUFDYixPQUFPLENBQ1IsQ0FBQztBQUNKLENBQUM7QUFFRCxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRztJQUNuQyxPQUFPLEVBQUUsYUFBYTtJQUN0QixVQUFVLEVBQUUsb0JBQW9CO0lBQ2hDLElBQUksRUFBRTtRQUNKLFdBQVc7UUFDWCxlQUFlO1FBQ2YsTUFBTTtRQUNOLE1BQU07UUFDTixhQUFhO1FBQ2IsYUFBYTtRQUNiLHFCQUFxQjtLQUN0QjtDQUNGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBY3Rpb24sXG4gIEFjdGlvbkJhckl0ZW0sXG4gIEFjdGlvblNlcnZpY2UsXG4gIEFwcFN0YXRlU2VydmljZSxcbiAgQnJlYWRjcnVtYixcbiAgQnJlYWRjcnVtYkl0ZW0sXG4gIERvY0xpbmssXG4gIEVtcHR5Q29tcG9uZW50LFxuICBnZXR0ZXh0LFxuICBQbHVnaW5zUmVzb2x2ZVNlcnZpY2UsXG4gIFJvdXRlclNlcnZpY2UsXG4gIFNlYXJjaCxcbiAgVGFiLFxuICBWaWV3Q29udGV4dFxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7IGlzQXJyYXkgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHtcbiAgQmVoYXZpb3JTdWJqZWN0LFxuICBjb21iaW5lTGF0ZXN0LFxuICBmcm9tLFxuICBmcm9tRXZlbnRQYXR0ZXJuLFxuICBtZXJnZSxcbiAgT2JzZXJ2YWJsZSxcbiAgb2YsXG4gIFN1YmplY3Rcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUsIGZpbHRlciwgbWFwLCBzdGFydFdpdGgsIHN3aXRjaE1hcCwgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgTmdab25lIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LCBBY3RpdmF0aW9uRW5kLCBSZXNvbHZlRW5kLCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgVmlld0NvbnRleHRMZWdhY3lQYXJhbWV0ZXIgfSBmcm9tICcuL25nMS92aWV3cy5wcm92aWRlcic7XG5cbmV4cG9ydCBjbGFzcyBCcmlkZ2VTZXJ2aWNlIHtcbiAgJHJvdXRlQ2hhbmdlczogT2JzZXJ2YWJsZTxhbnk+O1xuICAkbmcxUm91dGVDaGFuZ2VTdWNjZXNzOiBPYnNlcnZhYmxlPGFueT47XG4gICRuZzFSb3V0ZUNoYW5nZVN0YXJ0OiBPYnNlcnZhYmxlPGFueT47XG4gICRsaXZlVGFiczogU3ViamVjdDxUYWJbXT4gPSBuZXcgQmVoYXZpb3JTdWJqZWN0KFtdKTtcbiAgbmF2aWdhdGlvbk5vZGVzJDogT2JzZXJ2YWJsZTxhbnk+O1xuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgaW5qZWN0b3I6IGFueSxcbiAgICBwcml2YXRlIGFwcFN0YXRlOiBBcHBTdGF0ZVNlcnZpY2UsXG4gICAgcHVibGljIHJvdXRlcjogUm91dGVyLFxuICAgIHByaXZhdGUgbmdab25lOiBOZ1pvbmUsXG4gICAgcHJpdmF0ZSByb3V0ZXJTZXJ2aWNlOiBSb3V0ZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgYWN0aW9uU2VydmljZTogQWN0aW9uU2VydmljZSxcbiAgICBwbHVnaW5zOiBQbHVnaW5zUmVzb2x2ZVNlcnZpY2VcbiAgKSB7XG4gICAgdGhpcy5maXhFMmVJc3N1ZXMoKTtcbiAgICB0aGlzLiRuZzFSb3V0ZUNoYW5nZVN1Y2Nlc3MgPSB0aGlzLmZyb21OZzFFdmVudChcbiAgICAgIHRoaXMuaW5qZWN0b3IuZ2V0KCckcm9vdFNjb3BlJyksXG4gICAgICAnJHJvdXRlQ2hhbmdlU3VjY2VzcydcbiAgICApO1xuICAgIHRoaXMuJG5nMVJvdXRlQ2hhbmdlU3RhcnQgPSB0aGlzLmZyb21OZzFFdmVudChcbiAgICAgIHRoaXMuaW5qZWN0b3IuZ2V0KCckcm9vdFNjb3BlJyksXG4gICAgICAnJHJvdXRlQ2hhbmdlU3RhcnQnXG4gICAgKTtcbiAgICB0aGlzLmhvb2tMYW5ndWFnZSgpO1xuICAgIHRoaXMuaG9va1RhYigpO1xuICAgIHRoaXMuaG9va05hdmlnYXRvcigpO1xuICAgIHRoaXMuaG9va1VzZXJNZW51KCk7XG4gICAgdGhpcy5ob29rVmlld1Byb3ZpZGVyKCk7XG4gICAgdGhpcy5ob29rUm91dGUoKTtcbiAgICBwbHVnaW5zLmFsbFBsdWdpbnNMb2FkZWQkXG4gICAgICAucGlwZShcbiAgICAgICAgZmlsdGVyKHRtcCA9PiAhIXRtcCksXG4gICAgICAgIHRha2UoMSlcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLnJvdXRlci5pbml0aWFsTmF2aWdhdGlvbigpO1xuICAgICAgfSk7XG4gICAgdGhpcy5uZzFSb3V0ZXMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbnN1cmUgdGhhdCBhbmd1bGFyanMgcm91dGVzIGFyZSBub3QgdXNpbmcgYW55XG4gICAqIHNlY29uZGFyeSByb3V0ZXIgb3V0bGV0c1xuICAgKi9cbiAgaG9va1JvdXRlKCkge1xuICAgIHRoaXMucm91dGVyLmV2ZW50c1xuICAgICAgLnBpcGUoXG4gICAgICAgIGZpbHRlcihldmVudCA9PiBldmVudCBpbnN0YW5jZW9mIFJlc29sdmVFbmQpLFxuICAgICAgICBtYXAoKGV2ZW50OiBSZXNvbHZlRW5kKSA9PiBldmVudC5zdGF0ZS5yb290LmZpcnN0Q2hpbGQpLFxuICAgICAgICBmaWx0ZXIocm91dGUgPT4gcm91dGUgJiYgcm91dGUucm91dGVDb25maWcgJiYgcm91dGUucm91dGVDb25maWcucGF0aCA9PT0gJyoqJylcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKGV2ZW50OiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KSA9PiB7XG4gICAgICAgIGlmIChldmVudC5yb290LmNoaWxkcmVuLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaGFzaCA9IGV2ZW50LnJvb3QuY2hpbGRyZW5bMF0udXJsLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgaG9va1ZpZXdQcm92aWRlcigpIHtcbiAgICBjb25zdCBjOHlWaWV3cyA9IHRoaXMuaW5qZWN0b3IuZ2V0KCdjOHlWaWV3cycpO1xuICAgIC8vIGZpeCB0byB0cmlnZ2VyIGFuIGFuZ3VsYXJqcyByb3V0ZSBjaGFuZ2Ugc3VjY2Vzc1xuICAgIC8vIGV2ZW50IG9uIGNvbnRleHQgcm91dGUgbWF0Y2ggdG8gbWFrZSBsZWdhY3lcbiAgICAvLyB2aWV3LXByb3ZpZGVycyByZXNvbHZlLlxuICAgIGM4eVZpZXdzLndoZW4oJy9kZXZpY2UvOmlkJywge1xuICAgICAgdGVtcGxhdGU6ICcnXG4gICAgfSk7XG4gICAgYzh5Vmlld3Mud2hlbignL2dyb3VwLzppZCcsIHtcbiAgICAgIHRlbXBsYXRlOiAnJ1xuICAgIH0pO1xuICAgIGM4eVZpZXdzLmNvbnRleHRWaWV3cy5zdWJzY3JpYmUoY2ZnID0+IHRoaXMuYWRkUm91dGUoY2ZnKSk7XG4gIH1cblxuICBhZGRSb3V0ZShjZmcpIHtcbiAgICB0aGlzLnJvdXRlclNlcnZpY2UuYWRkUm91dGUoe1xuICAgICAgbGFiZWw6IGNmZy5sYWJlbCB8fCBjZmcubmFtZSxcbiAgICAgIHBhdGg6IGNmZy5wYXRoLFxuICAgICAgaWNvbjogY2ZnLmljb24sXG4gICAgICBjb250ZXh0OiBWaWV3Q29udGV4dFtjZmcuY29udGV4dEtleV0gYXMgVmlld0NvbnRleHQsXG4gICAgICBwcmlvcml0eTogY2ZnLnByaW9yaXR5LFxuICAgICAgY29tcG9uZW50OiBFbXB0eUNvbXBvbmVudCxcbiAgICAgIGRhdGE6IHtcbiAgICAgICAgc2hvd0lmOiBjZmcuc2hvd0lmXG4gICAgICAgICAgPyBuZ3hSb3V0ZSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAuLi5uZ3hSb3V0ZS5wYXJhbXMsXG4gICAgICAgICAgICAgICAgW1ZpZXdDb250ZXh0TGVnYWN5UGFyYW1ldGVyW2NmZy5jb250ZXh0S2V5XV06IG5neFJvdXRlLnBhcmFtcy5pZFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBjb25zdCBzaG93SWZSZXN1bHQgPSB0aGlzLmluamVjdG9yLmludm9rZShjZmcuc2hvd0lmLCB1bmRlZmluZWQsIHtcbiAgICAgICAgICAgICAgICAkcm91dGVQYXJhbXM6IHBhcmFtc1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgLy8gbWFrZSBzdXJlIHNob3dJZiByZXN1bHQgaXMgYSBwcm9taXNlIHdpdGggYm9vbGVhbiByZXN1bHQ6XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLmluamVjdG9yLmdldCgnJHEnKS53aGVuKHNob3dJZlJlc3VsdCkudGhlbihCb29sZWFuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICA6IHVuZGVmaW5lZFxuICAgICAgfSxcbiAgICAgIC4uLihjZmcuZmVhdHVyZUlkICYmIHsgZmVhdHVyZUlkOiBjZmcuZmVhdHVyZUlkIH0pXG4gICAgfSk7XG5cbiAgICBpZiAoY2ZnLnJ1blBoYXNlKSB7XG4gICAgICB0aGlzLnJvdXRlclNlcnZpY2UucmVmcmVzaCgpO1xuICAgIH1cbiAgfVxuXG4gIG5nMVJvdXRlcygpIHtcbiAgICBjb25zdCB0ZW1wbGF0ZSA9ICcnO1xuICAgIGNvbnN0IGZhbGxiYWNrUm91dGVzID0gW107XG5cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IGZvcmluXG4gICAgZm9yIChjb25zdCBjb250ZXh0IGluIFZpZXdDb250ZXh0KSB7XG4gICAgICBjb25zdCBwYXRoID0gVmlld0NvbnRleHRbY29udGV4dF0ubWF0Y2goLyhcXHcrKVxcLy8pWzFdO1xuICAgICAgY29uc3QgcmVnZXhwID0gbmV3IFJlZ0V4cChgXi8ke3BhdGh9Lyg/OihbXi9dKykpLiokYCk7XG4gICAgICBmYWxsYmFja1JvdXRlcy5wdXNoKHtcbiAgICAgICAga2V5czogW3sgbmFtZTogVmlld0NvbnRleHRMZWdhY3lQYXJhbWV0ZXJbY29udGV4dF0sIG9wdGlvbmFsOiBmYWxzZSB9XSxcbiAgICAgICAgcmVnZXhwLFxuICAgICAgICB0ZW1wbGF0ZVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2hlbiBhc3NldCBkZXRhaWwgcm91dGVzICgvZGV2aWNlLzppZCwgIC9ncm91cC86aWQpIGFyZSBtYXRjaGVkIGluIEFuZ3VsYXIgUm91dGVyLCBuZ1JvdXRlIGluXG4gICAgICogYW5ndWxhci5qcyBtdXN0IGFsc28gaGF2ZSBtYXRjaGluZyBnZW5lcmljIHJvdXRlcyBzbyB0aGF0IHRoZSBpZHMgY2FuIGJlIGV4dHJhY3RlZCBmcm9tIHRoZSBwYXRocyBhbmRcbiAgICAgKiBpbmplY3RlZCBpbiBtdWx0aXBsZSBjYWxscyAoc2hvd0lmLCBjOHlBY3Rpb25zLCBldGMpIGFzIHByb3BlcnRpZXMgb2YgJHJvdXRlUGFyYW1zLlxuICAgICAqXG4gICAgICogVGhlIGZ1bmN0aW9uIGluIHNyYy9uZ1JvdXRlL3JvdXRlLmpzIChhbmd1bGFyLmpzKSB3aGVyZSB0aGUgcm91dGVzIGFyZSBtYXRjaGVkIGlzIGNhbGxlZCBwYXJzZVJvdXRlKCkuIFRoaXNcbiAgICAgKiBmdW5jdGlvbiBjYWxscyBhbmd1bGFyLmZvckVhY2ggYW5kIGluIHR1cm4gdGhpcyBmdW5jdGlvbiBjaGVja3MgZm9yIHRoZSBwcmVzZW5jZSBvZiBhIGZvckVhY2ggbWV0aG9kIGJlZm9yZVxuICAgICAqIHRyeWluZyBvYmplY3Qga2V5IGl0ZXJhdGlvbi5cbiAgICAgKiBCeSBhdHRhY2hpbmcgYSBub24gZW51bWVyYWJsZSBmb3JFYWNoIG1ldGhvZCB0byB0aGUgcm91dGVzIG9iamVjdCB3ZSBndWFyYW50ZWUgdGhhdCB0aGUgZmFsbGJhY2sgZ2VuZXJpYyByb3V0ZXNcbiAgICAgKiBhcmUgb25seSBtYXRjaGVkIGFmdGVyIGFueSBvdGhlciByZWdpc3RlcmVkIHRocm91Z2ggJHJvdXRlUHJvdmlkZXIud2hlbi5cbiAgICAgKi9cbiAgICBjb25zdCAkcm91dGUgPSB0aGlzLmluamVjdG9yLmdldCgnJHJvdXRlJyk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KCRyb3V0ZS5yb3V0ZXMsICdmb3JFYWNoJywge1xuICAgICAgLy8gbWFrZSBub24gZW51bWVyYWJsZVxuICAgICAgdmFsdWU6IGZ1bmN0aW9uIGZvckVhY2goaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOiBmb3JpblxuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiB0aGlzKSB7XG4gICAgICAgICAgaXRlcmF0b3IuY2FsbChjb250ZXh0LCB0aGlzW2tleV0sIGtleSwgdGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgZmFsbGJhY2tSb3V0ZXMuZm9yRWFjaChyID0+IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgcikpO1xuICAgICAgfSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogU29tZSBmdW5jdGlvbnMgdXNlIHRoZSBjdXJyZW50IGNvbnRleHQuIEFzIHNvbWUgcGFydHMgYXJlIHVwZ3JhZGVkIGFuZCBzb21lIG5vdCwgdGhlIGZvbGxvd2luZyB1cGRhdGVzIHRoZVxuICAgICAqIGFuZ3VsYXJqcyBnZXRDb250ZXh0IGZ1bmN0aW9uIHRvIHJlc29sdmUgYWx3YXlzIHRoZSByaWdodCBjb250ZXh0LlxuICAgICAqL1xuICAgIGNvbnN0IGM4eVVpVXRpbCA9IHRoaXMuaW5qZWN0b3IuZ2V0KCdjOHlVaVV0aWwnKTtcbiAgICBjb25zdCBfZ2V0Q29udGV4dCA9IGM4eVVpVXRpbC5nZXRDb250ZXh0O1xuICAgIHRoaXMucm91dGVyLmV2ZW50c1xuICAgICAgLnBpcGUoZmlsdGVyKGV2ZW50ID0+IGV2ZW50IGluc3RhbmNlb2YgQWN0aXZhdGlvbkVuZCkpXG4gICAgICAuc3Vic2NyaWJlKChldmVudDogQWN0aXZhdGlvbkVuZCkgPT4ge1xuICAgICAgICBpZiAoZXZlbnQuc25hcHNob3Qucm91dGVDb25maWcucGF0aCA9PT0gJyoqJykge1xuICAgICAgICAgIGM4eVVpVXRpbC5nZXRDb250ZXh0ID0gX2dldENvbnRleHQ7XG4gICAgICAgIH0gZWxzZSBpZiAoZXZlbnQuc25hcHNob3QuZGF0YSAmJiBldmVudC5zbmFwc2hvdC5kYXRhLmNvbnRleHQpIHtcbiAgICAgICAgICBjOHlVaVV0aWwuZ2V0Q29udGV4dCA9ICgpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIGNvbnRleHQ6IGV2ZW50LnNuYXBzaG90LmRhdGEuY29udGV4dC5yZXBsYWNlKCcvOmlkJywgJycpLFxuICAgICAgICAgICAgICBpZDogZXZlbnQuc25hcHNob3QuZGF0YS5jb250ZXh0RGF0YS5pZCxcbiAgICAgICAgICAgICAgY29udGV4dERhdGE6IGV2ZW50LnNuYXBzaG90LmRhdGEuY29udGV4dERhdGFcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjOHlVaVV0aWwuZ2V0Q29udGV4dCA9ICgpID0+ICh7IGNvbnRleHQ6IG51bGwsIGlkOiBudWxsIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIGZpeEUyZUlzc3VlcygpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgeyBuZ1pvbmUgfSA9IHRoaXM7XG4gICAgICBjb25zdCB7IFV0aWxzIH0gPSAod2luZG93IGFzIGFueSkub3JnLmNvbWV0ZDtcbiAgICAgIGNvbnN0IHRpbWVvdXRGbiA9IFV0aWxzLnNldFRpbWVvdXQ7XG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6b25seS1hcnJvdy1mdW5jdGlvbnNcbiAgICAgIFV0aWxzLnNldFRpbWVvdXQgPSBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgICAgICByZXR1cm4gbmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHRpbWVvdXRGbi5hcHBseShVdGlscywgYXJncykpO1xuICAgICAgfTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBkbyBub3RoaW5nXG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgYWNlIH0gPSB3aW5kb3cgYXMgYW55O1xuICAgICAgY29uc3QgZWRpdEZuID0gYWNlLmVkaXQ7XG4gICAgICBjb25zdCB7IG5nWm9uZSB9ID0gdGhpcztcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpvbmx5LWFycm93LWZ1bmN0aW9uc1xuICAgICAgYWNlLmVkaXQgPSBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgICAgICByZXR1cm4gbmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IGVkaXRGbi5hcHBseShhY2UsIGFyZ3MpKTtcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gZG8gbm90aGluZ1xuICAgIH1cbiAgfVxuXG4gIGhvb2tMYW5ndWFnZSgpIHtcbiAgICBsZXQgZmlyc3QgPSB0cnVlO1xuICAgIHRoaXMuYXBwU3RhdGVcbiAgICAgIC5tYXAoc3RvcmUgPT4gc3RvcmUubGFuZylcbiAgICAgIC5zdWJzY3JpYmUobGFuZyA9PiB7XG4gICAgICAgIHRoaXMuaW5qZWN0b3IuZ2V0KCdjOHlMb2NhbGVzJykuc3dpdGNoVG9MYW5ndWFnZShsYW5nKTtcbiAgICAgICAgaWYgKCFmaXJzdCkge1xuICAgICAgICAgIHRoaXMuaW5qZWN0b3IuZ2V0KCckcm9vdFNjb3BlJykuJGFwcGx5KCk7XG4gICAgICAgIH1cbiAgICAgICAgZmlyc3QgPSBmYWxzZTtcbiAgICAgIH0pO1xuICB9XG5cbiAgaG9va1RhYigpIHtcbiAgICAvLyBKdXN0IGZvciBpbnN0YW50aWF0aW9uIG9mIHRoZSBjOHlBY3Rpb24gc2VydmljZVxuICAgIHRoaXMuaW5qZWN0b3IuZ2V0KCdjOHlBY3Rpb25zJyk7XG4gICAgY29uc3QgJGxvY2F0aW9uID0gdGhpcy5pbmplY3Rvci5nZXQoJyRsb2NhdGlvbicpO1xuICAgIGNvbnN0IGM4eVRhYnMgPSB0aGlzLmluamVjdG9yLmdldCgnYzh5VGFicycpO1xuICAgIGxldCBsaXZlVGFicyA9IFtdO1xuICAgIGM4eVRhYnMuYWRkVGFiID0gdGFiID0+IHtcbiAgICAgIGxpdmVUYWJzLnB1c2goe1xuICAgICAgICAuLi50YWIsXG4gICAgICAgIGxhYmVsOiB0YWIubGFiZWwgfHwgdGFiLm5hbWUsXG4gICAgICAgIHBhdGg6IGRlY29kZVVSSUNvbXBvbmVudCh0YWIucGF0aClcbiAgICAgIH0pO1xuICAgICAgdGhpcy4kbGl2ZVRhYnMubmV4dChsaXZlVGFicyk7XG4gICAgfTtcbiAgICB0aGlzLiRuZzFSb3V0ZUNoYW5nZVN0YXJ0LnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICBsaXZlVGFicyA9IFtdO1xuICAgICAgdGhpcy4kbGl2ZVRhYnMubmV4dChsaXZlVGFicyk7XG4gICAgfSk7XG4gICAgdGhpcy4kbmcxUm91dGVDaGFuZ2VTdWNjZXNzLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICBjb25zdCBwYXRoID0gJGxvY2F0aW9uLnBhdGgoKTtcbiAgICAgIGlmICh0aGlzLnJvdXRlci51cmwgIT09IHBhdGgpIHtcbiAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUocGF0aCA9PT0gJy8nID8gJycgOiBwYXRoLnNwbGl0KCcvJyksIHtcbiAgICAgICAgICBxdWVyeVBhcmFtczogJGxvY2F0aW9uLnNlYXJjaCgpLFxuICAgICAgICAgIHNraXBMb2NhdGlvbkNoYW5nZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmFjdGlvblNlcnZpY2UpIHtcbiAgICAgICAgdGhpcy5hY3Rpb25TZXJ2aWNlLnJlZnJlc2goKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB0aGlzLiRyb3V0ZUNoYW5nZXMgPSBtZXJnZShcbiAgICAgIHRoaXMuJG5nMVJvdXRlQ2hhbmdlU3VjY2VzcyxcbiAgICAgIHRoaXMuZnJvbU5nMUV2ZW50KGM4eVRhYnMsIGM4eVRhYnMuRVZFTlRfVVBEQVRFKSxcbiAgICAgIG9mKDEpXG4gICAgKS5waXBlKGRlYm91bmNlVGltZSgxMDApKTtcbiAgfVxuXG4gIGhvb2tOYXZpZ2F0b3IoKSB7XG4gICAgdGhpcy5uYXZpZ2F0aW9uTm9kZXMkID0gdGhpcy5pbmplY3Rvci5nZXQoJ2M4eU5hdmlnYXRvcicpLnJvb3ROb2RlcyQ7XG4gIH1cblxuICBnZXRUYWJzKCk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgY29uc3Qgb25seVZpc2libGUgPSAoeyBzaG93IH0pID0+IHNob3c7XG4gICAgY29uc3QgdXBncmFkZVRhYiA9IHRhYiA9PiAoe1xuICAgICAgLi4udGFiLFxuICAgICAgbGFiZWw6IHRhYi5sYWJlbCB8fCB0YWIubmFtZSxcbiAgICAgIHBhdGg6IGRlY29kZVVSSUNvbXBvbmVudCh0YWIucGF0aClcbiAgICB9KTtcbiAgICBjb25zdCByb3V0ZVRhYnMgPSB0aGlzLiRyb3V0ZUNoYW5nZXMucGlwZShcbiAgICAgIHN3aXRjaE1hcCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJvdXRlcyA9IHRoaXMuaW5qZWN0b3IuZ2V0KCdjOHlUYWJzJykucm91dGVUYWJzO1xuICAgICAgICBjb25zdCB2aXNpYmlsaXR5UHJvbWlzZSA9IFByb21pc2UuYWxsKFxuICAgICAgICAgIHJvdXRlcy5tYXAoKHsgY2hlY2tpbmdWaXNpYmlsaXR5IH0pID0+IGNoZWNraW5nVmlzaWJpbGl0eSlcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHZpc2liaWxpdHlQcm9taXNlLnRoZW4oKCkgPT4gcm91dGVzLmZpbHRlcihvbmx5VmlzaWJsZSkubWFwKHVwZ3JhZGVUYWIpKTtcbiAgICAgIH0pLFxuICAgICAgc3RhcnRXaXRoKFtdKVxuICAgICk7XG4gICAgcmV0dXJuIGNvbWJpbmVMYXRlc3QoW3JvdXRlVGFicywgdGhpcy4kbGl2ZVRhYnNdKS5waXBlKFxuICAgICAgbWFwKChbcm91dGUsIGxpdmVdKSA9PiByb3V0ZS5jb25jYXQobGl2ZSkpXG4gICAgKTtcbiAgfVxuXG4gIGdldFF1aWNrTGlua3MoKTogUHJvbWlzZTxEb2NMaW5rW10+IHtcbiAgICBjb25zdCBjOHlRdWlja0xpbmtzID0gdGhpcy5pbmplY3Rvci5nZXQoJ2M4eVF1aWNrTGlua3MnKTtcbiAgICByZXR1cm4gYzh5UXVpY2tMaW5rcy5saXN0KCk7XG4gIH1cblxuICBnZXRBY3Rpb25CYXJJdGVtcygpOiBPYnNlcnZhYmxlPEFjdGlvbkJhckl0ZW0+IHtcbiAgICBjb25zdCBjOHlBY3Rpb25CYXIgPSB0aGlzLmluamVjdG9yLmdldCgnYzh5QWN0aW9uQmFyJyk7XG4gICAgY29uc3QgJHJvb3RTY29wZSA9IHRoaXMuaW5qZWN0b3IuZ2V0KCckcm9vdFNjb3BlJyk7XG4gICAgY29uc3QgZ2V0QWN0aW9uQmFyRWxlbWVudHMgPSAoKSA9PlxuICAgICAgYzh5QWN0aW9uQmFyLmVsZW1lbnRzLm1hcChlbGVtZW50ID0+ICh7XG4gICAgICAgIHByaW9yaXR5OiBlbGVtZW50LmdldEF0dHJpYnV0ZSgnYWN0aW9uLWJhci1wcmlvcml0eScpIHx8IDAsXG4gICAgICAgIHRlbXBsYXRlOiBlbGVtZW50LFxuICAgICAgICBwbGFjZW1lbnQ6IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdhY3Rpb24tYmFyLXBvc2l0aW9uJykgfHwgJ3JpZ2h0J1xuICAgICAgfSkpO1xuICAgIHJldHVybiB0aGlzLmZyb21OZzFFdmVudCgkcm9vdFNjb3BlLCAnYzh5QWN0aW9uQmFyQ2hhbmdlZCcpLnBpcGUoXG4gICAgICBzdGFydFdpdGgoMSksXG4gICAgICBtYXAoZ2V0QWN0aW9uQmFyRWxlbWVudHMpXG4gICAgKTtcbiAgfVxuXG4gIGdldEJyZWFkY3J1bWJzKCk6IE9ic2VydmFibGU8QnJlYWRjcnVtYltdPiB7XG4gICAgY29uc3QgJGxvY2F0aW9uID0gdGhpcy5pbmplY3Rvci5nZXQoJyRsb2NhdGlvbicpO1xuICAgIGNvbnN0IGM4eUJyZWFkY3J1bWJzID0gdGhpcy5pbmplY3Rvci5nZXQoJ2M4eUJyZWFkY3J1bWJzJyk7XG4gICAgY29uc3QgYnJlYWRjcnVtYnNVcGRhdGUkID0gbmV3IE9ic2VydmFibGUoc3Vic2NyaWJlciA9PlxuICAgICAgYzh5QnJlYWRjcnVtYnMuJG9uKCd1cGRhdGUnLCAoKSA9PiBzdWJzY3JpYmVyLm5leHQoKSlcbiAgICApO1xuICAgIHJldHVybiBicmVhZGNydW1ic1VwZGF0ZSQucGlwZShcbiAgICAgIHN0YXJ0V2l0aCgwKSxcbiAgICAgIHN3aXRjaE1hcCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IHBhdGggPSAkbG9jYXRpb24ucGF0aCgpO1xuICAgICAgICBjb25zdCBicmVhZGNydW1icyA9IGM4eUJyZWFkY3J1bWJzLmdldChwYXRoKSB8fCB7fTtcbiAgICAgICAgY29uc3QgYnJlYWRjcnVtYnNEYXRhID0gdGhpcy5yZXNvbHZlQnJlYWRjcnVtYnNEYXRhKGJyZWFkY3J1bWJzLmRhdGEpO1xuICAgICAgICByZXR1cm4gZnJvbShicmVhZGNydW1ic0RhdGEpLnBpcGUoXG4gICAgICAgICAgbWFwKCh2YWx1ZTogYW55W10pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGxpdmVCcmVhZGNydW1icyA9IGM4eUJyZWFkY3J1bWJzLmdldExpdmVCcmVhZGNydW1icygpO1xuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5jb25jYXQobGl2ZUJyZWFkY3J1bWJzKTtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZS5tYXAoaXRlbXMgPT4gKHsgaXRlbXM6IGl0ZW1zIGFzIEJyZWFkY3J1bWJJdGVtW10gfSkgYXMgQnJlYWRjcnVtYik7XG4gICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHJlc29sdmVCcmVhZGNydW1ic0RhdGEoZGF0YSk6IE9ic2VydmFibGU8YW55W10+IHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHRoaXMuaW5qZWN0b3IuaW52b2tlKGRhdGEpO1xuICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAvLyBlbXB0eVxuICAgIH1cbiAgICBpZiAoaXNBcnJheShkYXRhKSkge1xuICAgICAgcmV0dXJuIG9mKFtkYXRhXSk7XG4gICAgfVxuICAgIHJldHVybiBvZihbXSk7XG4gIH1cblxuICBnZXRTZWFyY2goKTogU2VhcmNoW10ge1xuICAgIGNvbnN0IGM4eVNlYXJjaCA9IHRoaXMuaW5qZWN0b3IuZ2V0KCdjOHlTZWFyY2gnKTtcbiAgICByZXR1cm4gYzh5U2VhcmNoLmxpc3QoKS5tYXAoaXRlbSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBpY29uOiAnc2VhcmNoJyxcbiAgICAgICAgbmFtZTogaXRlbS5uYW1lLFxuICAgICAgICB0ZXJtOiAnJyxcbiAgICAgICAgb25TZWFyY2goKSB7XG4gICAgICAgICAgaWYgKHRoaXMudGVybSkge1xuICAgICAgICAgICAgYzh5U2VhcmNoLnNlYXJjaCh0aGlzLnRlcm0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBhcyBTZWFyY2g7XG4gICAgfSk7XG4gIH1cblxuICBnZXRBY3Rpb25zKCk6IE9ic2VydmFibGU8QWN0aW9uPiB7XG4gICAgY29uc3QgcmVnaXN0ZXJlZEFjdGlvbnMgPSB0aGlzLmluamVjdG9yLmdldCgnYzh5QWN0aW9ucycpLnJlZ2lzdGVyZWRBY3Rpb25zO1xuICAgIHJldHVybiBvZihcbiAgICAgIHJlZ2lzdGVyZWRBY3Rpb25zXG4gICAgICAgIC5maWx0ZXIoYWN0aW9uID0+ICFhY3Rpb24uaGlkZGVuKVxuICAgICAgICAubWFwKGFjdGlvbiA9PiAoe1xuICAgICAgICAgIC8vIFRoZSBwcmlvcml0eSB3YXMgcmV2ZXJzZWQ6IEFsaWduZWQgaXQgdG8gZGFzaGJvYXJkLCBoaWdoIGZpcnN0LCBsb3cgbGFzdC5cbiAgICAgICAgICBwcmlvcml0eTogKGFjdGlvbi5wcmlvcml0eSB8fCAwKSAqIC0xLFxuICAgICAgICAgIGxhYmVsOiBhY3Rpb24udGV4dCxcbiAgICAgICAgICBpY29uOiBhY3Rpb24uaWNvbixcbiAgICAgICAgICBkaXNhYmxlZDogYWN0aW9uLmRpc2FibGVkLFxuICAgICAgICAgIGFjdGlvbjogKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5pbmplY3Rvci5pbnZva2UoYWN0aW9uLmFjdGlvbiwgYWN0aW9uKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pKVxuICAgICk7XG4gIH1cblxuICBmcm9tTmcxRXZlbnQob2JqLCBldnQpIHtcbiAgICBsZXQgc3RvcExpc3RlbmluZztcbiAgICBmdW5jdGlvbiBhZGQoaGFuZGxlcikge1xuICAgICAgc3RvcExpc3RlbmluZyA9IG9iai4kb24oZXZ0LCBoYW5kbGVyKTtcbiAgICB9XG4gICAgcmV0dXJuIGZyb21FdmVudFBhdHRlcm4oYWRkLCAoKSA9PiBzdG9wTGlzdGVuaW5nKCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBob29rVXNlck1lbnUoKSB7XG4gICAgY29uc3QgdXNlck1lbnVTZXJ2aWNlID0gdGhpcy5pbmplY3Rvci5nZXQoJ2M4eVVzZXJNZW51U2VydmljZScpO1xuICAgIGNvbnN0IGM4eUFjY2Vzc0RlbmllZCA9IHRoaXMuaW5qZWN0b3IuZ2V0KCdjOHlBY2Nlc3NEZW5pZWQnKTtcbiAgICB1c2VyTWVudVNlcnZpY2UuYWRkKHtcbiAgICAgIGljb246ICdhY2Nlc3MnLFxuICAgICAgcHJpb3JpdHk6IDEwLFxuICAgICAgbGFiZWw6IGdldHRleHQoJ0FjY2VzcyBkZW5pZWQgcmVxdWVzdHMnKSxcbiAgICAgIGNsaWNrOiBjOHlBY2Nlc3NEZW5pZWQuc2hvd0FjY2Vzc0RlbmllZFJlcXVlc3RzTGlzdFxuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBicmlkZ2VTZXJ2aWNlRmFjdG9yeShcbiAgaW5qZWN0b3I6IGFueSxcbiAgYXBwU3RhdGU6IEFwcFN0YXRlU2VydmljZSxcbiAgcm91dGVyOiBSb3V0ZXIsXG4gIG5nWm9uZTogTmdab25lLFxuICByb3V0ZXJTZXJ2aWNlOiBSb3V0ZXJTZXJ2aWNlLFxuICBhY3Rpb25TZXJ2aWNlOiBBY3Rpb25TZXJ2aWNlLFxuICBwbHVnaW5zOiBQbHVnaW5zUmVzb2x2ZVNlcnZpY2Vcbikge1xuICByZXR1cm4gbmV3IEJyaWRnZVNlcnZpY2UoXG4gICAgaW5qZWN0b3IsXG4gICAgYXBwU3RhdGUsXG4gICAgcm91dGVyLFxuICAgIG5nWm9uZSxcbiAgICByb3V0ZXJTZXJ2aWNlLFxuICAgIGFjdGlvblNlcnZpY2UsXG4gICAgcGx1Z2luc1xuICApO1xufVxuXG5leHBvcnQgY29uc3QgYnJpZGdlU2VydmljZVByb3ZpZGVyID0ge1xuICBwcm92aWRlOiBCcmlkZ2VTZXJ2aWNlLFxuICB1c2VGYWN0b3J5OiBicmlkZ2VTZXJ2aWNlRmFjdG9yeSxcbiAgZGVwczogW1xuICAgICckaW5qZWN0b3InLFxuICAgIEFwcFN0YXRlU2VydmljZSxcbiAgICBSb3V0ZXIsXG4gICAgTmdab25lLFxuICAgIFJvdXRlclNlcnZpY2UsXG4gICAgQWN0aW9uU2VydmljZSxcbiAgICBQbHVnaW5zUmVzb2x2ZVNlcnZpY2VcbiAgXVxufTtcbiJdfQ==