UNPKG

@angulogic/ng-sidebar

Version:
417 lines 54.8 kB
import { Injectable } from '@angular/core'; import { NavigationEnd } from '@angular/router'; import * as i0 from "@angular/core"; import * as i1 from "@angular/router"; import * as i2 from "@angular/common/http"; /** * Service responsible for managing sidebar state, configurations, and behaviors. * It handles sidebar initialization, resizing, menu interactions, and theme changes. * * @export * @class NgSidebarService */ export class NgSidebarService { /** * Initializes the sidebar service and listens for route changes. * * @param {Router} router - Angular Router for detecting navigation events. * @param {HttpClient} http - Angular HttpClient for loading assets (e.g., SVG icons). */ constructor(router, http) { this.router = router; this.http = http; /** * Tracks whether auto-positioning is enabled. * @default false */ this.autoPositionActive = false; /** * Indicates whether the sidebar is currently being resized. * @default false */ this.isResizing = false; router.events.subscribe(route => { if (route instanceof NavigationEnd) { this.sidebarData.sidebarData.forEach(data => { this.updateActiveState(data.data, route.url); }); } }); } /** * Initializes the sidebar configuration with default values if not provided. * * @param {Partial<SidebarModel> & { sidebarData: SidebarData[] }} data - Sidebar data with optional configurations. * @returns {SidebarModel} - The complete SidebarModel with default values applied. */ initilazeSidebarData(data) { // Banner options data.bannerOptions = data.bannerOptions ? { logo: data.bannerOptions.logo ?? 'assets/icons/angular-logo.png', title: data.bannerOptions.title ?? 'Angulogic', onClick: data.bannerOptions.onClick, } : undefined; // User options data.userOptions = data.userOptions ? { avatar: data.userOptions.avatar ?? 'assets/icons/avatar.svg', name: data.userOptions.name, position: data.userOptions.position ?? 'bottom', onClick: data.userOptions.onClick, } : undefined; // Search options data.searchOptions = data.searchOptions ? { placeholder: data.searchOptions.placeholder, caseSensitive: data.searchOptions.caseSensitive ?? false, strategy: data.searchOptions.strategy ?? 'contains', cssClass: data.searchOptions.cssClass, localCompare: data.searchOptions.localCompare ?? 'en', onSearchStart: data.searchOptions.onSearchStart, onSearchEnd: data.searchOptions.onSearchEnd, } : undefined; // Sidebar data initialization data.sidebarData = data.sidebarData.map(item => ({ title: item.title, cssClass: item.cssClass, visible: item.visible ?? true, data: this.initializeMenuData(item.data), })); // Sidebar options initialization data.options = data.options ? { resize: data.options.resize ?? true, expand: data.options.expand ?? true, favorites: data.options.favorites ?? true, favoritesTitle: data.options.favoritesTitle ?? 'Favorites', search: data.options.search ?? true, cssClass: data.options.cssClass ?? '', viewMode: data.options.viewMode ?? 'toggle', theme: data.options.theme ?? 'light', themePicker: data.options.themePicker ?? true, minWidth: data.options.minWidth ?? 300, maxWidth: data.options.maxWidth ?? 500, width: data.options.width ?? 300, themeText: data.options.themeText ?? { light: 'Light', dark: 'Dark' }, autoPosition: data.options.autoPosition ?? true, toggleCollapseIcon: data.options.toggleCollapseIcon ?? 'assets/icons/collapse.svg', toggleExpandIcon: data.options.toggleExpandIcon ?? 'assets/icons/expand.svg', pinIcon: data.options.pinIcon ?? 'assets/icons/pin.svg', unpinIcon: data.options.unpinIcon ?? 'assets/icons/unpin.svg', closeIcon: data.options.closeIcon ?? 'assets/icons/cancel.svg', pinned: data.options.pinned ?? (data.options.expand && data.options.viewMode === 'hover') ?? false, onThemeChange: data.options.onThemeChange, onResizeStart: data.options.onResizeStart, onResizing: data.options.onResizing, onResizeEnd: data.options.onResizeEnd, onExpand: data.options.onExpand, onCollapse: data.options.onCollapse, onMenuNodeClick: data.options.onMenuNodeClick, } : { resize: true, expand: true, favorites: true, search: true, viewMode: 'toggle', theme: 'light', }; this.sidebarData = data; return data; } /** * Enables automatic positioning of the sidebar. * It observes the sidebar's width and updates the CSS variable `--sidebar-width` dynamically. */ setAutoPosition() { const divElement = document.getElementById('ng-sidebar'); if (!divElement) { return; } if (!document.body.classList.contains('auto-position')) { document.body.classList.add('auto-position'); } const duration = 300; this.observer = new MutationObserver(() => { const width = divElement.offsetWidth; this.updateWidth(divElement, performance.now(), duration); document.documentElement.style.setProperty('--sidebar-width', `${width}px`); }); this.observer.observe(divElement, { attributeFilter: ['style'], }); this.autoPositionActive = true; console.log('Auto position enabled'); } /** * Animates the width update of the sidebar. * * @param {HTMLElement} divElement - The sidebar element whose width is being updated. * @param {number} startTime - The start time of the animation. * @param {number} duration - The duration of the width animation in milliseconds. */ updateWidth(divElement, startTime, duration) { const animateWidth = (timestamp) => { let progress = (timestamp - startTime) / duration; const currentWidth = divElement.offsetWidth; document.documentElement.style.setProperty('--sidebar-width', `${currentWidth}px`); if (progress < 1) { requestAnimationFrame(animateWidth); } }; requestAnimationFrame(animateWidth); } /** * Disables automatic positioning of the sidebar. * Stops observing style changes and resets CSS modifications. */ destroyAutoPosition() { this.observer.disconnect(); if (document.body.classList.contains('auto-position')) { document.body.classList.remove('auto-position'); } this.autoPositionActive = false; console.log('Auto position disabled'); } /** * Handles sidebar resizing using mouse events. * * @param {SidebarModel} sidebarData - The sidebar configuration object. */ resize(sidebarData) { this.isResizing = true; const initialPin = sidebarData.options.pinned; sidebarData.options.pinned = true; const startEvent = { cancel: false, sidebarOptions: sidebarData, }; if (sidebarData.options.onResizeStart) { sidebarData.options.onResizeStart(startEvent); if (startEvent.cancel) { this.isResizing = false; return; } } document.body.classList.add('no-select'); /** * Handles mouse movement during resizing. * * @param {MouseEvent} e - The mouse movement event. */ const mouseMoveListener = (e) => { const resizeEvent = { cancel: false, sidebarOptions: sidebarData, mouseEvent: e, }; if (sidebarData.options.onResizing) { sidebarData.options.onResizing(resizeEvent); if (resizeEvent.cancel) { return; } } if (sidebarData.options.minWidth && e.clientX < sidebarData.options.minWidth) { sidebarData.options.width = sidebarData.options.minWidth; } else if (sidebarData.options.maxWidth && e.clientX > sidebarData.options.maxWidth) { sidebarData.options.width = sidebarData.options.maxWidth; } else { sidebarData.options.width = e.clientX; } }; document.addEventListener('mousemove', mouseMoveListener); /** * Handles mouse release after resizing. * * @param {MouseEvent} e - The mouse up event. */ const mouseUpListener = (e) => { document.body.classList.remove('no-select'); document.removeEventListener('mousemove', mouseMoveListener); document.removeEventListener('mouseup', mouseUpListener); this.isResizing = false; sidebarData.options.pinned = initialPin; const endEvent = { sidebarOptions: sidebarData, mouseEvent: e, }; if (sidebarData.options.onResizeEnd) { sidebarData.options.onResizeEnd(endEvent); } }; document.addEventListener('mouseup', mouseUpListener); } /** * Initializes menu data by assigning default values if not provided. * * @param {MenuData[]} menuData - The menu data array to initialize. * @returns {MenuData[]} - The processed menu data with default values applied. */ initializeMenuData(menuData) { return menuData.map(item => { item['name'] = item['name']; item['icon'] = item['icon']; item['route'] = item['route']; item['visible'] = item['visible'] ?? true; item['disabled'] = item['disabled'] ?? false; item['isExpanded'] = item['isExpanded'] ?? false; item['isFavorited'] = item['isFavorited'] ?? false; item['cssClass'] = item['cssClass']; item['active'] = item['active'] ?? false; item['children'] = item['children'] ? this.initializeMenuData(item['children']) : undefined; item['onClick'] = item['onClick']; return item; }); } /** * Searches for menu items by name within the sidebar data. * * @param {SidebarModel} data - The sidebar configuration containing menu data. * @param {string} searchValue - The search query entered by the user. * @returns {MenuData[]} - An array of matching menu items. */ searchByName(data, searchValue) { const { searchOptions, sidebarData } = data; /** * Compares two strings based on the configured search options. * * @param {string} source - The original menu item name. * @param {string} target - The search query entered by the user. * @returns {boolean} - True if the search criteria match, false otherwise. */ const compareStrings = (source, target) => { if (!searchOptions?.caseSensitive) { source = source.toLocaleLowerCase(searchOptions?.localCompare); target = target.toLocaleLowerCase(searchOptions?.localCompare); } switch (searchOptions?.strategy) { case 'contains': return source.includes(target); case 'startsWith': return source.startsWith(target); case 'endsWith': return source.endsWith(target); case 'equal': return source === target; default: return false; } }; /** * Recursively searches menu items and their children. * * @param {MenuData[]} data - The menu items to search in. * @returns {MenuData[]} - The filtered menu items. */ const searchInMenuData = (data) => { const resultSet = new Set(); data.forEach(item => { if (compareStrings(item.name, searchValue)) { resultSet.add(item); } if (item.children && item.children.length > 0) { const childResults = searchInMenuData(item.children); if (childResults.length > 0) { item.children = childResults; resultSet.add(item); } } }); return Array.from(resultSet); }; return sidebarData.flatMap(sidebarItem => searchInMenuData(sidebarItem.data)); } /** * Updates the active state of menu items based on the current route. * * @param {MenuData[]} menuData - The menu data array to update. * @param {string} currentRoute - The current active route. */ updateActiveState(menuData, currentRoute) { menuData.forEach(item => { if (item.route?.startsWith('/')) { item.active = item.route === currentRoute; } else { item.active = `/${item.route}` === currentRoute; } if (item.children) { this.updateActiveState(item.children, currentRoute); } }); } /** * Toggles the sidebar theme between 'light' and 'dark'. * Updates the `theme` property in `sidebarData.options`. */ changeTheme() { if (this.sidebarData.options.theme === 'light') { this.sidebarData.options.theme = 'dark'; } else { this.sidebarData.options.theme = 'light'; } // Trigger theme change event if provided if (this.sidebarData.options.onThemeChange) { this.sidebarData.options.onThemeChange(this.sidebarData.options.theme); } } /** * Loads an SVG file from the given path. * * @param {string} path - The file path of the SVG to load. * @returns {Promise<string>} - A promise resolving to the SVG content. */ loadSvg(path) { return new Promise((resolve, reject) => { this.http.get(path, { responseType: 'text' }).subscribe({ next: svgContent => resolve(svgContent), error: err => reject(new Error(`Failed to load SVG: ${path}. Error: ${err.message}`)), }); }); } /** * Toggles the sidebar's expanded or collapsed state. * Triggers the appropriate expand/collapse event if provided. */ async toggleSidebar() { let event = { cancel: false, click: true, }; // Trigger collapse event if sidebar is currently expanded if (this.sidebarData.options.expand) { await Promise.resolve(this.sidebarData.options.onCollapse?.(event)); } // Trigger expand event if sidebar is currently collapsed else { await Promise.resolve(this.sidebarData.options.onExpand?.(event)); } // If the event was canceled, do not toggle if (event.cancel) return; // Toggle expand/collapse state this.sidebarData.options.expand = !this.sidebarData.options.expand; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NgSidebarService, deps: [{ token: i1.Router }, { token: i2.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NgSidebarService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NgSidebarService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: () => [{ type: i1.Router }, { type: i2.HttpClient }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctc2lkZWJhci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctc2lkZWJhci9zcmMvbGliL25nLXNpZGViYXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBUTNDLE9BQU8sRUFBRSxhQUFhLEVBQVUsTUFBTSxpQkFBaUIsQ0FBQzs7OztBQUd4RDs7Ozs7O0dBTUc7QUFJSCxNQUFNLE9BQU8sZ0JBQWdCO0lBdUIzQjs7Ozs7T0FLRztJQUNILFlBQ1MsTUFBYyxFQUNiLElBQWdCO1FBRGpCLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDYixTQUFJLEdBQUosSUFBSSxDQUFZO1FBOUIxQjs7O1dBR0c7UUFDSCx1QkFBa0IsR0FBWSxLQUFLLENBQUM7UUFFcEM7OztXQUdHO1FBQ0gsZUFBVSxHQUFZLEtBQUssQ0FBQztRQXNCMUIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDOUIsSUFBSSxLQUFLLFlBQVksYUFBYSxFQUFFLENBQUM7Z0JBQ25DLElBQUksQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRTtvQkFDMUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUMvQyxDQUFDLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILG9CQUFvQixDQUNsQixJQUE0RDtRQUU1RCxpQkFBaUI7UUFDakIsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsYUFBYTtZQUNyQyxDQUFDLENBQUM7Z0JBQ0UsSUFBSSxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxJQUFJLCtCQUEr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QUEwRDtRQUMxRCxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3BDLE1BQU0sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3RFLENBQUM7UUFDRCx5REFBeUQ7YUFDcEQsQ0FBQztZQUNKLE1BQU0sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3BFLENBQUM7UUFFRCwyQ0FBMkM7UUFDM0MsSUFBSSxLQUFLLENBQUMsTUFBTTtZQUFFLE9BQU87UUFFekIsK0JBQStCO1FBQy9CLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUNyRSxDQUFDOytHQW5kVSxnQkFBZ0I7bUhBQWhCLGdCQUFnQixjQUZmLE1BQU07OzRGQUVQLGdCQUFnQjtrQkFINUIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7XHJcbiAgRXhwYW5kQ2xpY2tFdmVudCxcclxuICBNZW51RGF0YSxcclxuICBSZXNpemVFdmVudCxcclxuICBTaWRlYmFyRGF0YSxcclxuICBTaWRlYmFyTW9kZWwsXHJcbn0gZnJvbSAnLi9zaWRlYmFyLm1vZGVsJztcclxuaW1wb3J0IHsgTmF2aWdhdGlvbkVuZCwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcclxuaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuXHJcbi8qKlxyXG4gKiBTZXJ2aWNlIHJlc3BvbnNpYmxlIGZvciBtYW5hZ2luZyBzaWRlYmFyIHN0YXRlLCBjb25maWd1cmF0aW9ucywgYW5kIGJlaGF2aW9ycy5cclxuICogSXQgaGFuZGxlcyBzaWRlYmFyIGluaXRpYWxpemF0aW9uLCByZXNpemluZywgbWVudSBpbnRlcmFjdGlvbnMsIGFuZCB0aGVtZSBjaGFuZ2VzLlxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBjbGFzcyBOZ1NpZGViYXJTZXJ2aWNlXHJcbiAqL1xyXG5ASW5qZWN0YWJsZSh7XHJcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTmdTaWRlYmFyU2VydmljZSB7XHJcbiAgLyoqXHJcbiAgICogVHJhY2tzIHdoZXRoZXIgYXV0by1wb3NpdGlvbmluZyBpcyBlbmFibGVkLlxyXG4gICAqIEBkZWZhdWx0IGZhbHNlXHJcbiAgICovXHJcbiAgYXV0b1Bvc2l0aW9uQWN0aXZlOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSBzaWRlYmFyIGlzIGN1cnJlbnRseSBiZWluZyByZXNpemVkLlxyXG4gICAqIEBkZWZhdWx0IGZhbHNlXHJcbiAgICovXHJcbiAgaXNSZXNpemluZzogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBTdG9yZXMgdGhlIGNvbXBsZXRlIHNpZGViYXIgY29uZmlndXJhdGlvbiBhbmQgZGF0YS5cclxuICAgKi9cclxuICBzaWRlYmFyRGF0YSE6IFNpZGViYXJNb2RlbDtcclxuXHJcbiAgLyoqXHJcbiAgICogTXV0YXRpb25PYnNlcnZlciB0byBtb25pdG9yIHNpZGViYXIgc3R5bGUgY2hhbmdlcyBmb3IgYXV0by1wb3NpdGlvbmluZy5cclxuICAgKi9cclxuICBwcml2YXRlIG9ic2VydmVyITogTXV0YXRpb25PYnNlcnZlcjtcclxuXHJcbiAgLyoqXHJcbiAgICogSW5pdGlhbGl6ZXMgdGhlIHNpZGViYXIgc2VydmljZSBhbmQgbGlzdGVucyBmb3Igcm91dGUgY2hhbmdlcy5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7Um91dGVyfSByb3V0ZXIgLSBBbmd1bGFyIFJvdXRlciBmb3IgZGV0ZWN0aW5nIG5hdmlnYXRpb24gZXZlbnRzLlxyXG4gICAqIEBwYXJhbSB7SHR0cENsaWVudH0gaHR0cCAtIEFuZ3VsYXIgSHR0cENsaWVudCBmb3IgbG9hZGluZyBhc3NldHMgKGUuZy4sIFNWRyBpY29ucykuXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwdWJsaWMgcm91dGVyOiBSb3V0ZXIsXHJcbiAgICBwcml2YXRlIGh0dHA6IEh0dHBDbGllbnRcclxuICApIHtcclxuICAgIHJvdXRlci5ldmVudHMuc3Vic2NyaWJlKHJvdXRlID0+IHtcclxuICAgICAgaWYgKHJvdXRlIGluc3RhbmNlb2YgTmF2aWdhdGlvbkVuZCkge1xyXG4gICAgICAgIHRoaXMuc2lkZWJhckRhdGEuc2lkZWJhckRhdGEuZm9yRWFjaChkYXRhID0+IHtcclxuICAgICAgICAgIHRoaXMudXBkYXRlQWN0aXZlU3RhdGUoZGF0YS5kYXRhLCByb3V0ZS51cmwpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEluaXRpYWxpemVzIHRoZSBzaWRlYmFyIGNvbmZpZ3VyYXRpb24gd2l0aCBkZWZhdWx0IHZhbHVlcyBpZiBub3QgcHJvdmlkZWQuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge1BhcnRpYWw8U2lkZWJhck1vZGVsPiAmIHsgc2lkZWJhckRhdGE6IFNpZGViYXJEYXRhW10gfX0gZGF0YSAtIFNpZGViYXIgZGF0YSB3aXRoIG9wdGlvbmFsIGNvbmZpZ3VyYXRpb25zLlxyXG4gICAqIEByZXR1cm5zIHtTaWRlYmFyTW9kZWx9IC0gVGhlIGNvbXBsZXRlIFNpZGViYXJNb2RlbCB3aXRoIGRlZmF1bHQgdmFsdWVzIGFwcGxpZWQuXHJcbiAgICovXHJcbiAgaW5pdGlsYXplU2lkZWJhckRhdGEoXHJcbiAgICBkYXRhOiBQYXJ0aWFsPFNpZGViYXJNb2RlbD4gJiB7IHNpZGViYXJEYXRhOiBTaWRlYmFyRGF0YVtdIH1cclxuICApOiBTaWRlYmFyTW9kZWwge1xyXG4gICAgLy8gQmFubmVyIG9wdGlvbnNcclxuICAgIGRhdGEuYmFubmVyT3B0aW9ucyA9IGRhdGEuYmFubmVyT3B0aW9uc1xyXG4gICAgICA/IHtcclxuICAgICAgICAgIGxvZ286IGRhdGEuYmFubmVyT3B0aW9ucy5sb2dvID8/ICdhc3NldHMvaWNvbnMvYW5ndWxhci1sb2dvLnBuZycsXHJcbiAgICAgICAgICB0aXRsZTogZGF0YS5iYW5uZXJPcHRpb25zLnRpdGxlID8/ICdBbmd1bG9naWMnLFxyXG4gICAgICAgICAgb25DbGljazogZGF0YS5iYW5uZXJPcHRpb25zLm9uQ2xpY2ssXHJcbiAgICAgICAgfVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuXHJcbiAgICAvLyBVc2VyIG9wdGlvbnNcclxuICAgIGRhdGEudXNlck9wdGlvbnMgPSBkYXRhLnVzZXJPcHRpb25zXHJcbiAgICAgID8ge1xyXG4gICAgICAgICAgYXZhdGFyOiBkYXRhLnVzZXJPcHRpb25zLmF2YXRhciA/PyAnYXNzZXRzL2ljb25zL2F2YXRhci5zdmcnLFxyXG4gICAgICAgICAgbmFtZTogZGF0YS51c2VyT3B0aW9ucy5uYW1lLFxyXG4gICAgICAgICAgcG9zaXRpb246IGRhdGEudXNlck9wdGlvbnMucG9zaXRpb24gPz8gJ2JvdHRvbScsXHJcbiAgICAgICAgICBvbkNsaWNrOiBkYXRhLnVzZXJPcHRpb25zLm9uQ2xpY2ssXHJcbiAgICAgICAgfVxyXG4gICAgICA6IHVuZGVmaW5lZDtcclxuXHJcbiAgICAvLyBTZWFyY2ggb3B0aW9uc1xyXG4gICAgZGF0YS5zZWFyY2hPcHRpb25zID0gZGF0YS5zZWFyY2hPcHRpb25zXHJcbiAgICAgID8ge1xyXG4gICAgICAgICAgcGxhY2Vob2xkZXI6IGRhdGEuc2VhcmNoT3B0aW9ucy5wbGFjZWhvbGRlcixcclxuICAgICAgICAgIGNhc2VTZW5zaXRpdmU6IGRhdGEuc2VhcmNoT3B0aW9ucy5jYXNlU2Vuc2l0aXZlID8/IGZhbHNlLFxyXG4gICAgICAgICAgc3RyYXRlZ3k6IGRhdGEuc2VhcmNoT3B0aW9ucy5zdHJhdGVneSA/PyAnY29udGFpbnMnLFxyXG4gICAgICAgICAgY3NzQ2xhc3M6IGRhdGEuc2VhcmNoT3B0aW9ucy5jc3NDbGFzcyxcclxuICAgICAgICAgIGxvY2FsQ29tcGFyZTogZGF0YS5zZWFyY2hPcHRpb25zLmxvY2FsQ29tcGFyZSA/PyAnZW4nLFxyXG4gICAgICAgICAgb25TZWFyY2hTdGFydDogZGF0YS5zZWFyY2hPcHRpb25zLm9uU2VhcmNoU3RhcnQsXHJcbiAgICAgICAgICBvblNlYXJjaEVuZDogZGF0YS5zZWFyY2hPcHRpb25zLm9uU2VhcmNoRW5kLFxyXG4gICAgICAgIH1cclxuICAgICAgOiB1bmRlZmluZWQ7XHJcblxyXG4gICAgLy8gU2lkZWJhciBkYXRhIGluaXRpYWxpemF0aW9uXHJcbiAgICBkYXRhLnNpZGViYXJEYXRhID0gZGF0YS5zaWRlYmFyRGF0YS5tYXAoaXRlbSA9PiAoe1xyXG4gICAgICB0aXRsZTogaXRlbS50aXRsZSxcclxuICAgICAgY3NzQ2xhc3M6IGl0ZW0uY3NzQ2xhc3MsXHJcbiAgICAgIHZpc2libGU6IGl0ZW0udmlzaWJsZSA/PyB0cnVlLFxyXG4gICAgICBkYXRhOiB0aGlzLmluaXRpYWxpemVNZW51RGF0YShpdGVtLmRhdGEpLFxyXG4gICAgfSkpO1xyXG5cclxuICAgIC8vIFNpZGViYXIgb3B0aW9ucyBpbml0aWFsaXphdGlvblxyXG4gICAgZGF0YS5vcHRpb25zID0gZGF0YS5vcHRpb25zXHJcbiAgICAgID8ge1xyXG4gICAgICAgICAgcmVzaXplOiBkYXRhLm9wdGlvbnMucmVzaXplID8/IHRydWUsXHJcbiAgICAgICAgICBleHBhbmQ6IGRhdGEub3B0aW9ucy5leHBhbmQgPz8gdHJ1ZSxcclxuICAgICAgICAgIGZhdm9yaXRlczogZGF0YS5vcHRpb25zLmZhdm9yaXRlcyA/PyB0cnVlLFxyXG4gICAgICAgICAgZmF2b3JpdGVzVGl0bGU6IGRhdGEub3B0aW9ucy5mYXZvcml0ZXNUaXRsZSA/PyAnRmF2b3JpdGVzJyxcclxuICAgICAgICAgIHNlYXJjaDogZGF0YS5vcHRpb25zLnNlYXJjaCA/PyB0cnVlLFxyXG4gICAgICAgICAgY3NzQ2xhc3M6IGRhdGEub3B0aW9ucy5jc3NDbGFzcyA/PyAnJyxcclxuICAgICAgICAgIHZpZXdNb2RlOiBkYXRhLm9wdGlvbnMudmlld01vZGUgPz8gJ3RvZ2dsZScsXHJcbiAgICAgICAgICB0aGVtZTogZGF0YS5vcHRpb25zLnRoZW1lID8/ICdsaWdodCcsXHJcbiAgICAgICAgICB0aGVtZVBpY2tlcjogZGF0YS5vcHRpb25zLnRoZW1lUGlja2VyID8/IHRydWUsXHJcbiAgICAgICAgICBtaW5XaWR0aDogZGF0YS5vcHRpb25zLm1pbldpZHRoID8/IDMwMCxcclxuICAgICAgICAgIG1heFdpZHRoOiBkYXRhLm9wdGlvbnMubWF4V2lkdGggPz8gNTAwLFxyXG4gICAgICAgICAgd2lkdGg6IGRhdGEub3B0aW9ucy53aWR0aCA/PyAzMDAsXHJcbiAgICAgICAgICB0aGVtZVRleHQ6IGRhdGEub3B0aW9ucy50aGVtZVRleHQgPz8geyBsaWdodDogJ0xpZ2h0JywgZGFyazogJ0RhcmsnIH0sXHJcbiAgICAgICAgICBhdXRvUG9zaXRpb246IGRhdGEub3B0aW9ucy5hdXRvUG9zaXRpb24gPz8gdHJ1ZSxcclxuICAgICAgICAgIHRvZ2dsZUNvbGxhcHNlSWNvbjpcclxuICAgICAgICAgICAgZGF0YS5vcHRpb25zLnRvZ2dsZUNvbGxhcHNlSWNvbiA/PyAnYXNzZXRzL2ljb25zL2NvbGxhcHNlLnN2ZycsXHJcbiAgICAgICAgICB0b2dnbGVFeHBhbmRJY29uOlxyXG4gICAgICAgICAgICBkYXRhLm9wdGlvbnMudG9nZ2xlRXhwYW5kSWNvbiA/PyAnYXNzZXRzL2ljb25zL2V4cGFuZC5zdmcnLFxyXG4gICAgICAgICAgcGluSWNvbjogZGF0YS5vcHRpb25zLnBpbkljb24gPz8gJ2Fzc2V0cy9pY29ucy9waW4uc3ZnJyxcclxuICAgICAgICAgIHVucGluSWNvbjogZGF0YS5vcHRpb25zLnVucGluSWNvbiA/PyAnYXNzZXRzL2ljb25zL3VucGluLnN2ZycsXHJcbiAgICAgICAgICBjbG9zZUljb246IGRhdGEub3B0aW9ucy5jbG9zZUljb24gPz8gJ2Fzc2V0cy9pY29ucy9jYW5jZWwuc3ZnJyxcclxuICAgICAgICAgIHBpbm5lZDpcclxuICAgICAgICAgICAgZGF0YS5vcHRpb25zLnBpbm5lZCA/P1xyXG4gICAgICAgICAgICAoZGF0YS5vcHRpb25zLmV4cGFuZCAmJiBkYXRhLm9wdGlvbnMudmlld01vZGUgPT09ICdob3ZlcicpID8/XHJcbiAgICAgICAgICAgIGZhbHNlLFxyXG4gICAgICAgICAgb25UaGVtZUNoYW5nZTogZGF0YS5vcHRpb25zLm9uVGhlbWVDaGFuZ2UsXHJcbiAgICAgICAgICBvblJlc2l6ZVN0YXJ0OiBkYXRhLm9wdGlvbnMub25SZXNpemVTdGFydCxcclxuICAgICAgICAgIG9uUmVzaXppbmc6IGRhdGEub3B0aW9ucy5vblJlc2l6aW5nLFxyXG4gICAgICAgICAgb25SZXNpemVFbmQ6IGRhdGEub3B0aW9ucy5vblJlc2l6ZUVuZCxcclxuICAgICAgICAgIG9uRXhwYW5kOiBkYXRhLm9wdGlvbnMub25FeHBhbmQsXHJcbiAgICAgICAgICBvbkNvbGxhcHNlOiBkYXRhLm9wdGlvbnMub25Db2xsYXBzZSxcclxuICAgICAgICAgIG9uTWVudU5vZGVDbGljazogZGF0YS5vcHRpb25zLm9uTWVudU5vZGVDbGljayxcclxuICAgICAgICB9XHJcbiAgICAgIDoge1xyXG4gICAgICAgICAgcmVzaXplOiB0cnVlLFxyXG4gICAgICAgICAgZXhwYW5kOiB0cnVlLFxyXG4gICAgICAgICAgZmF2b3JpdGVzOiB0cnVlLFxyXG4gICAgICAgICAgc2VhcmNoOiB0cnVlLFxyXG4gICAgICAgICAgdmlld01vZGU6ICd0b2dnbGUnLFxyXG4gICAgICAgICAgdGhlbWU6ICdsaWdodCcsXHJcbiAgICAgICAgfTtcclxuXHJcbiAgICB0aGlzLnNpZGViYXJEYXRhID0gZGF0YSBhcyBTaWRlYmFyTW9kZWw7XHJcbiAgICByZXR1cm4gZGF0YSBhcyBTaWRlYmFyTW9kZWw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFbmFibGVzIGF1dG9tYXRpYyBwb3NpdGlvbmluZyBvZiB0aGUgc2lkZWJhci5cclxuICAgKiBJdCBvYnNlcnZlcyB0aGUgc2lkZWJhcidzIHdpZHRoIGFuZCB1cGRhdGVzIHRoZSBDU1MgdmFyaWFibGUgYC0tc2lkZWJhci13aWR0aGAgZHluYW1pY2FsbHkuXHJcbiAgICovXHJcbiAgc2V0QXV0b1Bvc2l0aW9uKCk6IHZvaWQge1xyXG4gICAgY29uc3QgZGl2RWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCduZy1zaWRlYmFyJyk7XHJcbiAgICBpZiAoIWRpdkVsZW1lbnQpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuY29udGFpbnMoJ2F1dG8tcG9zaXRpb24nKSkge1xyXG4gICAgICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoJ2F1dG8tcG9zaXRpb24nKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBkdXJhdGlvbiA9IDMwMDtcclxuICAgIHRoaXMub2JzZXJ2ZXIgPSBuZXcgTXV0YXRpb25PYnNlcnZlcigoKSA9PiB7XHJcbiAgICAgIGNvbnN0IHdpZHRoID0gZGl2RWxlbWVudC5vZmZzZXRXaWR0aDtcclxuICAgICAgdGhpcy51cGRhdGVXaWR0aChkaXZFbGVtZW50LCBwZXJmb3JtYW5jZS5ub3coKSwgZHVyYXRpb24pO1xyXG4gICAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUuc2V0UHJvcGVydHkoXHJcbiAgICAgICAgJy0tc2lkZWJhci13aWR0aCcsXHJcbiAgICAgICAgYCR7d2lkdGh9cHhgXHJcbiAgICAgICk7XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLm9ic2VydmVyLm9ic2VydmUoZGl2RWxlbWVudCwge1xyXG4gICAgICBhdHRyaWJ1dGVGaWx0ZXI6IFsnc3R5bGUnXSxcclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMuYXV0b1Bvc2l0aW9uQWN0aXZlID0gdHJ1ZTtcclxuICAgIGNvbnNvbGUubG9nKCdBdXRvIHBvc2l0aW9uIGVuYWJsZWQnKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFuaW1hdGVzIHRoZSB3aWR0aCB1cGRhdGUgb2YgdGhlIHNpZGViYXIuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBkaXZFbGVtZW50IC0gVGhlIHNpZGViYXIgZWxlbWVudCB3aG9zZSB3aWR0aCBpcyBiZWluZyB1cGRhdGVkLlxyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzdGFydFRpbWUgLSBUaGUgc3RhcnQgdGltZSBvZiB0aGUgYW5pbWF0aW9uLlxyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBkdXJhdGlvbiAtIFRoZSBkdXJhdGlvbiBvZiB0aGUgd2lkdGggYW5pbWF0aW9uIGluIG1pbGxpc2Vjb25kcy5cclxuICAgKi9cclxuICB1cGRhdGVXaWR0aChcclxuICAgIGRpdkVsZW1lbnQ6IEhUTUxFbGVtZW50LFxyXG4gICAgc3RhcnRUaW1lOiBudW1iZXIsXHJcbiAgICBkdXJhdGlvbjogbnVtYmVyXHJcbiAgKTogdm9pZCB7XHJcbiAgICBjb25zdCBhbmltYXRlV2lkdGggPSAodGltZXN0YW1wOiBudW1iZXIpID0+IHtcclxuICAgICAgbGV0IHByb2dyZXNzID0gKHRpbWVzdGFtcCAtIHN0YXJ0VGltZSkgLyBkdXJhdGlvbjtcclxuICAgICAgY29uc3QgY3VycmVudFdpZHRoID0gZGl2RWxlbWVudC5vZmZzZXRXaWR0aDtcclxuICAgICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLnNldFByb3BlcnR5KFxyXG4gICAgICAgICctLXNpZGViYXItd2lkdGgnLFxyXG4gICAgICAgIGAke2N1cnJlbnRXaWR0aH1weGBcclxuICAgICAgKTtcclxuICAgICAgaWYgKHByb2dyZXNzIDwgMSkge1xyXG4gICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZShhbmltYXRlV2lkdGgpO1xyXG4gICAgICB9XHJcbiAgICB9O1xyXG4gICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKGFuaW1hdGVXaWR0aCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBEaXNhYmxlcyBhdXRvbWF0aWMgcG9zaXRpb25pbmcgb2YgdGhlIHNpZGViYXIuXHJcbiAgICogU3RvcHMgb2JzZXJ2aW5nIHN0eWxlIGNoYW5nZXMgYW5kIHJlc2V0cyBDU1MgbW9kaWZpY2F0aW9ucy5cclxuICAgKi9cclxuICBkZXN0cm95QXV0b1Bvc2l0aW9uKCk6IHZvaWQge1xyXG4gICAgdGhpcy5vYnNlcnZlci5kaXNjb25uZWN0KCk7XHJcbiAgICBpZiAoZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuY29udGFpbnMoJ2F1dG8tcG9zaXRpb24nKSkge1xyXG4gICAgICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5yZW1vdmUoJ2F1dG8tcG9zaXRpb24nKTtcclxuICAgIH1cclxuICAgIHRoaXMuYXV0b1Bvc2l0aW9uQWN0aXZlID0gZmFsc2U7XHJcbiAgICBjb25zb2xlLmxvZygnQXV0byBwb3NpdGlvbiBkaXNhYmxlZCcpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSGFuZGxlcyBzaWRlYmFyIHJlc2l6aW5nIHVzaW5nIG1vdXNlIGV2ZW50cy5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7U2lkZWJhck1vZGVsfSBzaWRlYmFyRGF0YSAtIFRoZSBzaWRlYmFyIGNvbmZpZ3VyYXRpb24gb2JqZWN0LlxyXG4gICAqL1xyXG4gIHJlc2l6ZShzaWRlYmFyRGF0YTogU2lkZWJhck1vZGVsKTogdm9pZCB7XHJcbiAgICB0aGlzLmlzUmVzaXppbmcgPSB0cnVlO1xyXG4gICAgY29uc3QgaW5pdGlhbFBpbiA9IHNpZGViYXJEYXRhLm9wdGlvbnMucGlubmVkO1xyXG4gICAgc2lkZWJhckRhdGEub3B0aW9ucy5waW5uZWQgPSB0cnVlO1xyXG5cclxuICAgIGNvbnN0IHN0YXJ0RXZlbnQ6IFJlc2l6ZUV2ZW50ID0ge1xyXG4gICAgICBjYW5jZWw6IGZhbHNlLFxyXG4gICAgICBzaWRlYmFyT3B0aW9uczogc2lkZWJhckRhdGEsXHJcbiAgICB9O1xyXG5cclxuICAgIGlmIChzaWRlYmFyRGF0YS5vcHRpb25zLm9uUmVzaXplU3RhcnQpIHtcclxuICAgICAgc2lkZWJhckRhdGEub3B0aW9ucy5vblJlc2l6ZVN0YXJ0KHN0YXJ0RXZlbnQpO1xyXG4gICAgICBpZiAoc3RhcnRFdmVudC5jYW5jZWwpIHtcclxuICAgICAgICB0aGlzLmlzUmVzaXppbmcgPSBmYWxzZTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoJ25vLXNlbGVjdCcpO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGFuZGxlcyBtb3VzZSBtb3ZlbWVudCBkdXJpbmcgcmVzaXppbmcuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtNb3VzZUV2ZW50fSBlIC0gVGhlIG1vdXNlIG1vdmVtZW50IGV2ZW50LlxyXG4gICAgICovXHJcbiAgICBjb25zdCBtb3VzZU1vdmVMaXN0ZW5lciA9IChlOiBNb3VzZUV2ZW50KSA9PiB7XHJcbiAgICAgIGNvbnN0IHJlc2l6ZUV2ZW50OiBSZXNpemVFdmVudCA9IHtcclxuICAgICAgICBjYW5jZWw6IGZhbHNlLFxyXG4gICAgICAgIHNpZGViYXJPcHRpb25zOiBzaWRlYmFyRGF0YSxcclxuICAgICAgICBtb3VzZUV2ZW50OiBlLFxyXG4gICAgICB9O1xyXG5cclxuICAgICAgaWYgKHNpZGViYXJEYXRhLm9wdGlvbnMub25SZXNpemluZykge1xyXG4gICAgICAgIHNpZGViYXJEYXRhLm9wdGlvbnMub25SZXNpemluZyhyZXNpemVFdmVudCk7XHJcbiAgICAgICAgaWYgKHJlc2l6ZUV2ZW50LmNhbmNlbCkge1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKFxyXG4gICAgICAgIHNpZGViYXJEYXRhLm9wdGlvbnMubWluV2lkdGggJiZcclxuICAgICAgICBlLmNsaWVudFggPCBzaWRlYmFyRGF0YS5vcHRpb25zLm1pbldpZHRoXHJcbiAgICAgICkge1xyXG4gICAgICAgIHNpZGViYXJEYXRhLm9wdGlvbnMud2lkdGggPSBzaWRlYmFyRGF0YS5vcHRpb25zLm1pbldpZHRoO1xyXG4gICAgICB9IGVsc2UgaWYgKFxyXG4gICAgICAgIHNpZGViYXJEYXRhLm9wdGlvbnMubWF4V2lkdGggJiZcclxuICAgICAgICBlLmNsaWVudFggPiBzaWRlYmFyRGF0YS5vcHRpb25zLm1heFdpZHRoXHJcbiAgICAgICkge1xyXG4gICAgICAgIHNpZGViYXJEYXRhLm9wdGlvbnMud2lkdGggPSBzaWRlYmFyRGF0YS5vcHRpb25zLm1heFdpZHRoO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHNpZGViYXJEYXRhLm9wdGlvbnMud2lkdGggPSBlLmNsaWVudFg7XHJcbiAgICAgIH1cclxuICAgIH07XHJcblxyXG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgbW91c2VNb3ZlTGlzdGVuZXIpO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGFuZGxlcyBtb3VzZSByZWxlYXNlIGFmdGVyIHJlc2l6aW5nLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSB7TW91c2VFdmVudH0gZSAtIFRoZSBtb3VzZSB1cCBldmVudC5cclxuICAgICAqL1xyXG4gICAgY29uc3QgbW91c2VVcExpc3RlbmVyID0gKGU6IE1vdXNlRXZlbnQpID0+IHtcclxuICAgICAgZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QucmVtb3ZlKCduby1zZWxlY3QnKTtcclxuICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgbW91c2VNb3ZlTGlzdGVuZXIpO1xyXG4gICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgbW91c2VVcExpc3RlbmVyKTtcclxuXHJcbiAgICAgIHRoaXMuaXNSZXNpemluZyA9IGZhbHNlO1xyXG4gICAgICBzaWRlYmFyRGF0YS5vcHRpb25zLnBpbm5lZCA9IGluaXRpYWxQaW47XHJcblxyXG4gICAgICBjb25zdCBlbmRFdmVudDogUmVzaXplRXZlbnQgPSB7XHJcbiAgICAgICAgc2lkZWJhck9wdGlvbnM6IHNpZGViYXJEYXRhLFxyXG4gICAgICAgIG1vdXNlRXZlbnQ6IGUsXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBpZiAoc2lkZWJhckRhdGEub3B0aW9ucy5vblJlc2l6ZUVuZCkge1xyXG4gICAgICAgIHNpZGViYXJEYXRhLm9wdGlvbnMub25SZXNpemVFbmQoZW5kRXZlbnQpO1xyXG4gICAgICB9XHJcbiAgICB9O1xyXG5cclxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBtb3VzZVVwTGlzdGVuZXIpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSW5pdGlhbGl6ZXMgbWVudSBkYXRhIGJ5IGFzc2lnbmluZyBkZWZhdWx0IHZhbHVlcyBpZiBub3QgcHJvdmlkZWQuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge01lbnVEYXRhW119IG1lbnVEYXRhIC0gVGhlIG1lbnUgZGF0YSBhcnJheSB0byBpbml0aWFsaXplLlxyXG4gICAqIEByZXR1cm5zIHtNZW51RGF0YVtdfSAtIFRoZSBwcm9jZXNzZWQgbWVudSBkYXRhIHdpdGggZGVmYXVsdCB2YWx1ZXMgYXBwbGllZC5cclxuICAgKi9cclxuICBwcml2YXRlIGluaXRpYWxpemVNZW51RGF0YShtZW51RGF0YTogTWVudURhdGFbXSk6IE1lbnVEYXRhW10ge1xyXG4gICAgcmV0dXJuIG1lbnVEYXRhLm1hcChpdGVtID0+IHtcclxuICAgICAgaXRlbVsnbmFtZSddID0gaXRlbVsnbmFtZSddO1xyXG4gICAgICBpdGVtWydpY29uJ10gPSBpdGVtWydpY29uJ107XHJcbiAgICAgIGl0ZW1bJ3JvdXRlJ10gPSBpdGVtWydyb3V0ZSddO1xyXG4gICAgICBpdGVtWyd2aXNpYmxlJ10gPSBpdGVtWyd2aXNpYmxlJ10gPz8gdHJ1ZTtcclxuICAgICAgaXRlbVsnZGlzYWJsZWQnXSA9IGl0ZW1bJ2Rpc2FibGVkJ10gPz8gZmFsc2U7XHJcbiAgICAgIGl0ZW1bJ2lzRXhwYW5kZWQnXSA9IGl0ZW1bJ2lzRXhwYW5kZWQnXSA/PyBmYWxzZTtcclxuICAgICAgaXRlbVsnaXNGYXZvcml0ZWQnXSA9IGl0ZW1bJ2lzRmF2b3JpdGVkJ10gPz8gZmFsc2U7XHJcbiAgICAgIGl0ZW1bJ2Nzc0NsYXNzJ10gPSBpdGVtWydjc3NDbGFzcyddO1xyXG4gICAgICBpdGVtWydhY3RpdmUnXSA9IGl0ZW1bJ2FjdGl2ZSddID8/IGZhbHNlO1xyXG4gICAgICBpdGVtWydjaGlsZHJlbiddID0gaXRlbVsnY2hpbGRyZW4nXVxyXG4gICAgICAgID8gdGhpcy5pbml0aWFsaXplTWVudURhdGEoaXRlbVsnY2hpbGRyZW4nXSlcclxuICAgICAgICA6IHVuZGVmaW5lZDtcclxuICAgICAgaXRlbVsnb25DbGljayddID0gaXRlbVsnb25DbGljayddO1xyXG4gICAgICByZXR1cm4gaXRlbTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2VhcmNoZXMgZm9yIG1lbnUgaXRlbXMgYnkgbmFtZSB3aXRoaW4gdGhlIHNpZGViYXIgZGF0YS5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7U2lkZWJhck1vZGVsfSBkYXRhIC0gVGhlIHNpZGViYXIgY29uZmlndXJhdGlvbiBjb250YWluaW5nIG1lbnUgZGF0YS5cclxuICAgKiBAcGFyYW0ge3N0cmluZ30gc2VhcmNoVmFsdWUgLSBUaGUgc2VhcmNoIHF1ZXJ5IGVudGVyZWQgYnkgdGhlIHVzZXIuXHJcbiAgICogQHJldHVybnMge01lbnVEYXRhW119IC0gQW4gYXJyYXkgb2YgbWF0Y2hpbmcgbWVudSBpdGVtcy5cclxuICAgKi9cclxuICBzZWFyY2hCeU5hbWUoZGF0YTogU2lkZWJhck1vZGVsLCBzZWFyY2hWYWx1ZTogc3RyaW5nKTogTWVudURhdGFbXSB7XHJcbiAgICBjb25zdCB7IHNlYXJjaE9wdGlvbnMsIHNpZGViYXJEYXRhIH0gPSBkYXRhO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ29tcGFyZXMgdHdvIHN0cmluZ3MgYmFzZWQgb24gdGhlIGNvbmZpZ3VyZWQgc2VhcmNoIG9wdGlvbnMuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSAtIFRoZSBvcmlnaW5hbCBtZW51IGl0ZW0gbmFtZS5cclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0YXJnZXQgLSBUaGUgc2VhcmNoIHF1ZXJ5IGVudGVyZWQgYnkgdGhlIHVzZXIuXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBUcnVlIGlmIHRoZSBzZWFyY2ggY3JpdGVyaWEgbWF0Y2gsIGZhbHNlIG90aGVyd2lzZS5cclxuICAgICAqL1xyXG4gICAgY29uc3QgY29tcGFyZVN0cmluZ3MgPSAoc291cmNlOiBzdHJpbmcsIHRhcmdldDogc3RyaW5nKTogYm9vbGVhbiA9PiB7XHJcbiAgICAgIGlmICghc2VhcmNoT3B0aW9ucz8uY2FzZVNlbnNpdGl2ZSkge1xyXG4gICAgICAgIHNvdXJjZSA9IHNvdXJjZS50b0xvY2FsZUxvd2VyQ2FzZShzZWFyY2hPcHRpb25zPy5sb2NhbENvbXBhcmUpO1xyXG4gICAgICAgIHRhcmdldCA9IHRhcmdldC50b0xvY2FsZUxvd2VyQ2FzZShzZWFyY2hPcHRpb25zPy5sb2NhbENvbXBhcmUpO1xyXG4gICAgICB9XHJcbiAgICAgIHN3aXRjaCAoc2VhcmNoT3B0aW9ucz8uc3RyYXRlZ3kpIHtcclxuICAgICAgICBjYXNlICdjb250YWlucyc6XHJcbiAgICAgICAgICByZXR1cm4gc291cmNlLmluY2x1ZGVzKHRhcmdldCk7XHJcbiAgICAgICAgY2FzZSAnc3RhcnRzV2l0aCc6XHJcbiAgICAgICAgICByZXR1cm4gc291cmNlLnN0YXJ0c1dpdGgodGFyZ2V0KTtcclxuICAgICAgICBjYXNlICdlbmRzV2l0aCc6XHJcbiAgICAgICAgICByZXR1cm4gc291cmNlLmVuZHNXaXRoKHRhcmdldCk7XHJcbiAgICAgICAgY2FzZSAnZXF1YWwnOlxyXG4gICAgICAgICAgcmV0dXJuIHNvdXJjZSA9PT0gdGFyZ2V0O1xyXG4gICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgIH1cclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWN1cnNpdmVseSBzZWFyY2hlcyBtZW51IGl0ZW1zI