UNPKG

@clr/angular

Version:

Angular components for Clarity

420 lines (410 loc) 49.7 kB
/* * Copyright (c) 2016-2025 Broadcom. All Rights Reserved. * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. * This software is released under MIT license. * The full license information can be found in LICENSE in the root directory of this project. */ import { ChangeDetectionStrategy, Component, ContentChild, ElementRef, EventEmitter, Input, Output, ViewChild, } from '@angular/core'; import { HostWrapper } from '../../utils/host-wrapping/host-wrapper'; import { ClrPopoverHostDirective } from '../../utils/popover/popover-host.directive'; import { DatagridPropertyComparator } from './built-in/comparators/datagrid-property-comparator'; import { DatagridNumericFilterImpl } from './built-in/filters/datagrid-numeric-filter-impl'; import { DatagridPropertyNumericFilter } from './built-in/filters/datagrid-property-numeric-filter'; import { DatagridPropertyStringFilter } from './built-in/filters/datagrid-property-string-filter'; import { DatagridStringFilterImpl } from './built-in/filters/datagrid-string-filter-impl'; import { ClrDatagridSortOrder } from './enums/sort-order.enum'; import { CustomFilter } from './providers/custom-filter'; import { HIDDEN_COLUMN_CLASS } from './render/constants'; import { DatagridFilterRegistrar } from './utils/datagrid-filter-registrar'; import { WrappedColumn } from './wrapped-column'; import * as i0 from "@angular/core"; import * as i1 from "./providers/sort"; import * as i2 from "./providers/filters"; import * as i3 from "./providers/detail.service"; import * as i4 from "../../utils"; import * as i5 from "../../utils/popover/popover-host.directive"; import * as i6 from "@angular/common"; import * as i7 from "../../icon/icon"; import * as i8 from "./datagrid-column-separator"; import * as i9 from "./built-in/filters/datagrid-numeric-filter"; import * as i10 from "./built-in/filters/datagrid-string-filter"; export class ClrDatagridColumn extends DatagridFilterRegistrar { constructor(el, _sort, filters, vcr, detailService, changeDetectorRef, commonStrings) { super(filters); this.el = el; this._sort = _sort; this.vcr = vcr; this.detailService = detailService; this.changeDetectorRef = changeDetectorRef; this.commonStrings = commonStrings; this.sortOrderChange = new EventEmitter(); this.filterValueChange = new EventEmitter(); /** * A custom filter for this column that can be provided in the projected content */ this.customFilter = false; /* * What type is this column? This defaults to STRING, but can also be * set to NUMBER. Unsupported types default to STRING. Users can set it * via the [clrDgColType] input by setting it to 'string' or 'number'. */ this._colType = 'string'; /** * Indicates how the column is currently sorted */ this._sortOrder = ClrDatagridSortOrder.UNSORTED; /** * Subscription to the sort service changes */ this.subscriptions = []; this._showSeparator = true; this.subscriptions.push(this.listenForSortingChanges()); this.subscriptions.push(this.listenForDetailPaneChanges()); } get isHidden() { return this.el.nativeElement.classList.contains(HIDDEN_COLUMN_CLASS); } get showSeparator() { return this._showSeparator; } set showSeparator(value) { this._showSeparator = value; this.changeDetectorRef.markForCheck(); } // TODO: We might want to make this an enum in the future get colType() { return this._colType; } set colType(value) { this._colType = value; } get field() { return this._field; } set field(field) { if (typeof field === 'string') { this._field = field; if (!this._sortBy) { this._sortBy = new DatagridPropertyComparator(field); } } } get sortBy() { return this._sortBy; } set sortBy(comparator) { if (typeof comparator === 'string') { this._sortBy = new DatagridPropertyComparator(comparator); } else if (comparator) { this._sortBy = comparator; } else if (this.field) { this._sortBy = new DatagridPropertyComparator(this.field); } else { delete this._sortBy; } } get sortOrder() { return this._sortOrder; } set sortOrder(value) { if (typeof value === 'undefined') { return; } // only if the incoming order is different from the current one if (this._sortOrder === value) { return; } switch (value) { case ClrDatagridSortOrder.ASC: this.sort(false); break; case ClrDatagridSortOrder.DESC: this.sort(true); break; // the Unsorted case happens when the current state is neither Asc or Desc case ClrDatagridSortOrder.UNSORTED: default: this._sort.clear(); break; } } set updateFilterValue(newValue) { if (this.filter) { if (this.filter instanceof DatagridStringFilterImpl) { if (!newValue || typeof newValue !== 'string') { newValue = ''; } if (newValue !== this.filter.value) { this.filter.value = newValue; } } else if (this.filter instanceof DatagridNumericFilterImpl) { if (!newValue || !(newValue instanceof Array)) { newValue = [null, null]; } if (newValue.length === 2 && (newValue[0] !== this.filter.value[0] || newValue[1] !== this.filter.value[1])) { this.filter.value = newValue; } } } else { this.initFilterValue = newValue; } } set projectedFilter(custom) { if (custom) { this.deleteFilter(); this.customFilter = true; } } /** * Indicates if the column is sortable */ get sortable() { return !!this._sortBy; } get ariaSort() { switch (this._sortOrder) { case ClrDatagridSortOrder.ASC: return 'ascending'; case ClrDatagridSortOrder.DESC: return 'descending'; case ClrDatagridSortOrder.UNSORTED: default: return 'none'; } } get sortDirection() { return this._sortDirection; } /** * @NOTE type `any` here is to let us pass templateStrictMode, because in our code we try to handle * two types of filters String and Number with the same variable but both of them work with different * format we got an error for casting. We could not cast anything inside the template so to not mess the * casting, the last type is set to `any` * * Orignial types: string | [number, number] */ get filterValue() { if (this.filter instanceof DatagridStringFilterImpl || this.filter instanceof DatagridNumericFilterImpl) { return this.filter.value; } return null; } set filterValue(newValue) { if (this.filter instanceof DatagridStringFilterImpl || this.filter instanceof DatagridNumericFilterImpl) { this.updateFilterValue = newValue; this.filterValueChange.emit(this.filter.value); } } get _view() { return this.wrappedInjector.get(WrappedColumn, this.vcr).columnView; } ngOnInit() { this.wrappedInjector = new HostWrapper(WrappedColumn, this.vcr); } ngAfterViewInit() { this.setFilterToggleAriaLabel(); } ngOnChanges(changes) { if (changes.colType && changes.colType.currentValue && changes.colType.currentValue !== changes.colType.previousValue) { if (!this.customFilter && !this.filter && this.colType && this.field) { this.setupDefaultFilter(this.field, this.colType); } } if (changes.field && changes.field.currentValue && changes.field.currentValue !== changes.field.previousValue) { if (!this.customFilter && this.colType) { this.setupDefaultFilter(this.field, this.colType); } } } ngOnDestroy() { super.ngOnDestroy(); this.subscriptions.forEach(s => s.unsubscribe()); } /** * Sorts the datagrid based on this column */ sort(reverse) { if (!this.sortable) { return; } this._sort.toggle(this._sortBy, reverse); // setting the private variable to not retrigger the setter logic this._sortOrder = this._sort.reverse ? ClrDatagridSortOrder.DESC : ClrDatagridSortOrder.ASC; // Sets the correct icon for current sort order this._sortDirection = this._sortOrder === ClrDatagridSortOrder.DESC ? 'down' : 'up'; this.sortOrderChange.emit(this._sortOrder); } listenForDetailPaneChanges() { return this.detailService.stateChange.subscribe(state => { if (this.showSeparator !== !state) { this.showSeparator = !state; } }); } setFilterToggleAriaLabel() { const filterToggle = this.el.nativeElement.querySelector('.datagrid-filter-toggle'); if (filterToggle) { filterToggle.ariaLabel = this.commonStrings.parse(this.commonStrings.keys.datagridFilterAriaLabel, { COLUMN: this?.titleContainer?.nativeElement.textContent.trim().toLocaleLowerCase(), }); } } listenForSortingChanges() { return this._sort.change.subscribe(sort => { // Need to manually mark the component to be checked // for both activating and deactivating sorting this.changeDetectorRef.markForCheck(); // We're only listening to make sure we emit an event when the column goes from sorted to unsorted if (this.sortOrder !== ClrDatagridSortOrder.UNSORTED && sort.comparator !== this._sortBy) { this._sortOrder = ClrDatagridSortOrder.UNSORTED; this.sortOrderChange.emit(this._sortOrder); this._sortDirection = null; } }); } setupDefaultFilter(field, colType) { if (colType === 'number') { this.setFilter(new DatagridNumericFilterImpl(new DatagridPropertyNumericFilter(field))); } else if (colType === 'string') { this.setFilter(new DatagridStringFilterImpl(new DatagridPropertyStringFilter(field))); } if (this.filter && this.initFilterValue) { this.updateFilterValue = this.initFilterValue; // This initFilterValue should be used only once after the filter registration // So deleting this property value to prevent it from being used again // if this field property is set again delete this.initFilterValue; } } } ClrDatagridColumn.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrDatagridColumn, deps: [{ token: i0.ElementRef }, { token: i1.Sort }, { token: i2.FiltersProvider }, { token: i0.ViewContainerRef }, { token: i3.DetailService }, { token: i0.ChangeDetectorRef }, { token: i4.ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component }); ClrDatagridColumn.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ClrDatagridColumn, selector: "clr-dg-column", inputs: { filterStringPlaceholder: ["clrFilterStringPlaceholder", "filterStringPlaceholder"], filterNumberMaxPlaceholder: ["clrFilterNumberMaxPlaceholder", "filterNumberMaxPlaceholder"], filterNumberMinPlaceholder: ["clrFilterNumberMinPlaceholder", "filterNumberMinPlaceholder"], colType: ["clrDgColType", "colType"], field: ["clrDgField", "field"], sortBy: ["clrDgSortBy", "sortBy"], sortOrder: ["clrDgSortOrder", "sortOrder"], updateFilterValue: ["clrFilterValue", "updateFilterValue"] }, outputs: { sortOrderChange: "clrDgSortOrderChange", filterValueChange: "clrFilterValueChange" }, host: { attributes: { "role": "columnheader" }, properties: { "class.datagrid-column": "true", "attr.aria-sort": "ariaSort" } }, queries: [{ propertyName: "projectedFilter", first: true, predicate: CustomFilter, descendants: true }], viewQueries: [{ propertyName: "titleContainer", first: true, predicate: ["titleContainer"], descendants: true, read: ElementRef }], usesInheritance: true, usesOnChanges: true, hostDirectives: [{ directive: i5.ClrPopoverHostDirective }], ngImport: i0, template: ` <div class="datagrid-column-flex"> <button class="datagrid-column-title" *ngIf="sortable" (click)="sort()" type="button" #titleContainer> <ng-container *ngTemplateOutlet="columnTitle"></ng-container> <cds-icon *ngIf="sortDirection" shape="arrow" [attr.direction]="sortDirection" aria-hidden="true" class="sort-icon" ></cds-icon> </button> <!-- I'm really not happy with that select since it's not very scalable --> <ng-content select="clr-dg-filter, clr-dg-string-filter, clr-dg-numeric-filter"></ng-content> <clr-dg-string-filter *ngIf="field && !customFilter && colType == 'string'" [clrFilterPlaceholder]="filterStringPlaceholder" [clrDgStringFilter]="registered" [(clrFilterValue)]="filterValue" ></clr-dg-string-filter> <clr-dg-numeric-filter *ngIf="field && !customFilter && colType == 'number'" [clrFilterMaxPlaceholder]="filterNumberMaxPlaceholder" [clrFilterMinPlaceholder]="filterNumberMinPlaceholder" [clrDgNumericFilter]="registered" [(clrFilterValue)]="filterValue" ></clr-dg-numeric-filter> <ng-template #columnTitle> <ng-content></ng-content> </ng-template> <span class="datagrid-column-title" *ngIf="!sortable" #titleContainer> <ng-container *ngTemplateOutlet="columnTitle"></ng-container> </span> <clr-dg-column-separator *ngIf="showSeparator"></clr-dg-column-separator> </div> `, isInline: true, dependencies: [{ kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i7.CdsIconCustomTag, selector: "cds-icon" }, { kind: "component", type: i8.ClrDatagridColumnSeparator, selector: "clr-dg-column-separator" }, { kind: "component", type: i9.DatagridNumericFilter, selector: "clr-dg-numeric-filter", inputs: ["clrFilterMinPlaceholder", "clrFilterMaxPlaceholder", "clrFilterFromLabel", "clrFilterToLabel", "clrFilterValue", "clrDgNumericFilter"], outputs: ["clrFilterValueChange"] }, { kind: "component", type: i10.DatagridStringFilter, selector: "clr-dg-string-filter", inputs: ["clrFilterPlaceholder", "clrFilterLabel", "clrDgStringFilter", "clrFilterValue"], outputs: ["clrFilterValueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrDatagridColumn, decorators: [{ type: Component, args: [{ selector: 'clr-dg-column', template: ` <div class="datagrid-column-flex"> <button class="datagrid-column-title" *ngIf="sortable" (click)="sort()" type="button" #titleContainer> <ng-container *ngTemplateOutlet="columnTitle"></ng-container> <cds-icon *ngIf="sortDirection" shape="arrow" [attr.direction]="sortDirection" aria-hidden="true" class="sort-icon" ></cds-icon> </button> <!-- I'm really not happy with that select since it's not very scalable --> <ng-content select="clr-dg-filter, clr-dg-string-filter, clr-dg-numeric-filter"></ng-content> <clr-dg-string-filter *ngIf="field && !customFilter && colType == 'string'" [clrFilterPlaceholder]="filterStringPlaceholder" [clrDgStringFilter]="registered" [(clrFilterValue)]="filterValue" ></clr-dg-string-filter> <clr-dg-numeric-filter *ngIf="field && !customFilter && colType == 'number'" [clrFilterMaxPlaceholder]="filterNumberMaxPlaceholder" [clrFilterMinPlaceholder]="filterNumberMinPlaceholder" [clrDgNumericFilter]="registered" [(clrFilterValue)]="filterValue" ></clr-dg-numeric-filter> <ng-template #columnTitle> <ng-content></ng-content> </ng-template> <span class="datagrid-column-title" *ngIf="!sortable" #titleContainer> <ng-container *ngTemplateOutlet="columnTitle"></ng-container> </span> <clr-dg-column-separator *ngIf="showSeparator"></clr-dg-column-separator> </div> `, hostDirectives: [ClrPopoverHostDirective], host: { '[class.datagrid-column]': 'true', '[attr.aria-sort]': 'ariaSort', role: 'columnheader', }, changeDetection: ChangeDetectionStrategy.OnPush, }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.Sort }, { type: i2.FiltersProvider }, { type: i0.ViewContainerRef }, { type: i3.DetailService }, { type: i0.ChangeDetectorRef }, { type: i4.ClrCommonStringsService }]; }, propDecorators: { filterStringPlaceholder: [{ type: Input, args: ['clrFilterStringPlaceholder'] }], filterNumberMaxPlaceholder: [{ type: Input, args: ['clrFilterNumberMaxPlaceholder'] }], filterNumberMinPlaceholder: [{ type: Input, args: ['clrFilterNumberMinPlaceholder'] }], sortOrderChange: [{ type: Output, args: ['clrDgSortOrderChange'] }], filterValueChange: [{ type: Output, args: ['clrFilterValueChange'] }], titleContainer: [{ type: ViewChild, args: ['titleContainer', { read: ElementRef }] }], colType: [{ type: Input, args: ['clrDgColType'] }], field: [{ type: Input, args: ['clrDgField'] }], sortBy: [{ type: Input, args: ['clrDgSortBy'] }], sortOrder: [{ type: Input, args: ['clrDgSortOrder'] }], updateFilterValue: [{ type: Input, args: ['clrFilterValue'] }], projectedFilter: [{ type: ContentChild, args: [CustomFilter] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWdyaWQtY29sdW1uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYW5ndWxhci9zcmMvZGF0YS9kYXRhZ3JpZC9kYXRhZ3JpZC1jb2x1bW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0c7QUFFSCxPQUFPLEVBQ0wsdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osVUFBVSxFQUNWLFlBQVksRUFFWixLQUFLLEVBSUwsTUFBTSxFQUVOLFNBQVMsR0FFVixNQUFNLGVBQWUsQ0FBQztBQUl2QixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDckUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFDckYsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0scURBQXFELENBQUM7QUFDakcsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0saURBQWlELENBQUM7QUFDNUYsT0FBTyxFQUFFLDZCQUE2QixFQUFFLE1BQU0scURBQXFELENBQUM7QUFDcEcsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sb0RBQW9ELENBQUM7QUFDbEcsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sZ0RBQWdELENBQUM7QUFDMUYsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHL0QsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBSXpELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3pELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQzVFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQzs7Ozs7Ozs7Ozs7O0FBcURqRCxNQUFNLE9BQU8saUJBQ1gsU0FBUSx1QkFBeUQ7SUF3RGpFLFlBQ1UsRUFBMkIsRUFDM0IsS0FBYyxF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O2lCQUNoRDttUkFLc0MsdUJBQXVCO3NCQUEzRCxLQUFLO3VCQUFDLDRCQUE0QjtnQkFDSywwQkFBMEI7c0JBQWpFLEtBQUs7dUJBQUMsK0JBQStCO2dCQUNFLDBCQUEwQjtzQkFBakUsS0FBSzt1QkFBQywrQkFBK0I7Z0JBRU4sZUFBZTtzQkFBOUMsTUFBTTt1QkFBQyxzQkFBc0I7Z0JBQ0UsaUJBQWlCO3NCQUFoRCxNQUFNO3VCQUFDLHNCQUFzQjtnQkFFcUIsY0FBYztzQkFBaEUsU0FBUzt1QkFBQyxnQkFBZ0IsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7Z0JBMEU3QyxPQUFPO3NCQURWLEtBQUs7dUJBQUMsY0FBYztnQkFTakIsS0FBSztzQkFEUixLQUFLO3VCQUFDLFlBQVk7Z0JBZWYsTUFBTTtzQkFEVCxLQUFLO3VCQUFDLGFBQWE7Z0JBaUJoQixTQUFTO3NCQURaLEtBQUs7dUJBQUMsZ0JBQWdCO2dCQThCbkIsaUJBQWlCO3NCQURwQixLQUFLO3VCQUFDLGdCQUFnQjtnQkF3Qm5CLGVBQWU7c0JBRGxCLFlBQVk7dUJBQUMsWUFBWSIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTYtMjAyNSBCcm9hZGNvbS4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIFRoZSB0ZXJtIFwiQnJvYWRjb21cIiByZWZlcnMgdG8gQnJvYWRjb20gSW5jLiBhbmQvb3IgaXRzIHN1YnNpZGlhcmllcy5cbiAqIFRoaXMgc29mdHdhcmUgaXMgcmVsZWFzZWQgdW5kZXIgTUlUIGxpY2Vuc2UuXG4gKiBUaGUgZnVsbCBsaWNlbnNlIGluZm9ybWF0aW9uIGNhbiBiZSBmb3VuZCBpbiBMSUNFTlNFIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHByb2plY3QuXG4gKi9cblxuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIENvbnRlbnRDaGlsZCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBJbmplY3RvcixcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVmlld0NoaWxkLFxuICBWaWV3Q29udGFpbmVyUmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBDbHJDb21tb25TdHJpbmdzU2VydmljZSB9IGZyb20gJy4uLy4uL3V0aWxzJztcbmltcG9ydCB7IEhvc3RXcmFwcGVyIH0gZnJvbSAnLi4vLi4vdXRpbHMvaG9zdC13cmFwcGluZy9ob3N0LXdyYXBwZXInO1xuaW1wb3J0IHsgQ2xyUG9wb3Zlckhvc3REaXJlY3RpdmUgfSBmcm9tICcuLi8uLi91dGlscy9wb3BvdmVyL3BvcG92ZXItaG9zdC5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgRGF0YWdyaWRQcm9wZXJ0eUNvbXBhcmF0b3IgfSBmcm9tICcuL2J1aWx0LWluL2NvbXBhcmF0b3JzL2RhdGFncmlkLXByb3BlcnR5LWNvbXBhcmF0b3InO1xuaW1wb3J0IHsgRGF0YWdyaWROdW1lcmljRmlsdGVySW1wbCB9IGZyb20gJy4vYnVpbHQtaW4vZmlsdGVycy9kYXRhZ3JpZC1udW1lcmljLWZpbHRlci1pbXBsJztcbmltcG9ydCB7IERhdGFncmlkUHJvcGVydHlOdW1lcmljRmlsdGVyIH0gZnJvbSAnLi9idWlsdC1pbi9maWx0ZXJzL2RhdGFncmlkLXByb3BlcnR5LW51bWVyaWMtZmlsdGVyJztcbmltcG9ydCB7IERhdGFncmlkUHJvcGVydHlTdHJpbmdGaWx0ZXIgfSBmcm9tICcuL2J1aWx0LWluL2ZpbHRlcnMvZGF0YWdyaWQtcHJvcGVydHktc3RyaW5nLWZpbHRlcic7XG5pbXBvcnQgeyBEYXRhZ3JpZFN0cmluZ0ZpbHRlckltcGwgfSBmcm9tICcuL2J1aWx0LWluL2ZpbHRlcnMvZGF0YWdyaWQtc3RyaW5nLWZpbHRlci1pbXBsJztcbmltcG9ydCB7IENsckRhdGFncmlkU29ydE9yZGVyIH0gZnJvbSAnLi9lbnVtcy9zb3J0LW9yZGVyLmVudW0nO1xuaW1wb3J0IHsgQ2xyRGF0YWdyaWRDb21wYXJhdG9ySW50ZXJmYWNlIH0gZnJvbSAnLi9pbnRlcmZhY2VzL2NvbXBhcmF0b3IuaW50ZXJmYWNlJztcbmltcG9ydCB7IENsckRhdGFncmlkRmlsdGVySW50ZXJmYWNlIH0gZnJvbSAnLi9pbnRlcmZhY2VzL2ZpbHRlci5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgQ3VzdG9tRmlsdGVyIH0gZnJvbSAnLi9wcm92aWRlcnMvY3VzdG9tLWZpbHRlcic7XG5pbXBvcnQgeyBEZXRhaWxTZXJ2aWNlIH0gZnJvbSAnLi9wcm92aWRlcnMvZGV0YWlsLnNlcnZpY2UnO1xuaW1wb3J0IHsgRmlsdGVyc1Byb3ZpZGVyIH0gZnJvbSAnLi9wcm92aWRlcnMvZmlsdGVycyc7XG5pbXBvcnQgeyBTb3J0IH0gZnJvbSAnLi9wcm92aWRlcnMvc29ydCc7XG5pbXBvcnQgeyBISURERU5fQ09MVU1OX0NMQVNTIH0gZnJvbSAnLi9yZW5kZXIvY29uc3RhbnRzJztcbmltcG9ydCB7IERhdGFncmlkRmlsdGVyUmVnaXN0cmFyIH0gZnJvbSAnLi91dGlscy9kYXRhZ3JpZC1maWx0ZXItcmVnaXN0cmFyJztcbmltcG9ydCB7IFdyYXBwZWRDb2x1bW4gfSBmcm9tICcuL3dyYXBwZWQtY29sdW1uJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnY2xyLWRnLWNvbHVtbicsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImRhdGFncmlkLWNvbHVtbi1mbGV4XCI+XG4gICAgICA8YnV0dG9uIGNsYXNzPVwiZGF0YWdyaWQtY29sdW1uLXRpdGxlXCIgKm5nSWY9XCJzb3J0YWJsZVwiIChjbGljayk9XCJzb3J0KClcIiB0eXBlPVwiYnV0dG9uXCIgI3RpdGxlQ29udGFpbmVyPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiY29sdW1uVGl0bGVcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPGNkcy1pY29uXG4gICAgICAgICAgKm5nSWY9XCJzb3J0RGlyZWN0aW9uXCJcbiAgICAgICAgICBzaGFwZT1cImFycm93XCJcbiAgICAgICAgICBbYXR0ci5kaXJlY3Rpb25dPVwic29ydERpcmVjdGlvblwiXG4gICAgICAgICAgYXJpYS1oaWRkZW49XCJ0cnVlXCJcbiAgICAgICAgICBjbGFzcz1cInNvcnQtaWNvblwiXG4gICAgICAgID48L2Nkcy1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8IS0tIEknbSByZWFsbHkgbm90IGhhcHB5IHdpdGggdGhhdCBzZWxlY3Qgc2luY2UgaXQncyBub3QgdmVyeSBzY2FsYWJsZSAtLT5cbiAgICAgIDxuZy1jb250ZW50IHNlbGVjdD1cImNsci1kZy1maWx0ZXIsIGNsci1kZy1zdHJpbmctZmlsdGVyLCBjbHItZGctbnVtZXJpYy1maWx0ZXJcIj48L25nLWNvbnRlbnQ+XG5cbiAgICAgIDxjbHItZGctc3RyaW5nLWZpbHRlclxuICAgICAgICAqbmdJZj1cImZpZWxkICYmICFjdXN0b21GaWx0ZXIgJiYgY29sVHlwZSA9PSAnc3RyaW5nJ1wiXG4gICAgICAgIFtjbHJGaWx0ZXJQbGFjZWhvbGRlcl09XCJmaWx0ZXJTdHJpbmdQbGFjZWhvbGRlclwiXG4gICAgICAgIFtjbHJEZ1N0cmluZ0ZpbHRlcl09XCJyZWdpc3RlcmVkXCJcbiAgICAgICAgWyhjbHJGaWx0ZXJWYWx1ZSldPVwiZmlsdGVyVmFsdWVcIlxuICAgICAgPjwvY2xyLWRnLXN0cmluZy1maWx0ZXI+XG5cbiAgICAgIDxjbHItZGctbnVtZXJpYy1maWx0ZXJcbiAgICAgICAgKm5nSWY9XCJmaWVsZCAmJiAhY3VzdG9tRmlsdGVyICYmIGNvbFR5cGUgPT0gJ251bWJlcidcIlxuICAgICAgICBbY2xyRmlsdGVyTWF4UGxhY2Vob2xkZXJdPVwiZmlsdGVyTnVtYmVyTWF4UGxhY2Vob2xkZXJcIlxuICAgICAgICBbY2xyRmlsdGVyTWluUGxhY2Vob2xkZXJdPVwiZmlsdGVyTnVtYmVyTWluUGxhY2Vob2xkZXJcIlxuICAgICAgICBbY2xyRGdOdW1lcmljRmlsdGVyXT1cInJlZ2lzdGVyZWRcIlxuICAgICAgICBbKGNsckZpbHRlclZhbHVlKV09XCJmaWx0ZXJWYWx1ZVwiXG4gICAgICA+PC9jbHItZGctbnVtZXJpYy1maWx0ZXI+XG5cbiAgICAgIDxuZy10ZW1wbGF0ZSAjY29sdW1uVGl0bGU+XG4gICAgICAgIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbiAgICAgIDwvbmctdGVtcGxhdGU+XG5cbiAgICAgIDxzcGFuIGNsYXNzPVwiZGF0YWdyaWQtY29sdW1uLXRpdGxlXCIgKm5nSWY9XCIhc29ydGFibGVcIiAjdGl0bGVDb250YWluZXI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJjb2x1bW5UaXRsZVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgPC9zcGFuPlxuXG4gICAgICA8Y2xyLWRnLWNvbHVtbi1zZXBhcmF0b3IgKm5nSWY9XCJzaG93U2VwYXJhdG9yXCI+PC9jbHItZGctY29sdW1uLXNlcGFyYXRvcj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgaG9zdERpcmVjdGl2ZXM6IFtDbHJQb3BvdmVySG9zdERpcmVjdGl2ZV0sXG4gIGhvc3Q6IHtcbiAgICAnW2NsYXNzLmRhdGFncmlkLWNvbHVtbl0nOiAndHJ1ZScsXG4gICAgJ1thdHRyLmFyaWEtc29ydF0nOiAnYXJpYVNvcnQnLFxuICAgIHJvbGU6ICdjb2x1bW5oZWFkZXInLFxuICB9LFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgQ2xyRGF0YWdyaWRDb2x1bW48VCA9IGFueT5cbiAgZXh0ZW5kcyBEYXRhZ3JpZEZpbHRlclJlZ2lzdHJhcjxULCBDbHJEYXRhZ3JpZEZpbHRlckludGVyZmFjZTxUPj5cbiAgaW1wbGVtZW50cyBPbkRlc3Ryb3ksIE9uSW5pdCwgT25DaGFuZ2VzXG57XG4gIEBJbnB1dCgnY2xyRmlsdGVyU3RyaW5nUGxhY2Vob2xkZXInKSBmaWx0ZXJTdHJpbmdQbGFjZWhvbGRlcjogc3RyaW5nO1xuICBASW5wdXQoJ2NsckZpbHRlck51bWJlck1heFBsYWNlaG9sZGVyJykgZmlsdGVyTnVtYmVyTWF4UGxhY2Vob2xkZXI6IHN0cmluZztcbiAgQElucHV0KCdjbHJGaWx0ZXJOdW1iZXJNaW5QbGFjZWhvbGRlcicpIGZpbHRlck51bWJlck1pblBsYWNlaG9sZGVyOiBzdHJpbmc7XG5cbiAgQE91dHB1dCgnY2xyRGdTb3J0T3JkZXJDaGFuZ2UnKSBzb3J0T3JkZXJDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPENsckRhdGFncmlkU29ydE9yZGVyPigpO1xuICBAT3V0cHV0KCdjbHJGaWx0ZXJWYWx1ZUNoYW5nZScpIGZpbHRlclZhbHVlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBWaWV3Q2hpbGQoJ3RpdGxlQ29udGFpbmVyJywgeyByZWFkOiBFbGVtZW50UmVmIH0pIHRpdGxlQ29udGFpbmVyOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcblxuICAvKipcbiAgICogQSBjdXN0b20gZmlsdGVyIGZvciB0aGlzIGNvbHVtbiB0aGF0IGNhbiBiZSBwcm92aWRlZCBpbiB0aGUgcHJvamVjdGVkIGNvbnRlbnRcbiAgICovXG4gIGN1c3RvbUZpbHRlciA9IGZhbHNlO1xuXG4gIC8qXG4gICAqIFdoYXQgdHlwZSBpcyB0aGlzIGNvbHVtbj8gIFRoaXMgZGVmYXVsdHMgdG8gU1RSSU5HLCBidXQgY2FuIGFsc28gYmVcbiAgICogc2V0IHRvIE5VTUJFUi4gIFVuc3VwcG9ydGVkIHR5cGVzIGRlZmF1bHQgdG8gU1RSSU5HLiBVc2VycyBjYW4gc2V0IGl0XG4gICAqIHZpYSB0aGUgW2NsckRnQ29sVHlwZV0gaW5wdXQgYnkgc2V0dGluZyBpdCB0byAnc3RyaW5nJyBvciAnbnVtYmVyJy5cbiAgICovXG4gIHByaXZhdGUgX2NvbFR5cGU6ICdzdHJpbmcnIHwgJ251bWJlcicgPSAnc3RyaW5nJztcblxuICAvKlxuICAgKiBTaW1wbGUgb2JqZWN0IHByb3BlcnR5IHNob3J0Y3V0LCBhY3RpdmF0ZXMgYm90aCBzb3J0aW5nIGFuZCBmaWx0ZXJpbmdcbiAgICogYmFzZWQgb24gbmF0aXZlIGNvbXBhcmlzb24gb2YgdGhlIHNwZWNpZmllZCBwcm9wZXJ0eSBvbiB0aGUgaXRlbXMuXG4gICAqL1xuICBwcml2YXRlIF9maWVsZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDbHJEYXRhZ3JpZENvbXBhcmF0b3JJbnRlcmZhY2UgdG8gdXNlIHdoZW4gc29ydGluZyB0aGUgY29sdW1uXG4gICAqL1xuICBwcml2YXRlIF9zb3J0Qnk6IENsckRhdGFncmlkQ29tcGFyYXRvckludGVyZmFjZTxUPjtcblxuICAvKipcbiAgICogSW5kaWNhdGVzIGhvdyB0aGUgY29sdW1uIGlzIGN1cnJlbnRseSBzb3J0ZWRcbiAgICovXG4gIHByaXZhdGUgX3NvcnRPcmRlcjogQ2xyRGF0YWdyaWRTb3J0T3JkZXIgPSBDbHJEYXRhZ3JpZFNvcnRPcmRlci5VTlNPUlRFRDtcblxuICBwcml2YXRlIF9zb3J0RGlyZWN0aW9uOiAndXAnIHwgJ2Rvd24nIHwgbnVsbDtcblxuICAvLyBUaGlzIHByb3BlcnR5IGhvbGRzIGZpbHRlciB2YWx1ZSB0ZW1wb3JhcmlseSB3aGlsZSB0aGlzLmZpbHRlciBwcm9wZXJ0eSBpcyBub3QgeWV0IHJlZ2lzdGVyZWRcbiAgLy8gV2hlbiB0aGlzLmZpbHRlciBpcyByZWdpc3RlcmVkLCB0aGlzIHByb3BlcnR5IHZhbHVlIHdvdWxkIGJlIHVzZWQgdXBkYXRlIHRoaXMuZmlsdGVyLnZhbHVlXG4gIC8vXG4gIHByaXZhdGUgaW5pdEZpbHRlclZhbHVlOiBzdHJpbmcgfCBbbnVtYmVyLCBudW1iZXJdO1xuXG4gIHByaXZhdGUgd3JhcHBlZEluamVjdG9yOiBJbmplY3RvcjtcblxuICAvKipcbiAgICogU3Vic2NyaXB0aW9uIHRvIHRoZSBzb3J0IHNlcnZpY2UgY2hhbmdlc1xuICAgKi9cbiAgcHJpdmF0ZSBzdWJzY3JpcHRpb25zOiBTdWJzY3JpcHRpb25bXSA9IFtdO1xuXG4gIHByaXZhdGUgX3Nob3dTZXBhcmF0b3IgPSB0cnVlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZWw6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+LFxuICAgIHByaXZhdGUgX3NvcnQ6IFNvcnQ8VD4sXG4gICAgZmlsdGVyczogRmlsdGVyc1Byb3ZpZGVyPFQ+LFxuICAgIHByaXZhdGUgdmNyOiBWaWV3Q29udGFpbmVyUmVmLFxuICAgIHByaXZhdGUgZGV0YWlsU2VydmljZTogRGV0YWlsU2VydmljZSxcbiAgICBwcml2YXRlIGNoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcml2YXRlIGNvbW1vblN0cmluZ3M6IENsckNvbW1vblN0cmluZ3NTZXJ2aWNlXG4gICkge1xuICAgIHN1cGVyKGZpbHRlcnMpO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKHRoaXMubGlzdGVuRm9yU29ydGluZ0NoYW5nZXMoKSk7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2godGhpcy5saXN0ZW5Gb3JEZXRhaWxQYW5lQ2hhbmdlcygpKTtcbiAgfVxuXG4gIGdldCBpc0hpZGRlbigpIHtcbiAgICByZXR1cm4gdGhpcy5lbC5uYXRpdmVFbGVtZW50LmNsYXNzTGlzdC5jb250YWlucyhISURERU5fQ09MVU1OX0NMQVNTKTtcbiAgfVxuXG4gIGdldCBzaG93U2VwYXJhdG9yKCkge1xuICAgIHJldHVybiB0aGlzLl9zaG93U2VwYXJhdG9yO1xuICB9XG4gIHNldCBzaG93U2VwYXJhdG9yKHZhbHVlOiBib29sZWFuKSB7XG4gICAgdGhpcy5fc2hvd1NlcGFyYXRvciA9IHZhbHVlO1xuICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvLyBUT0RPOiBXZSBtaWdodCB3YW50IHRvIG1ha2UgdGhpcyBhbiBlbnVtIGluIHRoZSBmdXR1cmVcbiAgQElucHV0KCdjbHJEZ0NvbFR5cGUnKVxuICBnZXQgY29sVHlwZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fY29sVHlwZTtcbiAgfVxuICBzZXQgY29sVHlwZSh2YWx1ZTogJ3N0cmluZycgfCAnbnVtYmVyJykge1xuICAgIHRoaXMuX2NvbFR5cGUgPSB2YWx1ZTtcbiAgfVxuXG4gIEBJbnB1dCgnY2xyRGdGaWVsZCcpXG4gIGdldCBmaWVsZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZmllbGQ7XG4gIH1cbiAgc2V0IGZpZWxkKGZpZWxkOiBzdHJpbmcpIHtcbiAgICBpZiAodHlwZW9mIGZpZWxkID09PSAnc3RyaW5nJykge1xuICAgICAgdGhpcy5fZmllbGQgPSBmaWVsZDtcblxuICAgICAgaWYgKCF0aGlzLl9zb3J0QnkpIHtcbiAgICAgICAgdGhpcy5fc29ydEJ5ID0gbmV3IERhdGFncmlkUHJvcGVydHlDb21wYXJhdG9yKGZpZWxkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBASW5wdXQoJ2NsckRnU29ydEJ5JylcbiAgZ2V0IHNvcnRCeSgpIHtcbiAgICByZXR1cm4gdGhpcy5fc29ydEJ5O1xuICB9XG4gIHNldCBzb3J0QnkoY29tcGFyYXRvcjogQ2xyRGF0YWdyaWRDb21wYXJhdG9ySW50ZXJmYWNlPFQ+IHwgc3RyaW5nKSB7XG4gICAgaWYgKHR5cGVvZiBjb21wYXJhdG9yID09PSAnc3RyaW5nJykge1xuICAgICAgdGhpcy5fc29ydEJ5ID0gbmV3IERhdGFncmlkUHJvcGVydHlDb21wYXJhdG9yKGNvbXBhcmF0b3IpO1xuICAgIH0gZWxzZSBpZiAoY29tcGFyYXRvcikge1xuICAgICAgdGhpcy5fc29ydEJ5ID0gY29tcGFyYXRvcjtcbiAgICB9IGVsc2UgaWYgKHRoaXMuZmllbGQpIHtcbiAgICAgIHRoaXMuX3NvcnRCeSA9IG5ldyBEYXRhZ3JpZFByb3BlcnR5Q29tcGFyYXRvcih0aGlzLmZpZWxkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVsZXRlIHRoaXMuX3NvcnRCeTtcbiAgICB9XG4gIH1cblxuICBASW5wdXQoJ2NsckRnU29ydE9yZGVyJylcbiAgZ2V0IHNvcnRPcmRlcigpIHtcbiAgICByZXR1cm4gdGhpcy5fc29ydE9yZGVyO1xuICB9XG4gIHNldCBzb3J0T3JkZXIodmFsdWU6IENsckRhdGFncmlkU29ydE9yZGVyKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBvbmx5IGlmIHRoZSBpbmNvbWluZyBvcmRlciBpcyBkaWZmZXJlbnQgZnJvbSB0aGUgY3VycmVudCBvbmVcbiAgICBpZiAodGhpcy5fc29ydE9yZGVyID09PSB2YWx1ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHN3aXRjaCAodmFsdWUpIHtcbiAgICAgIGNhc2UgQ2xyRGF0YWdyaWRTb3J0T3JkZXIuQVNDOlxuICAgICAgICB0aGlzLnNvcnQoZmFsc2UpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgQ2xyRGF0YWdyaWRTb3J0T3JkZXIuREVTQzpcbiAgICAgICAgdGhpcy5zb3J0KHRydWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIC8vIHRoZSBVbnNvcnRlZCBjYXNlIGhhcHBlbnMgd2hlbiB0aGUgY3VycmVudCBzdGF0ZSBpcyBuZWl0aGVyIEFzYyBvciBEZXNjXG4gICAgICBjYXNlIENsckRhdGFncmlkU29ydE9yZGVyLlVOU09SVEVEOlxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhpcy5fc29ydC5jbGVhcigpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBASW5wdXQoJ2NsckZpbHRlclZhbHVlJylcbiAgc2V0IHVwZGF0ZUZpbHRlclZhbHVlKG5ld1ZhbHVlOiBzdHJpbmcgfCBbbnVtYmVyLCBudW1iZXJdKSB7XG4gICAgaWYgKHRoaXMuZmlsdGVyKSB7XG4gICAgICBpZiAodGhpcy5maWx0ZXIgaW5zdGFuY2VvZiBEYXRhZ3JpZFN0cmluZ0ZpbHRlckltcGwpIHtcbiAgICAgICAgaWYgKCFuZXdWYWx1ZSB8fCB0eXBlb2YgbmV3VmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgbmV3VmFsdWUgPSAnJztcbiAgICAgICAgfVxuICAgICAgICBpZiAobmV3VmFsdWUgIT09IHRoaXMuZmlsdGVyLnZhbHVlKSB7XG4gICAgICAgICAgdGhpcy5maWx0ZXIudmFsdWUgPSBuZXdWYWx1ZTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0aGlzLmZpbHRlciBpbnN0YW5jZW9mIERhdGFncmlkTnVtZXJpY0ZpbHRlckltcGwpIHtcbiAgICAgICAgaWYgKCFuZXdWYWx1ZSB8fCAhKG5ld1ZhbHVlIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgICAgbmV3VmFsdWUgPSBbbnVsbCwgbnVsbF07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5ld1ZhbHVlLmxlbmd0aCA9PT0gMiAmJiAobmV3VmFsdWVbMF0gIT09IHRoaXMuZmlsdGVyLnZhbHVlWzBdIHx8IG5ld1ZhbHVlWzFdICE9PSB0aGlzLmZpbHRlci52YWx1ZVsxXSkpIHtcbiAgICAgICAgICB0aGlzLmZpbHRlci52YWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaW5pdEZpbHRlclZhbHVlID0gbmV3VmFsdWU7XG4gICAgfVxuICB9XG5cbiAgQENvbnRlbnRDaGlsZChDdXN0b21GaWx0ZXIpXG4gIHNldCBwcm9qZWN0ZWRGaWx0ZXIoY3VzdG9tOiBhbnkpIHtcbiAgICBpZiAoY3VzdG9tKSB7XG4gICAgICB0aGlzLmRlbGV0ZUZpbHRlcigpO1xuICAgICAgdGhpcy5jdXN0b21GaWx0ZXIgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgaWYgdGhlIGNvbHVtbiBpcyBzb3J0YWJsZVxuICAgKi9cbiAgZ2V0IHNvcnRhYmxlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIXRoaXMuX3NvcnRCeTtcbiAgfVxuXG4gIGdldCBhcmlhU29ydCgpIHtcbiAgICBzd2l0Y2ggKHRoaXMuX3NvcnRPcmRlcikge1xuICAgICAgY2FzZSBDbHJEYXRhZ3JpZFNvcnRPcmRlci5BU0M6XG4gICAgICAgIHJldHVybiAnYXNjZW5kaW5nJztcbiAgICAgIGNhc2UgQ2xyRGF0YWdyaWRTb3J0T3JkZXIuREVTQzpcbiAgICAgICAgcmV0dXJuICdkZXNjZW5kaW5nJztcbiAgICAgIGNhc2UgQ2xyRGF0YWdyaWRTb3J0T3JkZXIuVU5TT1JURUQ6XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gJ25vbmUnO1xuICAgIH1cbiAgfVxuXG4gIGdldCBzb3J0RGlyZWN0aW9uKCk6ICd1cCcgfCAnZG93bicgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fc29ydERpcmVjdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBATk9URSB0eXBlIGBhbnlgIGhlcmUgaXMgdG8gbGV0IHVzIHBhc3MgdGVtcGxhdGVTdHJpY3RNb2RlLCBiZWNhdXNlIGluIG91ciBjb2RlIHdlIHRyeSB0byBoYW5kbGVcbiAgICogdHdvIHR5cGVzIG9mIGZpbHRlcnMgU3RyaW5nIGFuZCBOdW1iZXIgd2l0aCB0aGUgc2FtZSB2YXJpYWJsZSBidXQgYm90aCBvZiB0aGVtIHdvcmsgd2l0aCBkaWZmZXJlbnRcbiAgICogZm9ybWF0IHdlIGdvdCBhbiBlcnJvciBmb3IgY2FzdGluZy4gV2UgY291bGQgbm90IGNhc3QgYW55dGhpbmcgaW5zaWRlIHRoZSB0ZW1wbGF0ZSBzbyB0byBub3QgbWVzcyB0aGVcbiAgICogY2FzdGluZywgdGhlIGxhc3QgdHlwZSBpcyBzZXQgdG8gYGFueWBcbiAgICpcbiAgICogT3JpZ25pYWwgdHlwZXM6IHN0cmluZyB8IFtudW1iZXIsIG51bWJlcl1cbiAgICovXG4gIGdldCBmaWx0ZXJWYWx1ZSgpIHtcbiAgICBpZiAodGhpcy5maWx0ZXIgaW5zdGFuY2VvZiBEYXRhZ3JpZFN0cmluZ0ZpbHRlckltcGwgfHwgdGhpcy5maWx0ZXIgaW5zdGFuY2VvZiBEYXRhZ3JpZE51bWVyaWNGaWx0ZXJJbXBsKSB7XG4gICAgICByZXR1cm4gdGhpcy5maWx0ZXIudmFsdWU7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG4gIHNldCBmaWx0ZXJWYWx1ZShuZXdWYWx1ZTogYW55KSB7XG4gICAgaWYgKHRoaXMuZmlsdGVyIGluc3RhbmNlb2YgRGF0YWdyaWRTdHJpbmdGaWx0ZXJJbXBsIHx8IHRoaXMuZmlsdGVyIGluc3RhbmNlb2YgRGF0YWdyaWROdW1lcmljRmlsdGVySW1wbCkge1xuICAgICAgdGhpcy51cGRhdGVGaWx0ZXJWYWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgdGhpcy5maWx0ZXJWYWx1ZUNoYW5nZS5lbWl0KHRoaXMuZmlsdGVyLnZhbHVlKTtcbiAgICB9XG4gIH1cblxuICBnZXQgX3ZpZXcoKSB7XG4gICAgcmV0dXJuIHRoaXMud3JhcHBlZEluamVjdG9yLmdldChXcmFwcGVkQ29sdW1uLCB0aGlzLnZjcikuY29sdW1uVmlldztcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMud3JhcHBlZEluamVjdG9yID0gbmV3IEhvc3RXcmFwcGVyKFdyYXBwZWRDb2x1bW4sIHRoaXMudmNyKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLnNldEZpbHRlclRvZ2dsZUFyaWFMYWJlbCgpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xuICAgIGlmIChcbiAgICAgIGNoYW5nZXMuY29sVHlwZSAmJlxuICAgICAgY2hhbmdlcy5jb2xUeXBlLmN1cnJlbnRWYWx1ZSAmJlxuICAgICAgY2hhbmdlcy5jb2xUeXBlLmN1cnJlbnRWYWx1ZSAhPT0gY2hhbmdlcy5jb2xUeXBlLnByZXZpb3VzVmFsdWVcbiAgICApIHtcbiAgICAgIGlmICghdGhpcy5jdXN0b21GaWx0ZXIgJiYgIXRoaXMuZmlsdGVyICYmIHRoaXMuY29sVHlwZSAmJiB0aGlzLmZpZWxkKSB7XG4gICAgICAgIHRoaXMuc2V0dXBEZWZhdWx0RmlsdGVyKHRoaXMuZmllbGQsIHRoaXMuY29sVHlwZSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzLmZpZWxkICYmIGNoYW5nZXMuZmllbGQuY3VycmVudFZhbHVlICYmIGNoYW5nZXMuZmllbGQuY3VycmVudFZhbHVlICE9PSBjaGFuZ2VzLmZpZWxkLnByZXZpb3VzVmFsdWUpIHtcbiAgICAgIGlmICghdGhpcy5jdXN0b21GaWx0ZXIgJiYgdGhpcy5jb2xUeXBlKSB7XG4gICAgICAgIHRoaXMuc2V0dXBEZWZhdWx0RmlsdGVyKHRoaXMuZmllbGQsIHRoaXMuY29sVHlwZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgb3ZlcnJpZGUgbmdPbkRlc3Ryb3koKSB7XG4gICAgc3VwZXIubmdPbkRlc3Ryb3koKTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZm9yRWFjaChzID0+IHMudW5zdWJzY3JpYmUoKSk7XG4gIH1cblxuICAvKipcbiAgICogU29ydHMgdGhlIGRhdGFncmlkIGJhc2VkIG9uIHRoaXMgY29sdW1uXG4gICAqL1xuICBzb3J0KHJldmVyc2U/OiBib29sZWFuKSB7XG4gICAgaWYgKCF0aGlzLnNvcnRhYmxlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fc29ydC50b2dnbGUodGhpcy5fc29ydEJ5LCByZXZlcnNlKTtcblxuICAgIC8vIHNldHRpbmcgdGhlIHByaXZhdGUgdmFyaWFibGUgdG8gbm90IHJldHJpZ2dlciB0aGUgc2V0dGVyIGxvZ2ljXG4gICAgdGhpcy5fc29ydE9yZGVyID0gdGhpcy5fc29ydC5yZXZlcnNlID8gQ2xyRGF0YWdyaWRTb3J0T3JkZXIuREVTQyA6IENsckRhdGFncmlkU29ydE9yZGVyLkFTQztcbiAgICAvLyBTZXRzIHRoZSBjb3JyZWN0IGljb24gZm9yIGN1cnJlbnQgc29ydCBvcmRlclxuICAgIHRoaXMuX3NvcnREaXJlY3Rpb24gPSB0aGlzLl9zb3J0T3JkZXIgPT09IENsckRhdGFncmlkU29ydE9yZGVyLkRFU0MgPyAnZG93bicgOiAndXAnO1xuICAgIHRoaXMuc29ydE9yZGVyQ2hhbmdlLmVtaXQodGhpcy5fc29ydE9yZGVyKTtcbiAgfVxuXG4gIHByaXZhdGUgbGlzdGVuRm9yRGV0YWlsUGFuZUNoYW5nZXMoKSB7XG4gICAgcmV0dXJuIHRoaXMuZGV0YWlsU2VydmljZS5zdGF0ZUNoYW5nZS5zdWJzY3JpYmUoc3RhdGUgPT4ge1xuICAgICAgaWYgKHRoaXMuc2hvd1NlcGFyYXRvciAhPT0gIXN0YXRlKSB7XG4gICAgICAgIHRoaXMuc2hvd1NlcGFyYXRvciA9ICFzdGF0ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0RmlsdGVyVG9nZ2xlQXJpYUxhYmVsKCkge1xuICAgIGNvbnN0IGZpbHRlclRvZ2dsZSA9IHRoaXMuZWwubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCcuZGF0YWdyaWQtZmlsdGVyLXRvZ2dsZScpO1xuICAgIGlmIChmaWx0ZXJUb2dnbGUpIHtcbiAgICAgIGZpbHRlclRvZ2dsZS5hcmlhTGFiZWwgPSB0aGlzLmNvbW1vblN0cmluZ3MucGFyc2UodGhpcy5jb21tb25TdHJpbmdzLmtleXMuZGF0YWdyaWRGaWx0ZXJBcmlhTGFiZWwsIHtcbiAgICAgICAgQ09MVU1OOiB0aGlzPy50aXRsZUNvbnRhaW5lcj8ubmF0aXZlRWxlbWVudC50ZXh0Q29udGVudC50cmltKCkudG9Mb2NhbGVMb3dlckNhc2UoKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbGlzdGVuRm9yU29ydGluZ0NoYW5nZXMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NvcnQuY2hhbmdlLnN1YnNjcmliZShzb3J0ID0+IHtcbiAgICAgIC8vIE5lZWQgdG8gbWFudWFsbHkgbWFyayB0aGUgY29tcG9uZW50IHRvIGJlIGNoZWNrZWRcbiAgICAgIC8vIGZvciBib3RoIGFjdGl2YXRpbmcgYW5kIGRlYWN0aXZhdGluZyBzb3J0aW5nXG4gICAgICB0aGlzLmNoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuICAgICAgLy8gV2UncmUgb25seSBsaXN0ZW5pbmcgdG8gbWFrZSBzdXJlIHdlIGVtaXQgYW4gZXZlbnQgd2hlbiB0aGUgY29sdW1uIGdvZXMgZnJvbSBzb3J0ZWQgdG8gdW5zb3J0ZWRcbiAgICAgIGlmICh0aGlzLnNvcnRPcmRlciAhPT0gQ2xyRGF0YWdyaWRTb3J0T3JkZXIuVU5TT1JURUQgJiYgc29ydC5jb21wYXJhdG9yICE9PSB0aGlzLl9zb3J0QnkpIHtcbiAgICAgICAgdGhpcy5fc29ydE9yZGVyID0gQ2xyRGF0YWdyaWRTb3J0T3JkZXIuVU5TT1JURUQ7XG4gICAgICAgIHRoaXMuc29ydE9yZGVyQ2hhbmdlLmVtaXQodGhpcy5fc29ydE9yZGVyKTtcbiAgICAgICAgdGhpcy5fc29ydERpcmVjdGlvbiA9IG51bGw7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHNldHVwRGVmYXVsdEZpbHRlcihmaWVsZDogc3RyaW5nLCBjb2xUeXBlOiAnc3RyaW5nJyB8ICdudW1iZXInKSB7XG4gICAgaWYgKGNvbFR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgICB0aGlzLnNldEZpbHRlcihuZXcgRGF0YWdyaWROdW1lcmljRmlsdGVySW1wbChuZXcgRGF0YWdyaWRQcm9wZXJ0eU51bWVyaWNGaWx0ZXIoZmllbGQpKSk7XG4gICAgfSBlbHNlIGlmIChjb2xUeXBlID09PSAnc3RyaW5nJykge1xuICAgICAgdGhpcy5zZXRGaWx0ZXIobmV3IERhdGFncmlkU3RyaW5nRmlsdGVySW1wbChuZXcgRGF0YWdyaWRQcm9wZXJ0eVN0cmluZ0ZpbHRlcihmaWVsZCkpKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuZmlsdGVyICYmIHRoaXMuaW5pdEZpbHRlclZhbHVlKSB7XG4gICAgICB0aGlzLnVwZGF0ZUZpbHRlclZhbHVlID0gdGhpcy5pbml0RmlsdGVyVmFsdWU7XG4gICAgICAvLyBUaGlzIGluaXRGaWx0ZXJWYWx1ZSBzaG91bGQgYmUgdXNlZCBvbmx5IG9uY2UgYWZ0ZXIgdGhlIGZpbHRlciByZWdpc3RyYXRpb25cbiAgICAgIC8vIFNvIGRlbGV0aW5nIHRoaXMgcHJvcGVydHkgdmFsdWUgdG8gcHJldmVudCBpdCBmcm9tIGJlaW5nIHVzZWQgYWdhaW5cbiAgICAgIC8vIGlmIHRoaXMgZmllbGQgcHJvcGVydHkgaXMgc2V0IGFnYWluXG4gICAgICBkZWxldGUgdGhpcy5pbml0RmlsdGVyVmFsdWU7XG4gICAgfVxuICB9XG59XG4iXX0=