UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

195 lines 27.6 kB
import { Injectable, Injector } from '@angular/core'; import { ActivatedRoute, ActivationEnd, NavigationEnd, PRIMARY_OUTLET, Router } from '@angular/router'; import { ApiService } from '@c8y/ngx-components/api'; import { NEVER, Subject } from 'rxjs'; import { filter, merge, switchMap } from 'rxjs/operators'; import { TabsService } from '../tabs/tabs.service'; import { RouterTabsResolver } from './router-tabs.resolver'; import { ViewContext } from './router.model'; import { ViewContextServices } from './view-context.service'; import * as i0 from "@angular/core"; import * as i1 from "./router-tabs.resolver"; import * as i2 from "../tabs/tabs.service"; import * as i3 from "@angular/router"; import * as i4 from "@c8y/ngx-components/api"; export class ContextRouteService { constructor(tabsResolver, tabsService, router, apiService, injector) { this.tabsResolver = tabsResolver; this.tabsService = tabsService; this.router = router; this.apiService = apiService; this.injector = injector; this.lastAddedTabs = []; this.ID_REGEX = /([0-9]+)/; this.refreshTrigger$ = new Subject(); /** * Last context data snapshot */ this.activatedContextData = null; this.router.events .pipe(filter(event => event instanceof ActivationEnd)) .subscribe((event) => { const currentContext = this.getContextDataSnapshot(event.snapshot); if (currentContext) { this.activatedContextData = currentContext; } }); } /** * Resolves the current context data. If no context was found, null is returned. * * @param activatedRoute The current activated route. */ getContextData(activatedRoute) { const data = this.getContextDataSnapshot(this.getSnapshot(activatedRoute)); if (data?.context) { return data; } return null; } /** * Returns a route for the given ContextData. * * @param contextData The ContextData object. * @returns A route with the ids set correctly. */ getContextRoute(contextData) { return contextData.context.replace(/:id/g, contextData.contextData.id); } /** * Verifies if a given url is a view context route. * * @param url A route url. * @param contextToCheck The view context(s) to check. If not provided, all contexts are checked. * @returns true if the given url is a view context route. */ isContextRoute(url, contextToCheck = []) { const viewContexts = contextToCheck.length === 0 ? Object.values(ViewContext) : contextToCheck; // replace all :id placeholders with a regex matcher for a number const regexMatchers = viewContexts.map(context => `/${context.replace(/:id/g, '([0-9]+)')}`); const matchingRegexContext = regexMatchers.find(context => new RegExp(context).test(url)); return !!matchingRegexContext; } /** * @deprecated: Use ScopedContextRouteService instead. Will be removed in 10.22 */ init(route) { this.routerSubscription = this.router.events .pipe(filter(e => e instanceof NavigationEnd)) .subscribe(() => this.redirectToFirstTab()); this.dataSubscription = route.data .pipe(merge(this.updatedContext(route), this.refreshTrigger$), switchMap(() => this.tabsResolver.resolve(route.snapshot))) .subscribe(tabs => this.updateTabs(tabs)); } /** * @deprecated: Use ScopedContextRouteService instead. Will be removed in 10.22 */ destroy() { this.dataSubscription.unsubscribe(); this.routerSubscription.unsubscribe(); this.lastAddedTabs.forEach(t => this.tabsService.remove(t)); } /** * Reloads all ViewContexts. */ refreshContext() { this.refreshTrigger$.next(); } /** * Sets a new contextData in the ActivatedRoute. * @param activatedRoute The current activated route. * @param contextData New contextData. */ setContext(activatedRoute, contextData) { const data = !activatedRoute.snapshot.parent || activatedRoute.snapshot.data.context ? activatedRoute.snapshot.data : activatedRoute.parent.snapshot.data; if (!data) { return; } data.contextData = { ...contextData }; } /** * @deprecated: Use ScopedContextRouteService instead. Will be removed in 10.21 */ updatedContext(route) { const { data } = route.snapshot; const serviceInstance = ViewContextServices.contextToService(data.context); if (serviceInstance) { const service = this.injector.get(serviceInstance); const detailsUrlRegex = service .getDetailUrl(data.contextData) .replace(/\d+/g, '?\\d*'); const contextRegex = new RegExp(detailsUrlRegex, 'i'); const childrenRegex = new RegExp(`${detailsUrlRegex}/child`, 'i'); const filterResponse = ({ url, method }) => { const contextChanged = contextRegex.test(url) && ['POST', 'PUT'].includes(method); const childrenAffected = childrenRegex.test(url) && ['POST', 'DELETE'].includes(method); return contextChanged || childrenAffected; }; return this.apiService.hookResponse(filterResponse); } return NEVER; } updateTabs(tabs = []) { this.lastAddedTabs.forEach(t => this.tabsService.remove(t)); this.lastAddedTabs = tabs; tabs.forEach(t => this.tabsService.add(t)); this.redirectToFirstTab(); } redirectToFirstTab() { const currentContextId = (this.router.url.match(this.ID_REGEX) || []).shift(); if (this.needsRedirect()) { this.tabsService.firstTab$ .pipe(filter((tab) => typeof tab?.path === 'string')) .subscribe((tab) => { const tabPathId = (tab.path.match(this.ID_REGEX) || []).shift(); if (currentContextId === tabPathId) { this.router.navigateByUrl(tab.path, { replaceUrl: true }); } }); } } needsRedirect() { const tree = this.router.parseUrl(this.router.url); const groups = tree.root.children[PRIMARY_OUTLET]; const context = this.getMatchingContextRoute(this.router.url); if (!context) { return groups.segments.length === 2; } else { return context.split('/').length === groups.segments.length; } } getMatchingContextRoute(url) { const viewContexts = Object.values(ViewContext); const urlWithoutId = url.replace(/\d(.*)/g, ''); const id = viewContexts.findIndex(context => `/${context.replace(':id', '')}` === urlWithoutId); return viewContexts[id]; } getSnapshot(activatedRoute) { return activatedRoute instanceof ActivatedRoute || !!activatedRoute?.snapshot ? activatedRoute.snapshot : activatedRoute; } getContextDataSnapshot(activatedRoute) { let route = activatedRoute; while (route) { if (route.data.context) { return route.data; } route = route.parent; } return {}; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ContextRouteService, deps: [{ token: i1.RouterTabsResolver }, { token: i2.TabsService }, { token: i3.Router }, { token: i4.ApiService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ContextRouteService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ContextRouteService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.RouterTabsResolver }, { type: i2.TabsService }, { type: i3.Router }, { type: i4.ApiService }, { type: i0.Injector }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC1yb3V0ZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vY29yZS9yb3V0ZXIvY29udGV4dC1yb3V0ZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFRLE1BQU0sZUFBZSxDQUFDO0FBQzNELE9BQU8sRUFDTCxjQUFjLEVBRWQsYUFBYSxFQUViLGFBQWEsRUFDYixjQUFjLEVBQ2QsTUFBTSxFQUdQLE1BQU0saUJBQWlCLENBQUM7QUFFekIsT0FBTyxFQUFXLFVBQVUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzlELE9BQU8sRUFBRSxLQUFLLEVBQWMsT0FBTyxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUNoRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUxRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbkQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDNUQsT0FBTyxFQUFlLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzFELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHdCQUF3QixDQUFDOzs7Ozs7QUFLN0QsTUFBTSxPQUFPLG1CQUFtQjtJQWE5QixZQUNVLFlBQWdDLEVBQ2hDLFdBQXdCLEVBQ3hCLE1BQWMsRUFDZCxVQUFzQixFQUN0QixRQUFrQjtRQUpsQixpQkFBWSxHQUFaLFlBQVksQ0FBb0I7UUFDaEMsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDeEIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGVBQVUsR0FBVixVQUFVLENBQVk7UUFDdEIsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQWZwQixrQkFBYSxHQUFHLEVBQUUsQ0FBQztRQUNuQixhQUFRLEdBQUcsVUFBVSxDQUFDO1FBRTlCLG9C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O21IQUFuQixtQkFBbUIsY0FGbEIsTUFBTTs7NEZBRVAsbUJBQW1CO2tCQUgvQixVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIEluamVjdG9yLCBUeXBlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBBY3RpdmF0ZWRSb3V0ZSxcbiAgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCxcbiAgQWN0aXZhdGlvbkVuZCxcbiAgRGF0YSxcbiAgTmF2aWdhdGlvbkVuZCxcbiAgUFJJTUFSWV9PVVRMRVQsXG4gIFJvdXRlcixcbiAgVXJsU2VnbWVudEdyb3VwLFxuICBVcmxUcmVlXG59IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBJSWRlbnRpZmllZCB9IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7IEFwaUNhbGwsIEFwaVNlcnZpY2UgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzL2FwaSc7XG5pbXBvcnQgeyBORVZFUiwgT2JzZXJ2YWJsZSwgU3ViamVjdCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBmaWx0ZXIsIG1lcmdlLCBzd2l0Y2hNYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBUYWIsIFRhYldpdGhUZW1wbGF0ZSB9IGZyb20gJy4uL3RhYnMvdGFiLm1vZGVsJztcbmltcG9ydCB7IFRhYnNTZXJ2aWNlIH0gZnJvbSAnLi4vdGFicy90YWJzLnNlcnZpY2UnO1xuaW1wb3J0IHsgUm91dGVyVGFic1Jlc29sdmVyIH0gZnJvbSAnLi9yb3V0ZXItdGFicy5yZXNvbHZlcic7XG5pbXBvcnQgeyBDb250ZXh0RGF0YSwgVmlld0NvbnRleHQgfSBmcm9tICcuL3JvdXRlci5tb2RlbCc7XG5pbXBvcnQgeyBWaWV3Q29udGV4dFNlcnZpY2VzIH0gZnJvbSAnLi92aWV3LWNvbnRleHQuc2VydmljZSc7XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIENvbnRleHRSb3V0ZVNlcnZpY2Uge1xuICBwcml2YXRlIGRhdGFTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSByb3V0ZXJTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSBsYXN0QWRkZWRUYWJzID0gW107XG4gIHByaXZhdGUgSURfUkVHRVggPSAvKFswLTldKykvO1xuXG4gIHJlZnJlc2hUcmlnZ2VyJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgLyoqXG4gICAqIExhc3QgY29udGV4dCBkYXRhIHNuYXBzaG90XG4gICAqL1xuICBhY3RpdmF0ZWRDb250ZXh0RGF0YTogQ29udGV4dERhdGEgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgdGFic1Jlc29sdmVyOiBSb3V0ZXJUYWJzUmVzb2x2ZXIsXG4gICAgcHJpdmF0ZSB0YWJzU2VydmljZTogVGFic1NlcnZpY2UsXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcbiAgICBwcml2YXRlIGFwaVNlcnZpY2U6IEFwaVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBpbmplY3RvcjogSW5qZWN0b3JcbiAgKSB7XG4gICAgdGhpcy5yb3V0ZXIuZXZlbnRzXG4gICAgICAucGlwZShmaWx0ZXIoZXZlbnQgPT4gZXZlbnQgaW5zdGFuY2VvZiBBY3RpdmF0aW9uRW5kKSlcbiAgICAgIC5zdWJzY3JpYmUoKGV2ZW50OiBBY3RpdmF0aW9uRW5kKSA9PiB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRDb250ZXh0ID0gdGhpcy5nZXRDb250ZXh0RGF0YVNuYXBzaG90KGV2ZW50LnNuYXBzaG90KTtcbiAgICAgICAgaWYgKGN1cnJlbnRDb250ZXh0KSB7XG4gICAgICAgICAgdGhpcy5hY3RpdmF0ZWRDb250ZXh0RGF0YSA9IGN1cnJlbnRDb250ZXh0IGFzIENvbnRleHREYXRhO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyB0aGUgY3VycmVudCBjb250ZXh0IGRhdGEuIElmIG5vIGNvbnRleHQgd2FzIGZvdW5kLCBudWxsIGlzIHJldHVybmVkLlxuICAgKlxuICAgKiBAcGFyYW0gYWN0aXZhdGVkUm91dGUgVGhlIGN1cnJlbnQgYWN0aXZhdGVkIHJvdXRlLlxuICAgKi9cbiAgZ2V0Q29udGV4dERhdGEoXG4gICAgYWN0aXZhdGVkUm91dGU6IEFjdGl2YXRlZFJvdXRlIHwgQWN0aXZhdGVkUm91dGVTbmFwc2hvdFxuICApOiAoRGF0YSAmIENvbnRleHREYXRhKSB8IG51bGwge1xuICAgIGNvbnN0IGRhdGEgPSB0aGlzLmdldENvbnRleHREYXRhU25hcHNob3QodGhpcy5nZXRTbmFwc2hvdChhY3RpdmF0ZWRSb3V0ZSkpO1xuICAgIGlmIChkYXRhPy5jb250ZXh0KSB7XG4gICAgICByZXR1cm4gZGF0YSBhcyBEYXRhICYgQ29udGV4dERhdGE7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSByb3V0ZSBmb3IgdGhlIGdpdmVuIENvbnRleHREYXRhLlxuICAgKlxuICAgKiBAcGFyYW0gY29udGV4dERhdGEgVGhlIENvbnRleHREYXRhIG9iamVjdC5cbiAgICogQHJldHVybnMgQSByb3V0ZSB3aXRoIHRoZSBpZHMgc2V0IGNvcnJlY3RseS5cbiAgICovXG4gIGdldENvbnRleHRSb3V0ZShjb250ZXh0RGF0YTogQ29udGV4dERhdGEpOiBzdHJpbmcge1xuICAgIHJldHVybiBjb250ZXh0RGF0YS5jb250ZXh0LnJlcGxhY2UoLzppZC9nLCBjb250ZXh0RGF0YS5jb250ZXh0RGF0YS5pZCBhcyBzdHJpbmcpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWVzIGlmIGEgZ2l2ZW4gdXJsIGlzIGEgdmlldyBjb250ZXh0IHJvdXRlLlxuICAgKlxuICAgKiBAcGFyYW0gdXJsIEEgcm91dGUgdXJsLlxuICAgKiBAcGFyYW0gY29udGV4dFRvQ2hlY2sgVGhlIHZpZXcgY29udGV4dChzKSB0byBjaGVjay4gSWYgbm90IHByb3ZpZGVkLCBhbGwgY29udGV4dHMgYXJlIGNoZWNrZWQuXG4gICAqIEByZXR1cm5zIHRydWUgaWYgdGhlIGdpdmVuIHVybCBpcyBhIHZpZXcgY29udGV4dCByb3V0ZS5cbiAgICovXG4gIGlzQ29udGV4dFJvdXRlKHVybDogc3RyaW5nLCBjb250ZXh0VG9DaGVjazogVmlld0NvbnRleHRbXSA9IFtdKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgdmlld0NvbnRleHRzID0gY29udGV4dFRvQ2hlY2subGVuZ3RoID09PSAwID8gT2JqZWN0LnZhbHVlcyhWaWV3Q29udGV4dCkgOiBjb250ZXh0VG9DaGVjaztcbiAgICAvLyByZXBsYWNlIGFsbCA6aWQgcGxhY2Vob2xkZXJzIHdpdGggYSByZWdleCBtYXRjaGVyIGZvciBhIG51bWJlclxuICAgIGNvbnN0IHJlZ2V4TWF0Y2hlcnMgPSB2aWV3Q29udGV4dHMubWFwKGNvbnRleHQgPT4gYC8ke2NvbnRleHQucmVwbGFjZSgvOmlkL2csICcoWzAtOV0rKScpfWApO1xuICAgIGNvbnN0IG1hdGNoaW5nUmVnZXhDb250ZXh0ID0gcmVnZXhNYXRjaGVycy5maW5kKGNvbnRleHQgPT4gbmV3IFJlZ0V4cChjb250ZXh0KS50ZXN0KHVybCkpO1xuICAgIHJldHVybiAhIW1hdGNoaW5nUmVnZXhDb250ZXh0O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkOiBVc2UgU2NvcGVkQ29udGV4dFJvdXRlU2VydmljZSBpbnN0ZWFkLiBXaWxsIGJlIHJlbW92ZWQgaW4gMTAuMjJcbiAgICovXG4gIGluaXQocm91dGU6IEFjdGl2YXRlZFJvdXRlKTogdm9pZCB7XG4gICAgdGhpcy5yb3V0ZXJTdWJzY3JpcHRpb24gPSB0aGlzLnJvdXRlci5ldmVudHNcbiAgICAgIC5waXBlKGZpbHRlcihlID0+IGUgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uRW5kKSlcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5yZWRpcmVjdFRvRmlyc3RUYWIoKSk7XG5cbiAgICB0aGlzLmRhdGFTdWJzY3JpcHRpb24gPSByb3V0ZS5kYXRhXG4gICAgICAucGlwZShcbiAgICAgICAgbWVyZ2UodGhpcy51cGRhdGVkQ29udGV4dChyb3V0ZSksIHRoaXMucmVmcmVzaFRyaWdnZXIkKSxcbiAgICAgICAgc3dpdGNoTWFwKCgpID0+IHRoaXMudGFic1Jlc29sdmVyLnJlc29sdmUocm91dGUuc25hcHNob3QpKVxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSh0YWJzID0+IHRoaXMudXBkYXRlVGFicyh0YWJzKSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQ6IFVzZSBTY29wZWRDb250ZXh0Um91dGVTZXJ2aWNlIGluc3RlYWQuIFdpbGwgYmUgcmVtb3ZlZCBpbiAxMC4yMlxuICAgKi9cbiAgZGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmRhdGFTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLnJvdXRlclN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMubGFzdEFkZGVkVGFicy5mb3JFYWNoKHQgPT4gdGhpcy50YWJzU2VydmljZS5yZW1vdmUodCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbG9hZHMgYWxsIFZpZXdDb250ZXh0cy5cbiAgICovXG4gIHJlZnJlc2hDb250ZXh0KCkge1xuICAgIHRoaXMucmVmcmVzaFRyaWdnZXIkLm5leHQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGEgbmV3IGNvbnRleHREYXRhIGluIHRoZSBBY3RpdmF0ZWRSb3V0ZS5cbiAgICogQHBhcmFtIGFjdGl2YXRlZFJvdXRlIFRoZSBjdXJyZW50IGFjdGl2YXRlZCByb3V0ZS5cbiAgICogQHBhcmFtIGNvbnRleHREYXRhIE5ldyBjb250ZXh0RGF0YS5cbiAgICovXG4gIHNldENvbnRleHQoYWN0aXZhdGVkUm91dGU6IEFjdGl2YXRlZFJvdXRlLCBjb250ZXh0RGF0YTogSUlkZW50aWZpZWQpOiB2b2lkIHtcbiAgICBjb25zdCBkYXRhID1cbiAgICAgICFhY3RpdmF0ZWRSb3V0ZS5zbmFwc2hvdC5wYXJlbnQgfHwgYWN0aXZhdGVkUm91dGUuc25hcHNob3QuZGF0YS5jb250ZXh0XG4gICAgICAgID8gYWN0aXZhdGVkUm91dGUuc25hcHNob3QuZGF0YVxuICAgICAgICA6IGFjdGl2YXRlZFJvdXRlLnBhcmVudC5zbmFwc2hvdC5kYXRhO1xuXG4gICAgaWYgKCFkYXRhKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGRhdGEuY29udGV4dERhdGEgPSB7IC4uLmNvbnRleHREYXRhIH07XG4gIH1cblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQ6IFVzZSBTY29wZWRDb250ZXh0Um91dGVTZXJ2aWNlIGluc3RlYWQuIFdpbGwgYmUgcmVtb3ZlZCBpbiAxMC4yMVxuICAgKi9cbiAgdXBkYXRlZENvbnRleHQocm91dGU6IEFjdGl2YXRlZFJvdXRlKTogT2JzZXJ2YWJsZTxBcGlDYWxsPiB7XG4gICAgY29uc3QgeyBkYXRhIH0gPSByb3V0ZS5zbmFwc2hvdDtcbiAgICBjb25zdCBzZXJ2aWNlSW5zdGFuY2UgPSBWaWV3Q29udGV4dFNlcnZpY2VzLmNvbnRleHRUb1NlcnZpY2UoZGF0YS5jb250ZXh0KTtcbiAgICBpZiAoc2VydmljZUluc3RhbmNlKSB7XG4gICAgICBjb25zdCBzZXJ2aWNlID0gdGhpcy5pbmplY3Rvci5nZXQoXG4gICAgICAgIHNlcnZpY2VJbnN0YW5jZSBhcyBUeXBlPEluc3RhbmNlVHlwZTx0eXBlb2Ygc2VydmljZUluc3RhbmNlPj5cbiAgICAgICk7XG4gICAgICBjb25zdCBkZXRhaWxzVXJsUmVnZXggPSAoc2VydmljZSBhcyB0eXBlb2Ygc2VydmljZSAmIHsgZ2V0RGV0YWlsVXJsPzogKC4uLmFyZ3MpID0+IHN0cmluZyB9KVxuICAgICAgICAuZ2V0RGV0YWlsVXJsKGRhdGEuY29udGV4dERhdGEpXG4gICAgICAgIC5yZXBsYWNlKC9cXGQrL2csICc/XFxcXGQqJyk7XG4gICAgICBjb25zdCBjb250ZXh0UmVnZXggPSBuZXcgUmVnRXhwKGRldGFpbHNVcmxSZWdleCwgJ2knKTtcbiAgICAgIGNvbnN0IGNoaWxkcmVuUmVnZXggPSBuZXcgUmVnRXhwKGAke2RldGFpbHNVcmxSZWdleH0vY2hpbGRgLCAnaScpO1xuICAgICAgY29uc3QgZmlsdGVyUmVzcG9uc2UgPSAoeyB1cmwsIG1ldGhvZCB9KSA9PiB7XG4gICAgICAgIGNvbnN0IGNvbnRleHRDaGFuZ2VkID0gY29udGV4dFJlZ2V4LnRlc3QodXJsKSAmJiBbJ1BPU1QnLCAnUFVUJ10uaW5jbHVkZXMobWV0aG9kKTtcbiAgICAgICAgY29uc3QgY2hpbGRyZW5BZmZlY3RlZCA9IGNoaWxkcmVuUmVnZXgudGVzdCh1cmwpICYmIFsnUE9TVCcsICdERUxFVEUnXS5pbmNsdWRlcyhtZXRob2QpO1xuICAgICAgICByZXR1cm4gY29udGV4dENoYW5nZWQgfHwgY2hpbGRyZW5BZmZlY3RlZDtcbiAgICAgIH07XG4gICAgICByZXR1cm4gdGhpcy5hcGlTZXJ2aWNlLmhvb2tSZXNwb25zZShmaWx0ZXJSZXNwb25zZSk7XG4gICAgfVxuICAgIHJldHVybiBORVZFUjtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlVGFicyh0YWJzID0gW10pIHtcbiAgICB0aGlzLmxhc3RBZGRlZFRhYnMuZm9yRWFjaCh0ID0+IHRoaXMudGFic1NlcnZpY2UucmVtb3ZlKHQpKTtcbiAgICB0aGlzLmxhc3RBZGRlZFRhYnMgPSB0YWJzO1xuICAgIHRhYnMuZm9yRWFjaCh0ID0+IHRoaXMudGFic1NlcnZpY2UuYWRkKHQpKTtcbiAgICB0aGlzLnJlZGlyZWN0VG9GaXJzdFRhYigpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWRpcmVjdFRvRmlyc3RUYWIoKSB7XG4gICAgY29uc3QgY3VycmVudENvbnRleHRJZCA9ICh0aGlzLnJvdXRlci51cmwubWF0Y2godGhpcy5JRF9SRUdFWCkgfHwgW10pLnNoaWZ0KCk7XG4gICAgaWYgKHRoaXMubmVlZHNSZWRpcmVjdCgpKSB7XG4gICAgICB0aGlzLnRhYnNTZXJ2aWNlLmZpcnN0VGFiJFxuICAgICAgICAucGlwZShmaWx0ZXIoKHRhYjogVGFiKSA9PiB0eXBlb2YgdGFiPy5wYXRoID09PSAnc3RyaW5nJykpXG4gICAgICAgIC5zdWJzY3JpYmUoKHRhYjogVGFiV2l0aFRlbXBsYXRlPHN0cmluZz4pID0+IHtcbiAgICAgICAgICBjb25zdCB0YWJQYXRoSWQgPSAodGFiLnBhdGgubWF0Y2godGhpcy5JRF9SRUdFWCkgfHwgW10pLnNoaWZ0KCk7XG4gICAgICAgICAgaWYgKGN1cnJlbnRDb250ZXh0SWQgPT09IHRhYlBhdGhJZCkge1xuICAgICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGVCeVVybCh0YWIucGF0aCwgeyByZXBsYWNlVXJsOiB0cnVlIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBuZWVkc1JlZGlyZWN0KCkge1xuICAgIGNvbnN0IHRyZWU6IFVybFRyZWUgPSB0aGlzLnJvdXRlci5wYXJzZVVybCh0aGlzLnJvdXRlci51cmwpO1xuICAgIGNvbnN0IGdyb3VwczogVXJsU2VnbWVudEdyb3VwID0gdHJlZS5yb290LmNoaWxkcmVuW1BSSU1BUllfT1VUTEVUXTtcblxuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLmdldE1hdGNoaW5nQ29udGV4dFJvdXRlKHRoaXMucm91dGVyLnVybCk7XG4gICAgaWYgKCFjb250ZXh0KSB7XG4gICAgICByZXR1cm4gZ3JvdXBzLnNlZ21lbnRzLmxlbmd0aCA9PT0gMjtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbnRleHQuc3BsaXQoJy8nKS5sZW5ndGggPT09IGdyb3Vwcy5zZWdtZW50cy5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRNYXRjaGluZ0NvbnRleHRSb3V0ZSh1cmwpIHtcbiAgICBjb25zdCB2aWV3Q29udGV4dHMgPSBPYmplY3QudmFsdWVzKFZpZXdDb250ZXh0KTtcblxuICAgIGNvbnN0IHVybFdpdGhvdXRJZCA9IHVybC5yZXBsYWNlKC9cXGQoLiopL2csICcnKTtcbiAgICBjb25zdCBpZCA9IHZpZXdDb250ZXh0cy5maW5kSW5kZXgoY29udGV4dCA9PiBgLyR7Y29udGV4dC5yZXBsYWNlKCc6aWQnLCAnJyl9YCA9PT0gdXJsV2l0aG91dElkKTtcbiAgICByZXR1cm4gdmlld0NvbnRleHRzW2lkXTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0U25hcHNob3QoXG4gICAgYWN0aXZhdGVkUm91dGU6IEFjdGl2YXRlZFJvdXRlIHwgQWN0aXZhdGVkUm91dGVTbmFwc2hvdFxuICApOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90IHtcbiAgICByZXR1cm4gYWN0aXZhdGVkUm91dGUgaW5zdGFuY2VvZiBBY3RpdmF0ZWRSb3V0ZSB8fFxuICAgICAgISEoYWN0aXZhdGVkUm91dGUgYXMgdW5rbm93biBhcyB7IHNuYXBzaG90OiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90IH0pPy5zbmFwc2hvdFxuICAgICAgPyAoYWN0aXZhdGVkUm91dGUgYXMgdW5rbm93biBhcyB7IHNuYXBzaG90OiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90IH0pLnNuYXBzaG90XG4gICAgICA6IGFjdGl2YXRlZFJvdXRlO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRDb250ZXh0RGF0YVNuYXBzaG90KFxuICAgIGFjdGl2YXRlZFJvdXRlOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90XG4gICk6IERhdGEgJiBQYXJ0aWFsPENvbnRleHREYXRhPiB7XG4gICAgbGV0IHJvdXRlID0gYWN0aXZhdGVkUm91dGU7XG4gICAgd2hpbGUgKHJvdXRlKSB7XG4gICAgICBpZiAocm91dGUuZGF0YS5jb250ZXh0KSB7XG4gICAgICAgIHJldHVybiByb3V0ZS5kYXRhO1xuICAgICAgfVxuICAgICAgcm91dGUgPSByb3V0ZS5wYXJlbnQ7XG4gICAgfVxuICAgIHJldHVybiB7fTtcbiAgfVxufVxuIl19