@kushki/ng-suka
Version:
<p align="center"> <h1 align="center">Suka Components Angular</h1> <p align="center"> An Angular implementation of the Suka Design System </p> </p>
516 lines • 45.1 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, Input, Output, EventEmitter, ViewEncapsulation, ElementRef, HostListener } from '@angular/core';
import rangePlugin from 'flatpickr/dist/plugins/rangePlugin';
import flatpickr from 'flatpickr';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { sukaFlatpickrMonthSelectPlugin } from './sukaFlatpickrMonthSelectPlugin';
export class DatePicker {
/**
* @param {?} elementRef
*/
constructor(elementRef) {
this.elementRef = elementRef;
/**
* Select calendar range mode
*/
this.range = false;
/**
* Format of date
*
* For reference: https://flatpickr.js.org/formatting/
*/
this.dateFormat = 'd/m/Y';
this.placeholder = 'dd/mm/yyyy';
this.pattern = '^\\d{1,2}/\\d{1,2}/\\d{4}$';
this.id = `datepicker-${DatePicker.datePickerCount++}`;
this.disabled = false;
this.invalid = false;
this.skeleton = false;
this.plugins = [];
this.valueChange = new EventEmitter();
this._value = [];
this._flatpickrOptions = {
allowInput: true
};
this.flatpickrBaseOptions = {
mode: 'single',
dateFormat: 'd/m/Y',
plugins: this.plugins,
onOpen: (/**
* @return {?}
*/
() => { this.updateClassNames(); }),
value: this.value
};
this.flatpickrInstance = null;
this.onTouched = (/**
* @return {?}
*/
() => { });
this.propagateChange = (/**
* @param {?} _
* @return {?}
*/
(_) => { });
}
/**
* @param {?} v
* @return {?}
*/
set value(v) {
if (!v) {
v = [];
}
this._value = v;
}
/**
* @return {?}
*/
get value() {
return this._value;
}
/**
* @param {?} options
* @return {?}
*/
set flatpickrOptions(options) {
this._flatpickrOptions = Object.assign({}, this._flatpickrOptions, options);
}
/**
* @return {?}
*/
get flatpickrOptions() {
/** @type {?} */
const plugins = [...this.plugins, sukaFlatpickrMonthSelectPlugin];
if (this.range) {
plugins.push(rangePlugin({ input: `#${this.id}-rangeInput`, position: 'left' }));
}
return Object.assign({}, this._flatpickrOptions, this.flatpickrBaseOptions, {
mode: this.range ? 'range' : 'single',
plugins,
dateFormat: this.dateFormat
});
}
/**
* @param {?} options
* @return {?}
*/
set flatpickrOptionsRange(options) {
console.warn('flatpickrOptionsRange is deprecated, use flatpickrOptions and set the range to true instead');
this.range = true;
this.flatpickrOptions = options;
}
/**
* @return {?}
*/
get flatpickrOptionsRange() {
console.warn('flatpickrOptionsRange is deprecated, use flatpickrOptions and set the range to true instead');
return this.flatpickrOptions;
}
/**
* @param {?} changes
* @return {?}
*/
ngOnChanges(changes) {
if (this.isFlatpickrLoaded()) {
/** @type {?} */
let dates = this.flatpickrInstance.selectedDates;
if (changes.value && this.didDateValueChange(changes.value.currentValue, changes.value.previousValue)) {
dates = changes.value.currentValue;
}
// only reset the flatpickr instance on Input changes
this.flatpickrInstance = flatpickr(`#${this.id}`, this.flatpickrOptions);
this.setDateValues(dates);
}
}
// because the actual view may be delayed in loading (think projection into a tab pane)
// and because we rely on a library that operates outside the Angular view of the world
// we need to keep trying to load the library, until the relevant DOM is actually live
/**
* @return {?}
*/
ngAfterViewChecked() {
if (!this.isFlatpickrLoaded()) {
this.flatpickrInstance = flatpickr(`#${this.id}`, this.flatpickrOptions);
// if (and only if) the initialization succeeded, we can set the date values
if (this.isFlatpickrLoaded()) {
if (this.value.length > 0) {
this.setDateValues(this.value);
}
}
}
}
/**
* @return {?}
*/
onFocus() {
this.onTouched();
}
/**
* Writes a value from the model to the component. Expects the value to be `null` or `(Date | string)[]`
* @param {?} value value received from the model
* @return {?}
*/
writeValue(value) {
this.value = value;
if (this.isFlatpickrLoaded() && this.flatpickrInstance.config) {
this.setDateValues(this.value);
}
}
/**
* @param {?} fn
* @return {?}
*/
registerOnChange(fn) {
this.propagateChange = fn;
}
/**
* @param {?} fn
* @return {?}
*/
registerOnTouched(fn) {
this.onTouched = fn;
}
/**
* Cleans up our flatpickr instance
* @return {?}
*/
ngOnDestroy() {
if (!this.isFlatpickrLoaded()) {
return;
}
this.flatpickrInstance.destroy();
}
/**
* Handles the `valueChange` event from the primary/single input
* @param {?} event
* @return {?}
*/
onValueChange(event) {
if (this.isFlatpickrLoaded()) {
/** @type {?} */
const date = this.flatpickrInstance.parseDate(event, this.dateFormat);
if (this.range) {
this.setDateValues([date, this.flatpickrInstance.selectedDates[1]]);
}
else {
this.setDateValues([date]);
}
this.doSelect(this.flatpickrInstance.selectedDates);
}
}
/**
* Handles the `valueChange` event from the range input
* @param {?} event
* @return {?}
*/
onRangeValueChange(event) {
if (this.isFlatpickrLoaded()) {
/** @type {?} */
const date = this.flatpickrInstance.parseDate(event, this.dateFormat);
this.setDateValues([this.flatpickrInstance.selectedDates[0], date]);
this.doSelect(this.flatpickrInstance.selectedDates);
}
}
/**
* Carbon uses a number of specific classnames for parts of the flatpickr - this idempotent method applies them if needed.
* @protected
* @return {?}
*/
updateClassNames() {
if (!this.elementRef) {
return;
}
// get all the possible flatpickrs in the document - we need to add classes to (potentially) all of them
/** @type {?} */
const calendarContainer = document.querySelectorAll('.flatpickr-calendar');
/** @type {?} */
const monthContainer = document.querySelectorAll('.flatpickr-month');
/** @type {?} */
const weekdaysContainer = document.querySelectorAll('.flatpickr-weekdays');
/** @type {?} */
const weekdayContainer = document.querySelectorAll('.flatpickr-weekday');
/** @type {?} */
const daysContainer = document.querySelectorAll('.flatpickr-days');
/** @type {?} */
const dayContainer = document.querySelectorAll('.flatpickr-day');
// add classes to lists of elements
/** @type {?} */
const addClassIfNotExists = (/**
* @param {?} classname
* @param {?} elementList
* @return {?}
*/
(classname, elementList) => {
Array.from(elementList).forEach((/**
* @param {?} element
* @return {?}
*/
element => {
if (!element.classList.contains(classname)) {
element.classList.add(classname);
}
}));
});
// add classes (but only if they don't exist, small perf win)
addClassIfNotExists('date-picker__calendar', calendarContainer);
addClassIfNotExists('date-picker__month', monthContainer);
addClassIfNotExists('date-picker__weekdays', weekdaysContainer);
addClassIfNotExists('date-picker__days', daysContainer);
// add weekday classes and format the text
Array.from(weekdayContainer).forEach((/**
* @param {?} element
* @return {?}
*/
element => {
element.innerHTML = element.innerHTML.replace(/\s+/g, '');
element.classList.add('date-picker__weekday');
}));
// add day classes and special case the "today" element based on `this.value`
Array.from(dayContainer).forEach((/**
* @param {?} element
* @return {?}
*/
element => {
element.classList.add('date-picker__day');
if (!this.value) {
return;
}
if (element.classList.contains('today') && this.value.length > 0) {
element.classList.add('no-border');
}
else if (element.classList.contains('today') && this.value.length === 0) {
element.classList.remove('no-border');
}
}));
}
/**
* Applies the given date value array to both the flatpickr instance and the `input`(s)
* @protected
* @param {?} dates the date values to apply
* @return {?}
*/
setDateValues(dates) {
if (this.isFlatpickrLoaded()) {
/** @type {?} */
const singleInput = this.elementRef.nativeElement.querySelector(`#${this.id}`);
/** @type {?} */
const rangeInput = this.elementRef.nativeElement.querySelector(`#${this.id}-rangeInput`);
// set the date on the instance
this.flatpickrInstance.setDate(dates);
// we can either set a date value or an empty string, so we start with an empty string
/** @type {?} */
let singleDate = '';
// if date is a string, parse and format
if (typeof this.flatpickrInstance.selectedDates[0] === 'string') {
singleDate = this.flatpickrInstance.parseDate(this.flatpickrInstance.selectedDates[0], this.dateFormat);
singleDate = this.flatpickrInstance.formatDate(singleDate, this.dateFormat);
// if date is not a string we can assume it's a Date and we should format
}
else if (!!this.flatpickrInstance.selectedDates[0]) {
singleDate = this.flatpickrInstance.formatDate(this.flatpickrInstance.selectedDates[0], this.dateFormat);
}
if (rangeInput) {
// we can either set a date value or an empty string, so we start with an empty string
/** @type {?} */
let rangeDate = '';
// if date is a string, parse and format
if (typeof this.flatpickrInstance.selectedDates[1] === 'string') {
rangeDate = this.flatpickrInstance.parseDate(this.flatpickrInstance.selectedDates[1].toString(), this.dateFormat);
rangeDate = this.flatpickrInstance.formatDate(rangeDate, this.dateFormat);
// if date is not a string we can assume it's a Date and we should format
}
else if (!!this.flatpickrInstance.selectedDates[1]) {
rangeDate = this.flatpickrInstance.formatDate(this.flatpickrInstance.selectedDates[1], this.dateFormat);
}
setTimeout((/**
* @return {?}
*/
() => {
// apply the values
rangeInput.value = rangeDate;
singleInput.value = singleDate;
}));
}
}
}
/**
* @protected
* @param {?} selectedValue
* @return {?}
*/
doSelect(selectedValue) {
this.valueChange.emit(selectedValue);
this.propagateChange(selectedValue);
}
/**
* @protected
* @param {?} currentValue
* @param {?} previousValue
* @return {?}
*/
didDateValueChange(currentValue, previousValue) {
return currentValue[0] !== previousValue[0] || currentValue[1] !== previousValue[1];
}
/**
* More advanced checking of the loaded state of flatpickr
* @protected
* @return {?}
*/
isFlatpickrLoaded() {
// cast the instance to a boolean, and some method that has to exist for the library to be loaded in this case `setDate`
return !!this.flatpickrInstance && !!this.flatpickrInstance.setDate;
}
}
DatePicker.datePickerCount = 0;
DatePicker.decorators = [
{ type: Component, args: [{
selector: 'suka-date-picker',
template: `
<div class="form-item">
<div
class="date-picker"
[ngClass]="{
'date-picker--range' : range,
'date-picker--single' : !range,
'skeleton' : skeleton
}">
<div class="date-picker-container">
<suka-date-picker-input
[label]="label"
[placeholder]="placeholder"
[pattern]="pattern"
[id]="id"
[type]="(range ? 'range' : 'single')"
[hasIcon]="(range ? false : true)"
[disabled]="disabled"
[invalid]="invalid"
[invalidText]="invalidText"
[skeleton]="skeleton"
(valueChange)="onValueChange($event)">
</suka-date-picker-input>
</div>
<div *ngIf="range" class="date-picker-container">
<suka-date-picker-input
[label]="rangeLabel"
[placeholder]="placeholder"
[pattern]="pattern"
[id]="id + '-rangeInput'"
[type]="(range ? 'range' : 'single')"
[hasIcon]="(range ? true : null)"
[disabled]="disabled"
[invalid]="invalid"
[invalidText]="invalidText"
[skeleton]="skeleton"
(valueChange)="onRangeValueChange($event)">
</suka-date-picker-input>
</div>
</div>
</div>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: DatePicker,
multi: true
}
],
encapsulation: ViewEncapsulation.None
}] }
];
/** @nocollapse */
DatePicker.ctorParameters = () => [
{ type: ElementRef }
];
DatePicker.propDecorators = {
range: [{ type: Input }],
dateFormat: [{ type: Input }],
label: [{ type: Input }],
rangeLabel: [{ type: Input }],
placeholder: [{ type: Input }],
pattern: [{ type: Input }],
id: [{ type: Input }],
value: [{ type: Input }],
disabled: [{ type: Input }],
invalid: [{ type: Input }],
invalidText: [{ type: Input }],
skeleton: [{ type: Input }],
plugins: [{ type: Input }],
flatpickrOptions: [{ type: Input }],
valueChange: [{ type: Output }],
onFocus: [{ type: HostListener, args: ['focusin',] }]
};
if (false) {
/**
* @type {?}
* @private
*/
DatePicker.datePickerCount;
/**
* Select calendar range mode
* @type {?}
*/
DatePicker.prototype.range;
/**
* Format of date
*
* For reference: https://flatpickr.js.org/formatting/
* @type {?}
*/
DatePicker.prototype.dateFormat;
/** @type {?} */
DatePicker.prototype.label;
/** @type {?} */
DatePicker.prototype.rangeLabel;
/** @type {?} */
DatePicker.prototype.placeholder;
/** @type {?} */
DatePicker.prototype.pattern;
/** @type {?} */
DatePicker.prototype.id;
/** @type {?} */
DatePicker.prototype.disabled;
/** @type {?} */
DatePicker.prototype.invalid;
/** @type {?} */
DatePicker.prototype.invalidText;
/** @type {?} */
DatePicker.prototype.skeleton;
/** @type {?} */
DatePicker.prototype.plugins;
/** @type {?} */
DatePicker.prototype.valueChange;
/**
* @type {?}
* @protected
*/
DatePicker.prototype._value;
/**
* @type {?}
* @protected
*/
DatePicker.prototype._flatpickrOptions;
/**
* @type {?}
* @protected
*/
DatePicker.prototype.flatpickrBaseOptions;
/**
* @type {?}
* @protected
*/
DatePicker.prototype.flatpickrInstance;
/** @type {?} */
DatePicker.prototype.onTouched;
/** @type {?} */
DatePicker.prototype.propagateChange;
/**
* @type {?}
* @protected
*/
DatePicker.prototype.elementRef;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9Aa3VzaGtpL25nLXN1a2EvIiwic291cmNlcyI6WyJsaWIvZGF0ZXBpY2tlci9kYXRlcGlja2VyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksRUFDWixpQkFBaUIsRUFDakIsVUFBVSxFQUVWLFlBQVksRUFLYixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLFdBQVcsTUFBTSxvQ0FBb0MsQ0FBQztBQUM3RCxPQUFPLFNBQVMsTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDbkQsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUF3RGxGLE1BQU0sT0FBTyxVQUFVOzs7O0lBMEZyQixZQUFzQixVQUFzQjtRQUF0QixlQUFVLEdBQVYsVUFBVSxDQUFZOzs7O1FBcEZuQyxVQUFLLEdBQUcsS0FBSyxDQUFDOzs7Ozs7UUFPZCxlQUFVLEdBQUcsT0FBTyxDQUFDO1FBTXJCLGdCQUFXLEdBQUcsWUFBWSxDQUFDO1FBRTNCLFlBQU8sR0FBRyw0QkFBNEIsQ0FBQztRQUV2QyxPQUFFLEdBQUcsY0FBYyxVQUFVLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FBQztRQWFsRCxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBRWpCLFlBQU8sR0FBRyxLQUFLLENBQUM7UUFJaEIsYUFBUSxHQUFHLEtBQUssQ0FBQztRQUVqQixZQUFPLEdBQUcsRUFBRSxDQUFDO1FBNEJaLGdCQUFXLEdBQXNCLElBQUksWUFBWSxFQUFFLENBQUM7UUFFcEQsV0FBTSxHQUFHLEVBQUUsQ0FBQztRQUVaLHNCQUFpQixHQUFHO1lBQzVCLFVBQVUsRUFBRSxJQUFJO1NBQ2pCLENBQUM7UUFFUSx5QkFBb0IsR0FBRztZQUMvQixJQUFJ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QUUsVUFBVTt3QkFDdkIsS0FBSyxFQUFFLElBQUk7cUJBQ1o7aUJBQ0Y7Z0JBQ0QsYUFBYSxFQUFFLGlCQUFpQixDQUFDLElBQUk7YUFDdEM7Ozs7WUFsRUMsVUFBVTs7O29CQXlFVCxLQUFLO3lCQU9MLEtBQUs7b0JBRUwsS0FBSzt5QkFFTCxLQUFLOzBCQUVMLEtBQUs7c0JBRUwsS0FBSztpQkFFTCxLQUFLO29CQUVMLEtBQUs7dUJBV0wsS0FBSztzQkFFTCxLQUFLOzBCQUVMLEtBQUs7dUJBRUwsS0FBSztzQkFFTCxLQUFLOytCQUVMLEtBQUs7MEJBMEJMLE1BQU07c0JBZ0ROLFlBQVksU0FBQyxTQUFTOzs7Ozs7O0lBdkh2QiwyQkFBbUM7Ozs7O0lBS25DLDJCQUF1Qjs7Ozs7OztJQU92QixnQ0FBOEI7O0lBRTlCLDJCQUEwQzs7SUFFMUMsZ0NBQTRCOztJQUU1QixpQ0FBb0M7O0lBRXBDLDZCQUFnRDs7SUFFaEQsd0JBQTJEOztJQWEzRCw4QkFBMEI7O0lBRTFCLDZCQUF5Qjs7SUFFekIsaUNBQWdEOztJQUVoRCw4QkFBMEI7O0lBRTFCLDZCQUFzQjs7SUE0QnRCLGlDQUE4RDs7Ozs7SUFFOUQsNEJBQXNCOzs7OztJQUV0Qix1Q0FFRTs7Ozs7SUFFRiwwQ0FNRTs7Ozs7SUFFRix1Q0FBbUM7O0lBd0RuQywrQkFBaUM7O0lBRWpDLHFDQUFrQzs7Ozs7SUF4RHRCLGdDQUFnQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgRWxlbWVudFJlZixcbiAgT25EZXN0cm95LFxuICBIb3N0TGlzdGVuZXIsXG4gIFRlbXBsYXRlUmVmLFxuICBPbkNoYW5nZXMsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIEFmdGVyVmlld0NoZWNrZWRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgcmFuZ2VQbHVnaW4gZnJvbSAnZmxhdHBpY2tyL2Rpc3QvcGx1Z2lucy9yYW5nZVBsdWdpbic7XG5pbXBvcnQgZmxhdHBpY2tyIGZyb20gJ2ZsYXRwaWNrcic7XG5pbXBvcnQgeyBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IHN1a2FGbGF0cGlja3JNb250aFNlbGVjdFBsdWdpbiB9IGZyb20gJy4vc3VrYUZsYXRwaWNrck1vbnRoU2VsZWN0UGx1Z2luJztcblxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzdWthLWRhdGUtcGlja2VyJyxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1pdGVtXCI+XG4gICAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwiZGF0ZS1waWNrZXJcIlxuICAgICAgICBbbmdDbGFzc109XCJ7XG4gICAgICAgICAgJ2RhdGUtcGlja2VyLS1yYW5nZScgOiByYW5nZSxcbiAgICAgICAgICAnZGF0ZS1waWNrZXItLXNpbmdsZScgOiAhcmFuZ2UsXG4gICAgICAgICAgJ3NrZWxldG9uJyA6IHNrZWxldG9uXG4gICAgICAgIH1cIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImRhdGUtcGlja2VyLWNvbnRhaW5lclwiPlxuICAgICAgICAgIDxzdWthLWRhdGUtcGlja2VyLWlucHV0XG4gICAgICAgICAgICBbbGFiZWxdPVwibGFiZWxcIlxuICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyXCJcbiAgICAgICAgICAgIFtwYXR0ZXJuXT1cInBhdHRlcm5cIlxuICAgICAgICAgICAgW2lkXT1cImlkXCJcbiAgICAgICAgICAgIFt0eXBlXT1cIihyYW5nZSA/ICdyYW5nZScgOiAnc2luZ2xlJylcIlxuICAgICAgICAgICAgW2hhc0ljb25dPVwiKHJhbmdlID8gZmFsc2UgOiB0cnVlKVwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgW2ludmFsaWRdPVwiaW52YWxpZFwiXG4gICAgICAgICAgICBbaW52YWxpZFRleHRdPVwiaW52YWxpZFRleHRcIlxuICAgICAgICAgICAgW3NrZWxldG9uXT1cInNrZWxldG9uXCJcbiAgICAgICAgICAgICh2YWx1ZUNoYW5nZSk9XCJvblZhbHVlQ2hhbmdlKCRldmVudClcIj5cbiAgICAgICAgICA8L3N1a2EtZGF0ZS1waWNrZXItaW5wdXQ+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2ICpuZ0lmPVwicmFuZ2VcIiBjbGFzcz1cImRhdGUtcGlja2VyLWNvbnRhaW5lclwiPlxuICAgICAgICAgIDxzdWthLWRhdGUtcGlja2VyLWlucHV0XG4gICAgICAgICAgICBbbGFiZWxdPVwicmFuZ2VMYWJlbFwiXG4gICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICAgICAgICAgICAgW3BhdHRlcm5dPVwicGF0dGVyblwiXG4gICAgICAgICAgICBbaWRdPVwiaWQgKyAnLXJhbmdlSW5wdXQnXCJcbiAgICAgICAgICAgIFt0eXBlXT1cIihyYW5nZSA/ICdyYW5nZScgOiAnc2luZ2xlJylcIlxuICAgICAgICAgICAgW2hhc0ljb25dPVwiKHJhbmdlID8gdHJ1ZSA6IG51bGwpXCJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICBbaW52YWxpZF09XCJpbnZhbGlkXCJcbiAgICAgICAgICAgIFtpbnZhbGlkVGV4dF09XCJpbnZhbGlkVGV4dFwiXG4gICAgICAgICAgICBbc2tlbGV0b25dPVwic2tlbGV0b25cIlxuICAgICAgICAgICAgKHZhbHVlQ2hhbmdlKT1cIm9uUmFuZ2VWYWx1ZUNoYW5nZSgkZXZlbnQpXCI+XG4gICAgICAgICAgPC9zdWthLWRhdGUtcGlja2VyLWlucHV0PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICBgLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBEYXRlUGlja2VyLFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9XG4gIF0sXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmVcbn0pXG5leHBvcnQgY2xhc3MgRGF0ZVBpY2tlciBpbXBsZW1lbnRzIE9uRGVzdHJveSwgT25DaGFuZ2VzLCBBZnRlclZpZXdDaGVja2VkIHtcbiAgcHJpdmF0ZSBzdGF0aWMgZGF0ZVBpY2tlckNvdW50ID0gMDtcblxuICAvKipcbiAgICogU2VsZWN0IGNhbGVuZGFyIHJhbmdlIG1vZGVcbiAgICovXG4gIEBJbnB1dCgpIHJhbmdlID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEZvcm1hdCBvZiBkYXRlXG4gICAqXG4gICAqIEZvciByZWZlcmVuY2U6IGh0dHBzOi8vZmxhdHBpY2tyLmpzLm9yZy9mb3JtYXR0aW5nL1xuICAgKi9cbiAgQElucHV0KCkgZGF0ZUZvcm1hdCA9ICdkL20vWSc7XG5cbiAgQElucHV0KCkgbGFiZWw6IHN0cmluZyB8IFRlbXBsYXRlUmVmPGFueT47XG5cbiAgQElucHV0KCkgcmFuZ2VMYWJlbDogc3RyaW5nO1xuXG4gIEBJbnB1dCgpIHBsYWNlaG9sZGVyID0gJ2RkL21tL3l5eXknO1xuXG4gIEBJbnB1dCgpIHBhdHRlcm4gPSAnXlxcXFxkezEsMn0vXFxcXGR7MSwyfS9cXFxcZHs0fSQnO1xuXG4gIEBJbnB1dCgpIGlkID0gYGRhdGVwaWNrZXItJHtEYXRlUGlja2VyLmRhdGVQaWNrZXJDb3VudCsrfWA7XG5cbiAgQElucHV0KCkgc2V0IHZhbHVlKHY6IChEYXRlIHwgc3RyaW5nKVtdKSB7XG4gICAgaWYgKCF2KSB7XG4gICAgICB2ID0gW107XG4gICAgfVxuICAgIHRoaXMuX3ZhbHVlID0gdjtcbiAgfVxuXG4gIGdldCB2YWx1ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fdmFsdWU7XG4gIH1cblxuICBASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpIGludmFsaWQgPSBmYWxzZTtcblxuICBASW5wdXQoKSBpbnZhbGlkVGV4dDogc3RyaW5nIHwgVGVtcGxhdGVSZWY8YW55PjtcblxuICBASW5wdXQoKSBza2VsZXRvbiA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpIHBsdWdpbnMgPSBbXTtcblxuICBASW5wdXQoKVxuICBzZXQgZmxhdHBpY2tyT3B0aW9ucyhvcHRpb25zKSB7XG4gICAgdGhpcy5fZmxhdHBpY2tyT3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuX2ZsYXRwaWNrck9wdGlvbnMsIG9wdGlvbnMpO1xuICB9XG4gIGdldCBmbGF0cGlja3JPcHRpb25zKCkge1xuICAgIGNvbnN0IHBsdWdpbnMgPSBbLi4udGhpcy5wbHVnaW5zLCBzdWthRmxhdHBpY2tyTW9udGhTZWxlY3RQbHVnaW5dO1xuICAgIGlmICh0aGlzLnJhbmdlKSB7XG4gICAgICBwbHVnaW5zLnB1c2gocmFuZ2VQbHVnaW4oeyBpbnB1dDogYCMke3RoaXMuaWR9LXJhbmdlSW5wdXRgLCBwb3NpdGlvbjogJ2xlZnQnIH0pKTtcbiAgICB9XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIHRoaXMuX2ZsYXRwaWNrck9wdGlvbnMsIHRoaXMuZmxhdHBpY2tyQmFzZU9wdGlvbnMsIHtcbiAgICAgIG1vZGU6IHRoaXMucmFuZ2UgPyAncmFuZ2UnIDogJ3NpbmdsZScsXG4gICAgICBwbHVnaW5zLFxuICAgICAgZGF0ZUZvcm1hdDogdGhpcy5kYXRlRm9ybWF0XG4gICAgfSk7XG4gIH1cblxuICBzZXQgZmxhdHBpY2tyT3B0aW9uc1JhbmdlKG9wdGlvbnMpIHtcbiAgICBjb25zb2xlLndhcm4oJ2ZsYXRwaWNrck9wdGlvbnNSYW5nZSBpcyBkZXByZWNhdGVkLCB1c2UgZmxhdHBpY2tyT3B0aW9ucyBhbmQgc2V0IHRoZSByYW5nZSB0byB0cnVlIGluc3RlYWQnKTtcbiAgICB0aGlzLnJhbmdlID0gdHJ1ZTtcbiAgICB0aGlzLmZsYXRwaWNrck9wdGlvbnMgPSBvcHRpb25zO1xuICB9XG4gIGdldCBmbGF0cGlja3JPcHRpb25zUmFuZ2UoKSB7XG4gICAgY29uc29sZS53YXJuKCdmbGF0cGlja3JPcHRpb25zUmFuZ2UgaXMgZGVwcmVjYXRlZCwgdXNlIGZsYXRwaWNrck9wdGlvbnMgYW5kIHNldCB0aGUgcmFuZ2UgdG8gdHJ1ZSBpbnN0ZWFkJyk7XG4gICAgcmV0dXJuIHRoaXMuZmxhdHBpY2tyT3B0aW9ucztcbiAgfVxuXG4gIEBPdXRwdXQoKSB2YWx1ZUNoYW5nZTogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcHJvdGVjdGVkIF92YWx1ZSA9IFtdO1xuXG4gIHByb3RlY3RlZCBfZmxhdHBpY2tyT3B0aW9ucyA9IHtcbiAgICBhbGxvd0lucHV0OiB0cnVlXG4gIH07XG5cbiAgcHJvdGVjdGVkIGZsYXRwaWNrckJhc2VPcHRpb25zID0ge1xuICAgIG1vZGU6ICdzaW5nbGUnLFxuICAgIGRhdGVGb3JtYXQ6ICdkL20vWScsXG4gICAgcGx1Z2luczogdGhpcy5wbHVnaW5zLFxuICAgIG9uT3BlbjogKCkgPT4geyB0aGlzLnVwZGF0ZUNsYXNzTmFtZXMoKTsgfSxcbiAgICB2YWx1ZTogdGhpcy52YWx1ZVxuICB9O1xuXG4gIHByb3RlY3RlZCBmbGF0cGlja3JJbnN0YW5jZSA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYpIHsgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBpZiAodGhpcy5pc0ZsYXRwaWNrckxvYWRlZCgpKSB7XG4gICAgICBsZXQgZGF0ZXMgPSB0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNlbGVjdGVkRGF0ZXM7XG4gICAgICBpZiAoY2hhbmdlcy52YWx1ZSAmJiB0aGlzLmRpZERhdGVWYWx1ZUNoYW5nZShjaGFuZ2VzLnZhbHVlLmN1cnJlbnRWYWx1ZSwgY2hhbmdlcy52YWx1ZS5wcmV2aW91c1ZhbHVlKSkge1xuICAgICAgICBkYXRlcyA9IGNoYW5nZXMudmFsdWUuY3VycmVudFZhbHVlO1xuICAgICAgfVxuICAgICAgLy8gb25seSByZXNldCB0aGUgZmxhdHBpY2tyIGluc3RhbmNlIG9uIElucHV0IGNoYW5nZXNcbiAgICAgIHRoaXMuZmxhdHBpY2tySW5zdGFuY2UgPSBmbGF0cGlja3IoYCMke3RoaXMuaWR9YCwgdGhpcy5mbGF0cGlja3JPcHRpb25zKTtcbiAgICAgIHRoaXMuc2V0RGF0ZVZhbHVlcyhkYXRlcyk7XG4gICAgfVxuICB9XG5cbiAgLy8gYmVjYXVzZSB0aGUgYWN0dWFsIHZpZXcgbWF5IGJlIGRlbGF5ZWQgaW4gbG9hZGluZyAodGhpbmsgcHJvamVjdGlvbiBpbnRvIGEgdGFiIHBhbmUpXG4gIC8vIGFuZCBiZWNhdXNlIHdlIHJlbHkgb24gYSBsaWJyYXJ5IHRoYXQgb3BlcmF0ZXMgb3V0c2lkZSB0aGUgQW5ndWxhciB2aWV3IG9mIHRoZSB3b3JsZFxuICAvLyB3ZSBuZWVkIHRvIGtlZXAgdHJ5aW5nIHRvIGxvYWQgdGhlIGxpYnJhcnksIHVudGlsIHRoZSByZWxldmFudCBET00gaXMgYWN0dWFsbHkgbGl2ZVxuICBuZ0FmdGVyVmlld0NoZWNrZWQoKSB7XG4gICAgaWYgKCF0aGlzLmlzRmxhdHBpY2tyTG9hZGVkKCkpIHtcbiAgICAgIHRoaXMuZmxhdHBpY2tySW5zdGFuY2UgPSBmbGF0cGlja3IoYCMke3RoaXMuaWR9YCwgdGhpcy5mbGF0cGlja3JPcHRpb25zKTtcblxuICAgICAgLy8gaWYgKGFuZCBvbmx5IGlmKSB0aGUgaW5pdGlhbGl6YXRpb24gc3VjY2VlZGVkLCB3ZSBjYW4gc2V0IHRoZSBkYXRlIHZhbHVlc1xuICAgICAgaWYgKHRoaXMuaXNGbGF0cGlja3JMb2FkZWQoKSkge1xuICAgICAgICBpZiAodGhpcy52YWx1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdGhpcy5zZXREYXRlVmFsdWVzKHRoaXMudmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZm9jdXNpbicpXG4gIG9uRm9jdXMoKSB7XG4gICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXcml0ZXMgYSB2YWx1ZSBmcm9tIHRoZSBtb2RlbCB0byB0aGUgY29tcG9uZW50LiBFeHBlY3RzIHRoZSB2YWx1ZSB0byBiZSBgbnVsbGAgb3IgYChEYXRlIHwgc3RyaW5nKVtdYFxuICAgKiBAcGFyYW0gdmFsdWUgdmFsdWUgcmVjZWl2ZWQgZnJvbSB0aGUgbW9kZWxcbiAgICovXG4gIHdyaXRlVmFsdWUodmFsdWU6IChEYXRlIHwgc3RyaW5nKVtdKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgIGlmICh0aGlzLmlzRmxhdHBpY2tyTG9hZGVkKCkgJiYgdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5jb25maWcpIHtcbiAgICAgIHRoaXMuc2V0RGF0ZVZhbHVlcyh0aGlzLnZhbHVlKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpIHtcbiAgICB0aGlzLnByb3BhZ2F0ZUNoYW5nZSA9IGZuO1xuICB9XG5cbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSkge1xuICAgIHRoaXMub25Ub3VjaGVkID0gZm47XG4gIH1cblxuICBvblRvdWNoZWQ6ICgpID0+IGFueSA9ICgpID0+IHsgfTtcblxuICBwcm9wYWdhdGVDaGFuZ2UgPSAoXzogYW55KSA9PiB7IH07XG5cbiAgLyoqXG4gICAqIENsZWFucyB1cCBvdXIgZmxhdHBpY2tyIGluc3RhbmNlXG4gICAqL1xuICBuZ09uRGVzdHJveSgpIHtcbiAgICBpZiAoIXRoaXMuaXNGbGF0cGlja3JMb2FkZWQoKSkgeyByZXR1cm47IH1cbiAgICB0aGlzLmZsYXRwaWNrckluc3RhbmNlLmRlc3Ryb3koKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIHRoZSBgdmFsdWVDaGFuZ2VgIGV2ZW50IGZyb20gdGhlIHByaW1hcnkvc2luZ2xlIGlucHV0XG4gICAqL1xuICBvblZhbHVlQ2hhbmdlKGV2ZW50OiBzdHJpbmcpIHtcbiAgICBpZiAodGhpcy5pc0ZsYXRwaWNrckxvYWRlZCgpKSB7XG4gICAgICBjb25zdCBkYXRlID0gdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5wYXJzZURhdGUoZXZlbnQsIHRoaXMuZGF0ZUZvcm1hdCk7XG4gICAgICBpZiAodGhpcy5yYW5nZSkge1xuICAgICAgICB0aGlzLnNldERhdGVWYWx1ZXMoW2RhdGUsIHRoaXMuZmxhdHBpY2tySW5zdGFuY2Uuc2VsZWN0ZWREYXRlc1sxXV0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zZXREYXRlVmFsdWVzKFtkYXRlXSk7XG4gICAgICB9XG4gICAgICB0aGlzLmRvU2VsZWN0KHRoaXMuZmxhdHBpY2tySW5zdGFuY2Uuc2VsZWN0ZWREYXRlcyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgdGhlIGB2YWx1ZUNoYW5nZWAgZXZlbnQgZnJvbSB0aGUgcmFuZ2UgaW5wdXRcbiAgICovXG4gIG9uUmFuZ2VWYWx1ZUNoYW5nZShldmVudDogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuaXNGbGF0cGlja3JMb2FkZWQoKSkge1xuICAgICAgY29uc3QgZGF0ZSA9IHRoaXMuZmxhdHBpY2tySW5zdGFuY2UucGFyc2VEYXRlKGV2ZW50LCB0aGlzLmRhdGVGb3JtYXQpO1xuICAgICAgdGhpcy5zZXREYXRlVmFsdWVzKFt0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNlbGVjdGVkRGF0ZXNbMF0sIGRhdGVdKTtcbiAgICAgIHRoaXMuZG9TZWxlY3QodGhpcy5mbGF0cGlja3JJbnN0YW5jZS5zZWxlY3RlZERhdGVzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FyYm9uIHVzZXMgYSBudW1iZXIgb2Ygc3BlY2lmaWMgY2xhc3NuYW1lcyBmb3IgcGFydHMgb2YgdGhlIGZsYXRwaWNrciAtIHRoaXMgaWRlbXBvdGVudCBtZXRob2QgYXBwbGllcyB0aGVtIGlmIG5lZWRlZC5cbiAgICovXG4gIHByb3RlY3RlZCB1cGRhdGVDbGFzc05hbWVzKCkge1xuICAgIGlmICghdGhpcy5lbGVtZW50UmVmKSB7IHJldHVybjsgfVxuXG4gICAgLy8gZ2V0IGFsbCB0aGUgcG9zc2libGUgZmxhdHBpY2tycyBpbiB0aGUgZG9jdW1lbnQgLSB3ZSBuZWVkIHRvIGFkZCBjbGFzc2VzIHRvIChwb3RlbnRpYWxseSkgYWxsIG9mIHRoZW1cbiAgICBjb25zdCBjYWxlbmRhckNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5mbGF0cGlja3ItY2FsZW5kYXInKTtcbiAgICBjb25zdCBtb250aENvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5mbGF0cGlja3ItbW9udGgnKTtcbiAgICBjb25zdCB3ZWVrZGF5c0NvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5mbGF0cGlja3Itd2Vla2RheXMnKTtcbiAgICBjb25zdCB3ZWVrZGF5Q29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmZsYXRwaWNrci13ZWVrZGF5Jyk7XG4gICAgY29uc3QgZGF5c0NvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5mbGF0cGlja3ItZGF5cycpO1xuICAgIGNvbnN0IGRheUNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5mbGF0cGlja3ItZGF5Jyk7XG5cbiAgICAvLyBhZGQgY2xhc3NlcyB0byBsaXN0cyBvZiBlbGVtZW50c1xuICAgIGNvbnN0IGFkZENsYXNzSWZOb3RFeGlzdHMgPSAoY2xhc3NuYW1lOiBzdHJpbmcsIGVsZW1lbnRMaXN0OiBOb2RlTGlzdE9mPEVsZW1lbnQ+KSA9PiB7XG4gICAgICBBcnJheS5mcm9tKGVsZW1lbnRMaXN0KS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICBpZiAoIWVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKGNsYXNzbmFtZSkpIHtcbiAgICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoY2xhc3NuYW1lKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8vIGFkZCBjbGFzc2VzIChidXQgb25seSBpZiB0aGV5IGRvbid0IGV4aXN0LCBzbWFsbCBwZXJmIHdpbilcbiAgICBhZGRDbGFzc0lmTm90RXhpc3RzKCdkYXRlLXBpY2tlcl9fY2FsZW5kYXInLCBjYWxlbmRhckNvbnRhaW5lcik7XG4gICAgYWRkQ2xhc3NJZk5vdEV4aXN0cygnZGF0ZS1waWNrZXJfX21vbnRoJywgbW9udGhDb250YWluZXIpO1xuICAgIGFkZENsYXNzSWZOb3RFeGlzdHMoJ2RhdGUtcGlja2VyX193ZWVrZGF5cycsIHdlZWtkYXlzQ29udGFpbmVyKTtcbiAgICBhZGRDbGFzc0lmTm90RXhpc3RzKCdkYXRlLXBpY2tlcl9fZGF5cycsIGRheXNDb250YWluZXIpO1xuXG4gICAgLy8gYWRkIHdlZWtkYXkgY2xhc3NlcyBhbmQgZm9ybWF0IHRoZSB0ZXh0XG4gICAgQXJyYXkuZnJvbSh3ZWVrZGF5Q29udGFpbmVyKS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgZWxlbWVudC5pbm5lckhUTUwgPSBlbGVtZW50LmlubmVySFRNTC5yZXBsYWNlKC9cXHMrL2csICcnKTtcbiAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnZGF0ZS1waWNrZXJfX3dlZWtkYXknKTtcbiAgICB9KTtcblxuICAgIC8vIGFkZCBkYXkgY2xhc3NlcyBhbmQgc3BlY2lhbCBjYXNlIHRoZSBcInRvZGF5XCIgZWxlbWVudCBiYXNlZCBvbiBgdGhpcy52YWx1ZWBcbiAgICBBcnJheS5mcm9tKGRheUNvbnRhaW5lcikuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnZGF0ZS1waWNrZXJfX2RheScpO1xuICAgICAgaWYgKCF0aGlzLnZhbHVlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChlbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygndG9kYXknKSAmJiB0aGlzLnZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKCduby1ib3JkZXInKTtcbiAgICAgIH0gZWxzZSBpZiAoZWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ3RvZGF5JykgJiYgdGhpcy52YWx1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKCduby1ib3JkZXInKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBsaWVzIHRoZSBnaXZlbiBkYXRlIHZhbHVlIGFycmF5IHRvIGJvdGggdGhlIGZsYXRwaWNrciBpbnN0YW5jZSBhbmQgdGhlIGBpbnB1dGAocylcbiAgICogQHBhcmFtIGRhdGVzIHRoZSBkYXRlIHZhbHVlcyB0byBhcHBseVxuICAgKi9cbiAgcHJvdGVjdGVkIHNldERhdGVWYWx1ZXMoZGF0ZXM6IChEYXRlIHwgc3RyaW5nKVtdKSB7XG4gICAgaWYgKHRoaXMuaXNGbGF0cGlja3JMb2FkZWQoKSkge1xuICAgICAgY29uc3Qgc2luZ2xlSW5wdXQgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKGAjJHt0aGlzLmlkfWApO1xuICAgICAgY29uc3QgcmFuZ2VJbnB1dCA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoYCMke3RoaXMuaWR9LXJhbmdlSW5wdXRgKTtcblxuICAgICAgLy8gc2V0IHRoZSBkYXRlIG9uIHRoZSBpbnN0YW5jZVxuICAgICAgdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5zZXREYXRlKGRhdGVzKTtcblxuICAgICAgLy8gd2UgY2FuIGVpdGhlciBzZXQgYSBkYXRlIHZhbHVlIG9yIGFuIGVtcHR5IHN0cmluZywgc28gd2Ugc3RhcnQgd2l0aCBhbiBlbXB0eSBzdHJpbmdcbiAgICAgIGxldCBzaW5nbGVEYXRlID0gJyc7XG4gICAgICAvLyBpZiBkYXRlIGlzIGEgc3RyaW5nLCBwYXJzZSBhbmQgZm9ybWF0XG4gICAgICBpZiAodHlwZW9mIHRoaXMuZmxhdHBpY2tySW5zdGFuY2Uuc2VsZWN0ZWREYXRlc1swXSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgc2luZ2xlRGF0ZSA9IHRoaXMuZmxhdHBpY2tySW5zdGFuY2UucGFyc2VEYXRlKHRoaXMuZmxhdHBpY2tySW5zdGFuY2Uuc2VsZWN0ZWREYXRlc1swXSwgdGhpcy5kYXRlRm9ybWF0KTtcbiAgICAgICAgc2luZ2xlRGF0ZSA9IHRoaXMuZmxhdHBpY2tySW5zdGFuY2UuZm9ybWF0RGF0ZShzaW5nbGVEYXRlLCB0aGlzLmRhdGVGb3JtYXQpO1xuICAgICAgICAvLyBpZiBkYXRlIGlzIG5vdCBhIHN0cmluZyB3ZSBjYW4gYXNzdW1lIGl0J3MgYSBEYXRlIGFuZCB3ZSBzaG91bGQgZm9ybWF0XG4gICAgICB9IGVsc2UgaWYgKCEhdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5zZWxlY3RlZERhdGVzWzBdKSB7XG4gICAgICAgIHNpbmdsZURhdGUgPSB0aGlzLmZsYXRwaWNrckluc3RhbmNlLmZvcm1hdERhdGUodGhpcy5mbGF0cGlja3JJbnN0YW5jZS5zZWxlY3RlZERhdGVzWzBdLCB0aGlzLmRhdGVGb3JtYXQpO1xuICAgICAgfVxuXG4gICAgICBpZiAocmFuZ2VJbnB1dCkge1xuICAgICAgICAvLyB3ZSBjYW4gZWl0aGVyIHNldCBhIGRhdGUgdmFsdWUgb3IgYW4gZW1wdHkgc3RyaW5nLCBzbyB3ZSBzdGFydCB3aXRoIGFuIGVtcHR5IHN0cmluZ1xuICAgICAgICBsZXQgcmFuZ2VEYXRlID0gJyc7XG4gICAgICAgIC8vIGlmIGRhdGUgaXMgYSBzdHJpbmcsIHBhcnNlIGFuZCBmb3JtYXRcbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNlbGVjdGVkRGF0ZXNbMV0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgcmFuZ2VEYXRlID0gdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5wYXJzZURhdGUodGhpcy5mbGF0cGlja3JJbnN0YW5jZS5zZWxlY3RlZERhdGVzWzFdLnRvU3RyaW5nKCksIHRoaXMuZGF0ZUZvcm1hdCk7XG4gICAgICAgICAgcmFuZ2VEYXRlID0gdGhpcy5mbGF0cGlja3JJbnN0YW5jZS5mb3JtYXREYXRlKHJhbmdlRGF0ZSwgdGhpcy5kYXRlRm9ybWF0KTtcbiAgICAgICAgICAvLyBpZiBkYXRlIGlzIG5vdCBhIHN0cmluZyB3ZSBjYW4gYXNzdW1lIGl0J3MgYSBEYXRlIGFuZCB3ZSBzaG91bGQgZm9ybWF0XG4gICAgICAgIH0gZWxzZSBpZiAoISF0aGlzLmZsYXRwaWNrckluc3RhbmNlLnNlbGVjdGVkRGF0ZXNbMV0pIHtcbiAgICAgICAgICByYW5nZURhdGUgPSB0aGlzLmZsYXRwaWNrckluc3RhbmNlLmZvcm1hdERhdGUodGhpcy5mbGF0cGlja3JJbnN0YW5jZS5zZWxlY3RlZERhdGVzWzFdLCB0aGlzLmRhdGVGb3JtYXQpO1xuICAgICAgICB9XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIC8vIGFwcGx5IHRoZSB2YWx1ZXNcbiAgICAgICAgICByYW5nZUlucHV0LnZhbHVlID0gcmFuZ2VEYXRlO1xuICAgICAgICAgIHNpbmdsZUlucHV0LnZhbHVlID0gc2luZ2xlRGF0ZTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGRvU2VsZWN0KHNlbGVjdGVkVmFsdWU6IChEYXRlIHwgc3RyaW5nKVtdKSB7XG4gICAgdGhpcy52YWx1ZUNoYW5nZS5lbWl0KHNlbGVjdGVkVmFsdWUpO1xuICAgIHRoaXMucHJvcGFnYXRlQ2hhbmdlKHNlbGVjdGVkVmFsdWUpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGRpZERhdGVWYWx1ZUNoYW5nZShjdXJyZW50VmFsdWUsIHByZXZpb3VzVmFsdWUpIHtcbiAgICByZXR1cm4gY3VycmVudFZhbHVlWzBdICE9PSBwcmV2aW91c1ZhbHVlWzBdIHx8IGN1cnJlbnRWYWx1ZVsxXSAhPT0gcHJldmlvdXNWYWx1ZVsxXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb3JlIGFkdmFuY2VkIGNoZWNraW5nIG9mIHRoZSBsb2FkZWQgc3RhdGUgb2YgZmxhdHBpY2tyXG4gICAqL1xuICBwcm90ZWN0ZWQgaXNGbGF0cGlja3JMb2FkZWQoKSB7XG4gICAgLy8gY2FzdCB0aGUgaW5zdGFuY2UgdG8gYSBib29sZWFuLCBhbmQgc29tZSBtZXRob2QgdGhhdCBoYXMgdG8gZXhpc3QgZm9yIHRoZSBsaWJyYXJ5IHRvIGJlIGxvYWRlZCBpbiB0aGlzIGNhc2UgYHNldERhdGVgXG4gICAgcmV0dXJuICEhdGhpcy5mbGF0cGlja3JJbnN0YW5jZSAmJiAhIXRoaXMuZmxhdHBpY2tySW5zdGFuY2Uuc2V0RGF0ZTtcbiAgfVxufVxuIl19