@angulogic/ng-sidebar
Version:
angular sidebar
417 lines • 54.8 kB
JavaScript
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