UNPKG

angular-google-charts

Version:

A wrapper for the Google Charts library written with Angular

209 lines 30.9 kB
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Optional, Output } from '@angular/core'; import { fromEvent, ReplaySubject } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; import { getPackageForChart } from '../../helpers/chart.helper'; import { DataTableService } from '../../services/data-table.service'; import { ScriptLoaderService } from '../../services/script-loader.service'; import { ChartType } from '../../types/chart-type'; import { DashboardComponent } from '../dashboard/dashboard.component'; import * as i0 from "@angular/core"; import * as i1 from "../../services/script-loader.service"; import * as i2 from "../../services/data-table.service"; import * as i3 from "../dashboard/dashboard.component"; export class GoogleChartComponent { constructor(element, scriptLoaderService, dataTableService, dashboard) { this.element = element; this.scriptLoaderService = scriptLoaderService; this.dataTableService = dataTableService; this.dashboard = dashboard; /** * The chart-specific options. All options listen in the Google Charts documentation applying * to the chart type specified can be used here. */ this.options = {}; /** * If this is set to `true`, the chart will be redrawn if the browser window is resized. * Defaults to `false` and should only be used when specifying the width or height of the chart * in percent. * * Note that this can impact performance. */ this.dynamicResize = false; this.ready = new EventEmitter(); this.error = new EventEmitter(); this.select = new EventEmitter(); this.mouseover = new EventEmitter(); this.mouseleave = new EventEmitter(); this.wrapperReadySubject = new ReplaySubject(1); this.initialized = false; this.eventListeners = new Map(); } get chart() { return this.chartWrapper.getChart(); } get wrapperReady$() { return this.wrapperReadySubject.asObservable(); } get chartWrapper() { if (!this.wrapper) { throw new Error('Trying to access the chart wrapper before it was fully initialized'); } return this.wrapper; } set chartWrapper(wrapper) { this.wrapper = wrapper; this.drawChart(); } ngOnInit() { // We don't need to load any chart packages, the chart wrapper will handle this for us this.scriptLoaderService.loadChartPackages(getPackageForChart(this.type)).subscribe(() => { this.dataTable = this.dataTableService.create(this.data, this.columns, this.formatters); // Only ever create the wrapper once to allow animations to happen when something changes. this.wrapper = new google.visualization.ChartWrapper({ container: this.element.nativeElement, chartType: this.type, dataTable: this.dataTable, options: this.mergeOptions() }); this.registerChartEvents(); this.wrapperReadySubject.next(this.wrapper); this.initialized = true; this.drawChart(); }); } ngOnChanges(changes) { if (changes.dynamicResize) { this.updateResizeListener(); } if (this.initialized) { let shouldRedraw = false; if (changes.data || changes.columns || changes.formatters) { this.dataTable = this.dataTableService.create(this.data, this.columns, this.formatters); this.wrapper.setDataTable(this.dataTable); shouldRedraw = true; } if (changes.type) { this.wrapper.setChartType(this.type); shouldRedraw = true; } if (changes.options || changes.width || changes.height || changes.title) { this.wrapper.setOptions(this.mergeOptions()); shouldRedraw = true; } if (shouldRedraw) { this.drawChart(); } } } ngOnDestroy() { this.unsubscribeToResizeIfSubscribed(); } /** * For listening to events other than the most common ones (available via Output properties). * * Can be called after the chart emits that it's "ready". * * Returns a handle that can be used for `removeEventListener`. */ addEventListener(eventName, callback) { const handle = this.registerChartEvent(this.chart, eventName, callback); this.eventListeners.set(handle, { eventName, callback, handle }); return handle; } removeEventListener(handle) { const entry = this.eventListeners.get(handle); if (entry) { google.visualization.events.removeListener(entry.handle); this.eventListeners.delete(handle); } } updateResizeListener() { this.unsubscribeToResizeIfSubscribed(); if (this.dynamicResize) { this.resizeSubscription = fromEvent(window, 'resize', { passive: true }) .pipe(debounceTime(100)) .subscribe(() => { if (this.initialized) { this.drawChart(); } }); } } unsubscribeToResizeIfSubscribed() { if (this.resizeSubscription != null) { this.resizeSubscription.unsubscribe(); this.resizeSubscription = undefined; } } mergeOptions() { return { title: this.title, width: this.width, height: this.height, ...this.options }; } registerChartEvents() { google.visualization.events.removeAllListeners(this.wrapper); this.registerChartEvent(this.wrapper, 'ready', () => { // This could also be done by checking if we already subscribed to the events google.visualization.events.removeAllListeners(this.chart); this.registerChartEvent(this.chart, 'onmouseover', (event) => this.mouseover.emit(event)); this.registerChartEvent(this.chart, 'onmouseout', (event) => this.mouseleave.emit(event)); this.registerChartEvent(this.chart, 'select', () => { const selection = this.chart.getSelection(); this.select.emit({ selection }); }); this.eventListeners.forEach(x => (x.handle = this.registerChartEvent(this.chart, x.eventName, x.callback))); this.ready.emit({ chart: this.chart }); }); this.registerChartEvent(this.wrapper, 'error', (error) => this.error.emit(error)); } registerChartEvent(object, eventName, callback) { return google.visualization.events.addListener(object, eventName, callback); } drawChart() { if (this.dashboard != null) { // If this chart is part of a dashboard, the dashboard takes care of drawing return; } this.wrapper.draw(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GoogleChartComponent, deps: [{ token: i0.ElementRef }, { token: i1.ScriptLoaderService }, { token: i2.DataTableService }, { token: i3.DashboardComponent, optional: true }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: GoogleChartComponent, selector: "google-chart", inputs: { type: "type", data: "data", columns: "columns", title: "title", width: "width", height: "height", options: "options", formatters: "formatters", dynamicResize: "dynamicResize" }, outputs: { ready: "ready", error: "error", select: "select", mouseover: "mouseover", mouseleave: "mouseleave" }, host: { classAttribute: "google-chart" }, exportAs: ["googleChart"], usesOnChanges: true, ngImport: i0, template: '', isInline: true, styles: [":host{width:-moz-fit-content;width:fit-content;display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: GoogleChartComponent, decorators: [{ type: Component, args: [{ selector: 'google-chart', template: '', host: { class: 'google-chart' }, exportAs: 'googleChart', changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{width:-moz-fit-content;width:fit-content;display:block}\n"] }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.ScriptLoaderService }, { type: i2.DataTableService }, { type: i3.DashboardComponent, decorators: [{ type: Optional }] }]; }, propDecorators: { type: [{ type: Input }], data: [{ type: Input }], columns: [{ type: Input }], title: [{ type: Input }], width: [{ type: Input }], height: [{ type: Input }], options: [{ type: Input }], formatters: [{ type: Input }], dynamicResize: [{ type: Input }], ready: [{ type: Output }], error: [{ type: Output }], select: [{ type: Output }], mouseover: [{ type: Output }], mouseleave: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ29vZ2xlLWNoYXJ0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FuZ3VsYXItZ29vZ2xlLWNoYXJ0cy9zcmMvbGliL2NvbXBvbmVudHMvZ29vZ2xlLWNoYXJ0L2dvb2dsZS1jaGFydC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixLQUFLLEVBSUwsUUFBUSxFQUNSLE1BQU0sRUFFUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsU0FBUyxFQUFjLGFBQWEsRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDMUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTlDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3JFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQzNFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQVVuRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQzs7Ozs7QUFVdEUsTUFBTSxPQUFPLG9CQUFvQjtJQWlHL0IsWUFDVSxPQUFtQixFQUNuQixtQkFBd0MsRUFDeEMsZ0JBQWtDLEVBQ3RCLFNBQThCO1FBSDFDLFlBQU8sR0FBUCxPQUFPLENBQVk7UUFDbkIsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjtRQUN4QyxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWtCO1FBQ3RCLGNBQVMsR0FBVCxTQUFTLENBQXFCO1FBckRwRDs7O1dBR0c7UUFFSSxZQUFPLEdBQVcsRUFBRSxDQUFDO1FBVzVCOzs7Ozs7V0FNRztRQUVJLGtCQUFhLEdBQUcsS0FBSyxDQUFDO1FBR3RCLFVBQUssR0FBRyxJQUFJLFlBQVksRUFBbUIsQ0FBQztRQUc1QyxVQUFLLEdBQUcsSUFBSSxZQUFZLEVBQW1CLENBQUM7UUFHNUMsV0FBTSxHQUFHLElBQUksWUFBWSxFQUE4QixDQUFDO1FBR3hELGNBQVMsR0FBRyxJQUFJLFlBQVksRUFBdUIsQ0FBQztRQUdwRCxlQUFVLEdBQUcsSUFBSSxZQUFZLEVBQXdCLENBQUM7UUFNckQsd0JBQW1CLEdBQUcsSUFBSSxhQUFhLENBQW9DLENBQUMsQ0FBQyxDQUFDO1FBQzlFLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLG1CQUFjLEdBQUcsSUFBSSxHQUFHLEVBQStELENBQUM7SUFPN0YsQ0FBQztJQUVKLElBQVcsS0FBSztRQUNkLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUN0QyxDQUFDO0lBRUQsSUFBVyxhQUFhO1FBQ3RCLE9BQU8sSUFBSSxDQUFDLG1CQUFtQixDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ2pELENBQUM7SUFFRCxJQUFXLFlBQVk7UUFDckIsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQyxvRUFBb0UsQ0FBQyxDQUFDO1NBQ3ZGO1FBRUQsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3RCLENBQUM7SUFFRCxJQUFXLFlBQVksQ0FBQyxPQUEwQztRQUNoRSxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUVNLFFBQVE7UUFDYixzRkFBc0Y7UUFDdEYsSUFBSSxDQUFDLG1CQUFtQixDQUFDLGlCQUFpQixDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDdkYsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFFeEYsMEZBQTBGO1lBQzFGLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxNQUFNLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQztnQkFDbkQsU0FBUyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYTtnQkFDckMsU0FBUyxFQUFFLElBQUksQ0FBQyxJQUFJO2dCQUNwQixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7Z0JBQ3pCLE9BQU8sRUFBRSxJQUFJLENBQUMsWUFBWSxFQUFFO2FBQzdCLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBRTNCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzVDLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO1lBRXhCLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUNuQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTSxXQUFXLENBQUMsT0FBc0I7UUFDdkMsSUFBSSxPQUFPLENBQUMsYUFBYSxFQUFFO1lBQ3pCLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1NBQzdCO1FBRUQsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ3BCLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztZQUN6QixJQUFJLE9BQU8sQ0FBQyxJQUFJLElBQUksT0FBTyxDQUFDLE9BQU8sSUFBSSxPQUFPLENBQUMsVUFBVSxFQUFFO2dCQUN6RCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDeEYsSUFBSSxDQUFDLE9BQVEsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVUsQ0FBQyxDQUFDO2dCQUM1QyxZQUFZLEdBQUcsSUFBSSxDQUFDO2FBQ3JCO1lBRUQsSUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFO2dCQUNoQixJQUFJLENBQUMsT0FBUSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3RDLFlBQVksR0FBRyxJQUFJLENBQUM7YUFDckI7WUFFRCxJQUFJLE9BQU8sQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLEtBQUssSUFBSSxPQUFPLENBQUMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxLQUFLLEVBQUU7Z0JBQ3ZFLElBQUksQ0FBQyxPQUFRLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO2dCQUM5QyxZQUFZLEdBQUcsSUFBSSxDQUFDO2FBQ3JCO1lBRUQsSUFBSSxZQUFZLEVBQUU7Z0JBQ2hCLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQzthQUNsQjtTQUNGO0lBQ0gsQ0FBQztJQUVNLFdBQVc7UUFDaEIsSUFBSSxDQUFDLCtCQUErQixFQUFFLENBQUM7SUFDekMsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLGdCQUFnQixDQUFDLFNBQWlCLEVBQUUsUUFBa0I7UUFDM0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ3hFLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUNqRSxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRU0sbUJBQW1CLENBQUMsTUFBVztRQUNwQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5QyxJQUFJLEtBQUssRUFBRTtZQUNULE1BQU0sQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDekQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7U0FDcEM7SUFDSCxDQUFDO0lBRU8sb0JBQW9CO1FBQzFCLElBQUksQ0FBQywrQkFBK0IsRUFBRSxDQUFDO1FBRXZDLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRTtZQUN0QixJQUFJLENBQUMsa0JBQWtCLEdBQUcsU0FBUyxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUM7aUJBQ3JFLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7aUJBQ3ZCLFNBQVMsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2QsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO29CQUNwQixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7aUJBQ2xCO1lBQ0gsQ0FBQyxDQUFDLENBQUM7U0FDTjtJQUNILENBQUM7SUFFTywrQkFBK0I7UUFDckMsSUFBSSxJQUFJLENBQUMsa0JBQWtCLElBQUksSUFBSSxFQUFFO1lBQ25DLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN0QyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsU0FBUyxDQUFDO1NBQ3JDO0lBQ0gsQ0FBQztJQUVPLFlBQVk7UUFDbEIsT0FBTztZQUNMLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztZQUNqQixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUs7WUFDakIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLEdBQUcsSUFBSSxDQUFDLE9BQU87U0FDaEIsQ0FBQztJQUNKLENBQUM7SUFFTyxtQkFBbUI7UUFDekIsTUFBTSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTdELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUU7WUFDbEQsNkVBQTZFO1lBQzdFLE1BQU0sQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMzRCxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxhQUFhLEVBQUUsQ0FBQyxLQUEwQixFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQy9HLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLFlBQVksRUFBRSxDQUFDLEtBQTJCLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDaEgsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRTtnQkFDakQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDN0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO1lBQ2xDLENBQUMsQ0FBQyxDQUFDO1lBQ0gsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBRTVHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQzFDLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUMsS0FBc0IsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNyRyxDQUFDO0lBRU8sa0JBQWtCLENBQUMsTUFBVyxFQUFFLFNBQWlCLEVBQUUsUUFBa0I7UUFDM0UsT0FBTyxNQUFNLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUM5RSxDQUFDO0lBRU8sU0FBUztRQUNmLElBQUksSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLEVBQUU7WUFDMUIsNEVBQTRFO1lBQzVFLE9BQU87U0FDUjtRQUVELElBQUksQ0FBQyxPQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDdkIsQ0FBQzsrR0F0UVUsb0JBQW9CO21HQUFwQixvQkFBb0IsMmJBTnJCLEVBQUU7OzRGQU1ELG9CQUFvQjtrQkFSaEMsU0FBUzsrQkFDRSxjQUFjLFlBQ2QsRUFBRSxRQUVOLEVBQUUsS0FBSyxFQUFFLGNBQWMsRUFBRSxZQUNyQixhQUFhLG1CQUNOLHVCQUF1QixDQUFDLE1BQU07OzBCQXVHNUMsUUFBUTs0Q0FoR0osSUFBSTtzQkFEVixLQUFLO2dCQVNDLElBQUk7c0JBRFYsS0FBSztnQkFVQyxPQUFPO3NCQURiLEtBQUs7Z0JBU0MsS0FBSztzQkFEWCxLQUFLO2dCQVNDLEtBQUs7c0JBRFgsS0FBSztnQkFTQyxNQUFNO3NCQURaLEtBQUs7Z0JBUUMsT0FBTztzQkFEYixLQUFLO2dCQVVDLFVBQVU7c0JBRGhCLEtBQUs7Z0JBV0MsYUFBYTtzQkFEbkIsS0FBSztnQkFJQyxLQUFLO3NCQURYLE1BQU07Z0JBSUEsS0FBSztzQkFEWCxNQUFNO2dCQUlBLE1BQU07c0JBRFosTUFBTTtnQkFJQSxTQUFTO3NCQURmLE1BQU07Z0JBSUEsVUFBVTtzQkFEaEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXNcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBmcm9tRXZlbnQsIE9ic2VydmFibGUsIFJlcGxheVN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBnZXRQYWNrYWdlRm9yQ2hhcnQgfSBmcm9tICcuLi8uLi9oZWxwZXJzL2NoYXJ0LmhlbHBlcic7XG5pbXBvcnQgeyBEYXRhVGFibGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvZGF0YS10YWJsZS5zZXJ2aWNlJztcbmltcG9ydCB7IFNjcmlwdExvYWRlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9zY3JpcHQtbG9hZGVyLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ2hhcnRUeXBlIH0gZnJvbSAnLi4vLi4vdHlwZXMvY2hhcnQtdHlwZSc7XG5pbXBvcnQge1xuICBDaGFydEVycm9yRXZlbnQsXG4gIENoYXJ0TW91c2VMZWF2ZUV2ZW50LFxuICBDaGFydE1vdXNlT3ZlckV2ZW50LFxuICBDaGFydFJlYWR5RXZlbnQsXG4gIENoYXJ0U2VsZWN0aW9uQ2hhbmdlZEV2ZW50XG59IGZyb20gJy4uLy4uL3R5cGVzL2V2ZW50cyc7XG5pbXBvcnQgeyBGb3JtYXR0ZXIgfSBmcm9tICcuLi8uLi90eXBlcy9mb3JtYXR0ZXInO1xuaW1wb3J0IHsgQ2hhcnRCYXNlLCBDb2x1bW4sIFJvdyB9IGZyb20gJy4uL2NoYXJ0LWJhc2UvY2hhcnQtYmFzZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgRGFzaGJvYXJkQ29tcG9uZW50IH0gZnJvbSAnLi4vZGFzaGJvYXJkL2Rhc2hib2FyZC5jb21wb25lbnQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdnb29nbGUtY2hhcnQnLFxuICB0ZW1wbGF0ZTogJycsXG4gIHN0eWxlczogWyc6aG9zdCB7IHdpZHRoOiBmaXQtY29udGVudDsgZGlzcGxheTogYmxvY2s7IH0nXSxcbiAgaG9zdDogeyBjbGFzczogJ2dvb2dsZS1jaGFydCcgfSxcbiAgZXhwb3J0QXM6ICdnb29nbGVDaGFydCcsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIEdvb2dsZUNoYXJ0Q29tcG9uZW50IGltcGxlbWVudHMgQ2hhcnRCYXNlLCBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcbiAgLyoqXG4gICAqIFRoZSB0eXBlIG9mIHRoZSBjaGFydCB0byBjcmVhdGUuXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgdHlwZSE6IENoYXJ0VHlwZTtcblxuICAvKipcbiAgICogRGF0YSB1c2VkIHRvIGluaXRpYWxpemUgdGhlIHRhYmxlLlxuICAgKlxuICAgKiBUaGlzIG11c3QgYWxzbyBjb250YWluIGFsbCByb2xlcyB0aGF0IGFyZSBzZXQgaW4gdGhlIGBjb2x1bW5zYCBwcm9wZXJ0eS5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBkYXRhITogUm93W107XG5cbiAgLyoqXG4gICAqIFRoZSBjb2x1bW5zIHRoZSBgZGF0YWAgY29uc2lzdHMgb2YuXG4gICAqIFRoZSBsZW5ndGggb2YgdGhpcyBhcnJheSBtdXN0IG1hdGNoIHRoZSBsZW5ndGggb2YgZWFjaCByb3cgaW4gdGhlIGBkYXRhYCBvYmplY3QuXG4gICAqXG4gICAqIElmIHtAbGluayBodHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS9jaGFydC9pbnRlcmFjdGl2ZS9kb2NzL3JvbGVzIHJvbGVzfSBzaG91bGQgYmUgYXBwbGllZCwgdGhleSBtdXN0IGJlIGluY2x1ZGVkIGluIHRoaXMgYXJyYXkgYXMgd2VsbC5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjb2x1bW5zPzogQ29sdW1uW107XG5cbiAgLyoqXG4gICAqIEEgY29udmVuaWVuY2UgcHJvcGVydHkgdXNlZCB0byBzZXQgdGhlIHRpdGxlIG9mIHRoZSBjaGFydC5cbiAgICpcbiAgICogVGhpcyBjYW4gYWxzbyBiZSBzZXQgdXNpbmcgYG9wdGlvbnMudGl0bGVgLCB3aGljaCwgaWYgZXhpc3RhbnQsIHdpbGwgb3ZlcndyaXRlIHRoaXMgdmFsdWUuXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgdGl0bGU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgY29udmVuaWVuY2UgcHJvcGVydHkgdXNlZCB0byBzZXQgdGhlIHdpZHRoIG9mIHRoZSBjaGFydCBpbiBwaXhlbHMuXG4gICAqXG4gICAqIFRoaXMgY2FuIGFsc28gYmUgc2V0IHVzaW5nIGBvcHRpb25zLndpZHRoYCwgd2hpY2gsIGlmIGV4aXN0YW50LCB3aWxsIG92ZXJ3cml0ZSB0aGlzIHZhbHVlLlxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIHdpZHRoPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBBIGNvbnZlbmllbmNlIHByb3BlcnR5IHVzZWQgdG8gc2V0IHRoZSBoZWlnaHQgb2YgdGhlIGNoYXJ0IGluIHBpeGVscy5cbiAgICpcbiAgICogVGhpcyBjYW4gYWxzbyBiZSBzZXQgdXNpbmcgYG9wdGlvbnMuaGVpZ2h0YCwgd2hpY2gsIGlmIGV4aXN0YW50LCB3aWxsIG92ZXJ3cml0ZSB0aGlzIHZhbHVlLlxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIGhlaWdodD86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIGNoYXJ0LXNwZWNpZmljIG9wdGlvbnMuIEFsbCBvcHRpb25zIGxpc3RlbiBpbiB0aGUgR29vZ2xlIENoYXJ0cyBkb2N1bWVudGF0aW9uIGFwcGx5aW5nXG4gICAqIHRvIHRoZSBjaGFydCB0eXBlIHNwZWNpZmllZCBjYW4gYmUgdXNlZCBoZXJlLlxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIG9wdGlvbnM6IG9iamVjdCA9IHt9O1xuXG4gIC8qKlxuICAgKiBVc2VkIHRvIGNoYW5nZSB0aGUgZGlzcGxheWVkIHZhbHVlIG9mIHRoZSBzcGVjaWZpZWQgY29sdW1uIGluIGFsbCByb3dzLlxuICAgKlxuICAgKiBFYWNoIGFycmF5IGVsZW1lbnQgbXVzdCBjb25zaXN0IG9mIGFuIGluc3RhbmNlIG9mIGEgW2Bmb3JtYXR0ZXJgXShodHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS9jaGFydC9pbnRlcmFjdGl2ZS9kb2NzL3JlZmVyZW5jZSNmb3JtYXR0ZXJzKVxuICAgKiBhbmQgdGhlIGluZGV4IG9mIHRoZSBjb2x1bW4geW91IHdhbnQgdGhlIGZvcm1hdHRlciB0byBnZXQgYXBwbGllZCB0by5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBmb3JtYXR0ZXJzPzogRm9ybWF0dGVyW107XG5cbiAgLyoqXG4gICAqIElmIHRoaXMgaXMgc2V0IHRvIGB0cnVlYCwgdGhlIGNoYXJ0IHdpbGwgYmUgcmVkcmF3biBpZiB0aGUgYnJvd3NlciB3aW5kb3cgaXMgcmVzaXplZC5cbiAgICogRGVmYXVsdHMgdG8gYGZhbHNlYCBhbmQgc2hvdWxkIG9ubHkgYmUgdXNlZCB3aGVuIHNwZWNpZnlpbmcgdGhlIHdpZHRoIG9yIGhlaWdodCBvZiB0aGUgY2hhcnRcbiAgICogaW4gcGVyY2VudC5cbiAgICpcbiAgICogTm90ZSB0aGF0IHRoaXMgY2FuIGltcGFjdCBwZXJmb3JtYW5jZS5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBkeW5hbWljUmVzaXplID0gZmFsc2U7XG5cbiAgQE91dHB1dCgpXG4gIHB1YmxpYyByZWFkeSA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhcnRSZWFkeUV2ZW50PigpO1xuXG4gIEBPdXRwdXQoKVxuICBwdWJsaWMgZXJyb3IgPSBuZXcgRXZlbnRFbWl0dGVyPENoYXJ0RXJyb3JFdmVudD4oKTtcblxuICBAT3V0cHV0KClcbiAgcHVibGljIHNlbGVjdCA9IG5ldyBFdmVudEVtaXR0ZXI8Q2hhcnRTZWxlY3Rpb25DaGFuZ2VkRXZlbnQ+KCk7XG5cbiAgQE91dHB1dCgpXG4gIHB1YmxpYyBtb3VzZW92ZXIgPSBuZXcgRXZlbnRFbWl0dGVyPENoYXJ0TW91c2VPdmVyRXZlbnQ+KCk7XG5cbiAgQE91dHB1dCgpXG4gIHB1YmxpYyBtb3VzZWxlYXZlID0gbmV3IEV2ZW50RW1pdHRlcjxDaGFydE1vdXNlTGVhdmVFdmVudD4oKTtcblxuICBwcml2YXRlIHJlc2l6ZVN1YnNjcmlwdGlvbj86IFN1YnNjcmlwdGlvbjtcblxuICBwcml2YXRlIGRhdGFUYWJsZTogZ29vZ2xlLnZpc3VhbGl6YXRpb24uRGF0YVRhYmxlIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHdyYXBwZXI6IGdvb2dsZS52aXN1YWxpemF0aW9uLkNoYXJ0V3JhcHBlciB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSB3cmFwcGVyUmVhZHlTdWJqZWN0ID0gbmV3IFJlcGxheVN1YmplY3Q8Z29vZ2xlLnZpc3VhbGl6YXRpb24uQ2hhcnRXcmFwcGVyPigxKTtcbiAgcHJpdmF0ZSBpbml0aWFsaXplZCA9IGZhbHNlO1xuICBwcml2YXRlIGV2ZW50TGlzdGVuZXJzID0gbmV3IE1hcDxhbnksIHsgZXZlbnROYW1lOiBzdHJpbmc7IGNhbGxiYWNrOiBGdW5jdGlvbjsgaGFuZGxlOiBhbnkgfT4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVsZW1lbnQ6IEVsZW1lbnRSZWYsXG4gICAgcHJpdmF0ZSBzY3JpcHRMb2FkZXJTZXJ2aWNlOiBTY3JpcHRMb2FkZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgZGF0YVRhYmxlU2VydmljZTogRGF0YVRhYmxlU2VydmljZSxcbiAgICBAT3B0aW9uYWwoKSBwcml2YXRlIGRhc2hib2FyZD86IERhc2hib2FyZENvbXBvbmVudFxuICApIHt9XG5cbiAgcHVibGljIGdldCBjaGFydCgpOiBnb29nbGUudmlzdWFsaXphdGlvbi5DaGFydEJhc2UgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5jaGFydFdyYXBwZXIuZ2V0Q2hhcnQoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgd3JhcHBlclJlYWR5JCgpOiBPYnNlcnZhYmxlPGdvb2dsZS52aXN1YWxpemF0aW9uLkNoYXJ0V3JhcHBlcj4ge1xuICAgIHJldHVybiB0aGlzLndyYXBwZXJSZWFkeVN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGNoYXJ0V3JhcHBlcigpOiBnb29nbGUudmlzdWFsaXphdGlvbi5DaGFydFdyYXBwZXIge1xuICAgIGlmICghdGhpcy53cmFwcGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RyeWluZyB0byBhY2Nlc3MgdGhlIGNoYXJ0IHdyYXBwZXIgYmVmb3JlIGl0IHdhcyBmdWxseSBpbml0aWFsaXplZCcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLndyYXBwZXI7XG4gIH1cblxuICBwdWJsaWMgc2V0IGNoYXJ0V3JhcHBlcih3cmFwcGVyOiBnb29nbGUudmlzdWFsaXphdGlvbi5DaGFydFdyYXBwZXIpIHtcbiAgICB0aGlzLndyYXBwZXIgPSB3cmFwcGVyO1xuICAgIHRoaXMuZHJhd0NoYXJ0KCk7XG4gIH1cblxuICBwdWJsaWMgbmdPbkluaXQoKSB7XG4gICAgLy8gV2UgZG9uJ3QgbmVlZCB0byBsb2FkIGFueSBjaGFydCBwYWNrYWdlcywgdGhlIGNoYXJ0IHdyYXBwZXIgd2lsbCBoYW5kbGUgdGhpcyBmb3IgdXNcbiAgICB0aGlzLnNjcmlwdExvYWRlclNlcnZpY2UubG9hZENoYXJ0UGFja2FnZXMoZ2V0UGFja2FnZUZvckNoYXJ0KHRoaXMudHlwZSkpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICB0aGlzLmRhdGFUYWJsZSA9IHRoaXMuZGF0YVRhYmxlU2VydmljZS5jcmVhdGUodGhpcy5kYXRhLCB0aGlzLmNvbHVtbnMsIHRoaXMuZm9ybWF0dGVycyk7XG5cbiAgICAgIC8vIE9ubHkgZXZlciBjcmVhdGUgdGhlIHdyYXBwZXIgb25jZSB0byBhbGxvdyBhbmltYXRpb25zIHRvIGhhcHBlbiB3aGVuIHNvbWV0aGluZyBjaGFuZ2VzLlxuICAgICAgdGhpcy53cmFwcGVyID0gbmV3IGdvb2dsZS52aXN1YWxpemF0aW9uLkNoYXJ0V3JhcHBlcih7XG4gICAgICAgIGNvbnRhaW5lcjogdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgIGNoYXJ0VHlwZTogdGhpcy50eXBlLFxuICAgICAgICBkYXRhVGFibGU6IHRoaXMuZGF0YVRhYmxlLFxuICAgICAgICBvcHRpb25zOiB0aGlzLm1lcmdlT3B0aW9ucygpXG4gICAgICB9KTtcblxuICAgICAgdGhpcy5yZWdpc3RlckNoYXJ0RXZlbnRzKCk7XG5cbiAgICAgIHRoaXMud3JhcHBlclJlYWR5U3ViamVjdC5uZXh0KHRoaXMud3JhcHBlcik7XG4gICAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTtcblxuICAgICAgdGhpcy5kcmF3Q2hhcnQoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKGNoYW5nZXMuZHluYW1pY1Jlc2l6ZSkge1xuICAgICAgdGhpcy51cGRhdGVSZXNpemVMaXN0ZW5lcigpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmluaXRpYWxpemVkKSB7XG4gICAgICBsZXQgc2hvdWxkUmVkcmF3ID0gZmFsc2U7XG4gICAgICBpZiAoY2hhbmdlcy5kYXRhIHx8IGNoYW5nZXMuY29sdW1ucyB8fCBjaGFuZ2VzLmZvcm1hdHRlcnMpIHtcbiAgICAgICAgdGhpcy5kYXRhVGFibGUgPSB0aGlzLmRhdGFUYWJsZVNlcnZpY2UuY3JlYXRlKHRoaXMuZGF0YSwgdGhpcy5jb2x1bW5zLCB0aGlzLmZvcm1hdHRlcnMpO1xuICAgICAgICB0aGlzLndyYXBwZXIhLnNldERhdGFUYWJsZSh0aGlzLmRhdGFUYWJsZSEpO1xuICAgICAgICBzaG91bGRSZWRyYXcgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2hhbmdlcy50eXBlKSB7XG4gICAgICAgIHRoaXMud3JhcHBlciEuc2V0Q2hhcnRUeXBlKHRoaXMudHlwZSk7XG4gICAgICAgIHNob3VsZFJlZHJhdyA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChjaGFuZ2VzLm9wdGlvbnMgfHwgY2hhbmdlcy53aWR0aCB8fCBjaGFuZ2VzLmhlaWdodCB8fCBjaGFuZ2VzLnRpdGxlKSB7XG4gICAgICAgIHRoaXMud3JhcHBlciEuc2V0T3B0aW9ucyh0aGlzLm1lcmdlT3B0aW9ucygpKTtcbiAgICAgICAgc2hvdWxkUmVkcmF3ID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNob3VsZFJlZHJhdykge1xuICAgICAgICB0aGlzLmRyYXdDaGFydCgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnVuc3Vic2NyaWJlVG9SZXNpemVJZlN1YnNjcmliZWQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3IgbGlzdGVuaW5nIHRvIGV2ZW50cyBvdGhlciB0aGFuIHRoZSBtb3N0IGNvbW1vbiBvbmVzIChhdmFpbGFibGUgdmlhIE91dHB1dCBwcm9wZXJ0aWVzKS5cbiAgICpcbiAgICogQ2FuIGJlIGNhbGxlZCBhZnRlciB0aGUgY2hhcnQgZW1pdHMgdGhhdCBpdCdzIFwicmVhZHlcIi5cbiAgICpcbiAgICogUmV0dXJucyBhIGhhbmRsZSB0aGF0IGNhbiBiZSB1c2VkIGZvciBgcmVtb3ZlRXZlbnRMaXN0ZW5lcmAuXG4gICAqL1xuICBwdWJsaWMgYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWU6IHN0cmluZywgY2FsbGJhY2s6IEZ1bmN0aW9uKTogYW55IHtcbiAgICBjb25zdCBoYW5kbGUgPSB0aGlzLnJlZ2lzdGVyQ2hhcnRFdmVudCh0aGlzLmNoYXJ0LCBldmVudE5hbWUsIGNhbGxiYWNrKTtcbiAgICB0aGlzLmV2ZW50TGlzdGVuZXJzLnNldChoYW5kbGUsIHsgZXZlbnROYW1lLCBjYWxsYmFjaywgaGFuZGxlIH0pO1xuICAgIHJldHVybiBoYW5kbGU7XG4gIH1cblxuICBwdWJsaWMgcmVtb3ZlRXZlbnRMaXN0ZW5lcihoYW5kbGU6IGFueSk6IHZvaWQge1xuICAgIGNvbnN0IGVudHJ5ID0gdGhpcy5ldmVudExpc3RlbmVycy5nZXQoaGFuZGxlKTtcbiAgICBpZiAoZW50cnkpIHtcbiAgICAgIGdvb2dsZS52aXN1YWxpemF0aW9uLmV2ZW50cy5yZW1vdmVMaXN0ZW5lcihlbnRyeS5oYW5kbGUpO1xuICAgICAgdGhpcy5ldmVudExpc3RlbmVycy5kZWxldGUoaGFuZGxlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVJlc2l6ZUxpc3RlbmVyKCkge1xuICAgIHRoaXMudW5zdWJzY3JpYmVUb1Jlc2l6ZUlmU3Vic2NyaWJlZCgpO1xuXG4gICAgaWYgKHRoaXMuZHluYW1pY1Jlc2l6ZSkge1xuICAgICAgdGhpcy5yZXNpemVTdWJzY3JpcHRpb24gPSBmcm9tRXZlbnQod2luZG93LCAncmVzaXplJywgeyBwYXNzaXZlOiB0cnVlIH0pXG4gICAgICAgIC5waXBlKGRlYm91bmNlVGltZSgxMDApKVxuICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5pbml0aWFsaXplZCkge1xuICAgICAgICAgICAgdGhpcy5kcmF3Q2hhcnQoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdW5zdWJzY3JpYmVUb1Jlc2l6ZUlmU3Vic2NyaWJlZCgpIHtcbiAgICBpZiAodGhpcy5yZXNpemVTdWJzY3JpcHRpb24gIT0gbnVsbCkge1xuICAgICAgdGhpcy5yZXNpemVTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgIHRoaXMucmVzaXplU3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbWVyZ2VPcHRpb25zKCk6IG9iamVjdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRpdGxlOiB0aGlzLnRpdGxlLFxuICAgICAgd2lkdGg6IHRoaXMud2lkdGgsXG4gICAgICBoZWlnaHQ6IHRoaXMuaGVpZ2h0LFxuICAgICAgLi4udGhpcy5vcHRpb25zXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcmVnaXN0ZXJDaGFydEV2ZW50cygpIHtcbiAgICBnb29nbGUudmlzdWFsaXphdGlvbi5ldmVudHMucmVtb3ZlQWxsTGlzdGVuZXJzKHRoaXMud3JhcHBlcik7XG5cbiAgICB0aGlzLnJlZ2lzdGVyQ2hhcnRFdmVudCh0aGlzLndyYXBwZXIsICdyZWFkeScsICgpID0+IHtcbiAgICAgIC8vIFRoaXMgY291bGQgYWxzbyBiZSBkb25lIGJ5IGNoZWNraW5nIGlmIHdlIGFscmVhZHkgc3Vic2NyaWJlZCB0byB0aGUgZXZlbnRzXG4gICAgICBnb29nbGUudmlzdWFsaXphdGlvbi5ldmVudHMucmVtb3ZlQWxsTGlzdGVuZXJzKHRoaXMuY2hhcnQpO1xuICAgICAgdGhpcy5yZWdpc3RlckNoYXJ0RXZlbnQodGhpcy5jaGFydCwgJ29ubW91c2VvdmVyJywgKGV2ZW50OiBDaGFydE1vdXNlT3ZlckV2ZW50KSA9PiB0aGlzLm1vdXNlb3Zlci5lbWl0KGV2ZW50KSk7XG4gICAgICB0aGlzLnJlZ2lzdGVyQ2hhcnRFdmVudCh0aGlzLmNoYXJ0LCAnb25tb3VzZW91dCcsIChldmVudDogQ2hhcnRNb3VzZUxlYXZlRXZlbnQpID0+IHRoaXMubW91c2VsZWF2ZS5lbWl0KGV2ZW50KSk7XG4gICAgICB0aGlzLnJlZ2lzdGVyQ2hhcnRFdmVudCh0aGlzLmNoYXJ0LCAnc2VsZWN0JywgKCkgPT4ge1xuICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB0aGlzLmNoYXJ0IS5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgdGhpcy5zZWxlY3QuZW1pdCh7IHNlbGVjdGlvbiB9KTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5ldmVudExpc3RlbmVycy5mb3JFYWNoKHggPT4gKHguaGFuZGxlID0gdGhpcy5yZWdpc3RlckNoYXJ0RXZlbnQodGhpcy5jaGFydCwgeC5ldmVudE5hbWUsIHguY2FsbGJhY2spKSk7XG5cbiAgICAgIHRoaXMucmVhZHkuZW1pdCh7IGNoYXJ0OiB0aGlzLmNoYXJ0ISB9KTtcbiAgICB9KTtcblxuICAgIHRoaXMucmVnaXN0ZXJDaGFydEV2ZW50KHRoaXMud3JhcHBlciwgJ2Vycm9yJywgKGVycm9yOiBDaGFydEVycm9yRXZlbnQpID0+IHRoaXMuZXJyb3IuZW1pdChlcnJvcikpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWdpc3RlckNoYXJ0RXZlbnQob2JqZWN0OiBhbnksIGV2ZW50TmFtZTogc3RyaW5nLCBjYWxsYmFjazogRnVuY3Rpb24pOiBhbnkge1xuICAgIHJldHVybiBnb29nbGUudmlzdWFsaXphdGlvbi5ldmVudHMuYWRkTGlzdGVuZXIob2JqZWN0LCBldmVudE5hbWUsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIHByaXZhdGUgZHJhd0NoYXJ0KCkge1xuICAgIGlmICh0aGlzLmRhc2hib2FyZCAhPSBudWxsKSB7XG4gICAgICAvLyBJZiB0aGlzIGNoYXJ0IGlzIHBhcnQgb2YgYSBkYXNoYm9hcmQsIHRoZSBkYXNoYm9hcmQgdGFrZXMgY2FyZSBvZiBkcmF3aW5nXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy53cmFwcGVyIS5kcmF3KCk7XG4gIH1cbn1cbiJdfQ==