@hxui/angular
Version:
This README includes the steps that are necessary to import the HxUi-angular into a project or to contribute with development.
584 lines (583 loc) • 54.1 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
import { Directive, ElementRef, EventEmitter, HostListener, Input, Output, Renderer2, TemplateRef, ViewContainerRef } from '@angular/core';
import { NgControl } from '@angular/forms';
import { TypeaheadContainerComponent } from './typeahead-container.component';
import { getValueFromObject, latinize, tokenize } from './typeahead-utils';
import { Observable, from } from 'rxjs';
import { debounceTime, mergeMap, filter, toArray } from 'rxjs/operators';
import { TypeaheadMatch } from './typeahead-match.class';
import { ComponentLoaderFactory } from '../component-loader/component-loader.factory';
var TypeaheadDirective = /** @class */ (function () {
function TypeaheadDirective(control, viewContainerRef, element, renderer, cis) {
/**
* minimal no of characters that needs to be entered before typeahead kicks-in. When set to 0, typeahead shows on focus with full list of options (limited as normal by typeaheadOptionsLimit)
*/
this.typeaheadMinLength = void 0;
/**
* should be used only in case of typeahead attribute is array. If true - loading of options will be async, otherwise - sync. true make sense if options array is large.
*/
this.typeaheadAsync = void 0;
/**
* match latin symbols. If true the word súper would match super and vice versa.
*/
this.typeaheadLatinize = true;
/**
* break words with spaces. If true the text "exact phrase" here match would match with match exact phrase here but not with phrase here exact match (kind of "google style").
*/
this.typeaheadSingleWords = true;
/**
* should be used only in case typeaheadSingleWords attribute is true. Sets the word delimiter to break words. Defaults to space.
*/
this.typeaheadWordDelimiters = ' ';
/**
* should be used only in case typeaheadSingleWords attribute is true. Sets the word delimiter to match exact phrase. Defaults to simple and double quotes.
*/
this.typeaheadPhraseDelimiters = '\'"';
/**
* fired when 'busy' state of this component was changed, fired on async mode only, returns boolean
*/
this.typeaheadLoading = new EventEmitter();
/**
* fired on every key event and returns true in case of matches are not detected
*/
this.typeaheadNoResults = new EventEmitter();
/**
* fired when option was selected, return object with data of this option
*/
this.typeaheadOnSelect = new EventEmitter();
/**
* fired when blur event occurres. returns the active item
*/
this.typeaheadOnBlur = new EventEmitter();
this.isTypeaheadOptionsListActive = false;
this.keyUpEventEmitter = new EventEmitter();
this.placement = 'bottom-left';
this.element = element;
this.ngControl = control;
this.viewContainerRef = viewContainerRef;
this.renderer = renderer;
this._typeahead = cis
.createLoader(element, viewContainerRef, renderer);
}
/**
* @param {?} e
* @return {?}
*/
TypeaheadDirective.prototype.onChange = /**
* @param {?} e
* @return {?}
*/
function (e) {
if (this._container) {
// esc
if (e.keyCode === 27) {
this.hide();
return;
}
// up
if (e.keyCode === 38) {
this._container.prevActiveMatch();
return;
}
// down
if (e.keyCode === 40) {
this._container.nextActiveMatch();
return;
}
// enter
if (e.keyCode === 13) {
this._container.selectActiveMatch();
return;
}
}
// For `<input>`s, use the `value` property. For others that don't have a
// `value` (such as `<span contenteditable="true">`, use `innerText`.
var /** @type {?} */ value = e.target.value !== undefined
? e.target.value
: e.target.innerText;
if (value.trim().length >= this.typeaheadMinLength) {
this.typeaheadLoading.emit(true);
this.keyUpEventEmitter.emit(e.target.value);
}
else {
this.typeaheadLoading.emit(false);
this.typeaheadNoResults.emit(false);
this.hide();
}
};
/**
* @return {?}
*/
TypeaheadDirective.prototype.onFocus = /**
* @return {?}
*/
function () {
if (this.typeaheadMinLength === 0) {
this.typeaheadLoading.emit(true);
this.keyUpEventEmitter.emit('');
}
};
/**
* @return {?}
*/
TypeaheadDirective.prototype.onBlur = /**
* @return {?}
*/
function () {
if (this._container && !this._container.isFocused) {
this.typeaheadOnBlur.emit(this._container.active);
this.hide();
}
};
/**
* @param {?} e
* @return {?}
*/
TypeaheadDirective.prototype.onKeydown = /**
* @param {?} e
* @return {?}
*/
function (e) {
// no container - no problems
if (!this._container) {
return;
}
// if items is visible - prevent form submition
if (e.keyCode === 13) {
e.preventDefault();
return;
}
};
/**
* @return {?}
*/
TypeaheadDirective.prototype.ngOnInit = /**
* @return {?}
*/
function () {
this.typeaheadOptionsLimit = this.typeaheadOptionsLimit || 20;
this.typeaheadMinLength = this.typeaheadMinLength === void 0
? 1
: this.typeaheadMinLength;
this.typeaheadWaitMs = this.typeaheadWaitMs || 0;
// async should be false in case of array
if (this.typeaheadAsync === undefined && !(this.typeahead instanceof Observable)) {
this.typeaheadAsync = false;
}
if (this.typeahead instanceof Observable) {
this.typeaheadAsync = true;
}
if (this.typeaheadAsync) {
this.asyncActions();
}
else {
this.syncActions();
}
};
/**
* @param {?} match
* @return {?}
*/
TypeaheadDirective.prototype.changeModel = /**
* @param {?} match
* @return {?}
*/
function (match) {
var /** @type {?} */ valueStr = match.value;
this.ngControl.viewToModelUpdate(valueStr);
(/** @type {?} */ (this.ngControl.control)).setValue(valueStr);
this.hide();
};
Object.defineProperty(TypeaheadDirective.prototype, "matches", {
get: /**
* @return {?}
*/
function () {
return this._matches;
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
TypeaheadDirective.prototype.show = /**
* @return {?}
*/
function () {
this._typeahead
.attach(TypeaheadContainerComponent)
.to(this.container)
.position({ attachment: 'bottom left' })
.show({
typeaheadRef: this,
placement: this.placement,
animation: false
});
this._container = this._typeahead.instance;
this._container.parent = this;
// This improves the speed as it won't have to be done for each list item
var /** @type {?} */ normalizedQuery = (this.typeaheadLatinize
? latinize(this.ngControl.control.value)
: this.ngControl.control.value).toString()
.toLowerCase();
this._container.query = this.typeaheadSingleWords
? tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters)
: normalizedQuery;
this._container.matches = this._matches;
this.element.nativeElement.focus();
};
/**
* @return {?}
*/
TypeaheadDirective.prototype.hide = /**
* @return {?}
*/
function () {
if (this._typeahead.isShown) {
this._typeahead.hide();
this._container = null;
}
};
/**
* @return {?}
*/
TypeaheadDirective.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this._typeahead.dispose();
};
/**
* @return {?}
*/
TypeaheadDirective.prototype.asyncActions = /**
* @return {?}
*/
function () {
var _this = this;
this.keyUpEventEmitter.pipe(debounceTime(this.typeaheadWaitMs), mergeMap(function () { return _this.typeahead; })).subscribe(function (matches) {
_this.finalizeAsyncCall(matches);
}, function (err) {
console.error(err);
});
};
/**
* @return {?}
*/
TypeaheadDirective.prototype.syncActions = /**
* @return {?}
*/
function () {
var _this = this;
this.keyUpEventEmitter.pipe(debounceTime(this.typeaheadWaitMs), mergeMap(function (value) {
var /** @type {?} */ normalizedQuery = _this.normalizeQuery(value);
return from(_this.typeahead).pipe(filter(function (option) {
return option && _this.testMatch(_this.normalizeOption(option), normalizedQuery);
}), toArray());
}))
.subscribe(function (matches) {
_this.finalizeAsyncCall(matches);
}, function (err) {
console.error(err);
});
};
/**
* @param {?} option
* @return {?}
*/
TypeaheadDirective.prototype.normalizeOption = /**
* @param {?} option
* @return {?}
*/
function (option) {
var /** @type {?} */ optionValue = getValueFromObject(option, this.typeaheadOptionField);
var /** @type {?} */ normalizedOption = this.typeaheadLatinize
? latinize(optionValue)
: optionValue;
return normalizedOption.toLowerCase();
};
/**
* @param {?} value
* @return {?}
*/
TypeaheadDirective.prototype.normalizeQuery = /**
* @param {?} value
* @return {?}
*/
function (value) {
// If singleWords, break model here to not be doing extra work on each
// iteration
var /** @type {?} */ normalizedQuery = (this.typeaheadLatinize ? latinize(value) : value)
.toString()
.toLowerCase();
normalizedQuery = this.typeaheadSingleWords
? tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters)
: normalizedQuery;
return normalizedQuery;
};
/**
* @param {?} match
* @param {?} test
* @return {?}
*/
TypeaheadDirective.prototype.testMatch = /**
* @param {?} match
* @param {?} test
* @return {?}
*/
function (match, test) {
var /** @type {?} */ spaceLength;
if (typeof test === 'object') {
spaceLength = test.length;
for (var /** @type {?} */ i = 0; i < spaceLength; i += 1) {
if (test[i].length > 0 && match.indexOf(test[i]) < 0) {
return false;
}
}
return true;
}
else {
return match.indexOf(test) >= 0;
}
};
/**
* @param {?} matches
* @return {?}
*/
TypeaheadDirective.prototype.finalizeAsyncCall = /**
* @param {?} matches
* @return {?}
*/
function (matches) {
this.prepareMatches(matches);
this.typeaheadLoading.emit(false);
this.typeaheadNoResults.emit(!this.hasMatches());
if (!this.hasMatches()) {
this.hide();
return;
}
if (this._container) {
// This improves the speed as it won't have to be done for each list item
var /** @type {?} */ normalizedQuery = (this.typeaheadLatinize
? latinize(this.ngControl.control.value)
: this.ngControl.control.value).toString()
.toLowerCase();
this._container.query = this.typeaheadSingleWords
? tokenize(normalizedQuery, this.typeaheadWordDelimiters, this.typeaheadPhraseDelimiters)
: normalizedQuery;
this._container.matches = this._matches;
}
else {
this.show();
}
};
/**
* @param {?} options
* @return {?}
*/
TypeaheadDirective.prototype.prepareMatches = /**
* @param {?} options
* @return {?}
*/
function (options) {
var _this = this;
var /** @type {?} */ limited = options.slice(0, this.typeaheadOptionsLimit);
if (this.typeaheadGroupField) {
var /** @type {?} */ matches_1 = [];
// extract all group names
var /** @type {?} */ groups = limited
.map(function (option) { return getValueFromObject(option, _this.typeaheadGroupField); })
.filter(function (v, i, a) { return a.indexOf(v) === i; });
groups.forEach(function (group) {
// add group header to array of matches
// add group header to array of matches
matches_1.push(new TypeaheadMatch(group, group, true));
// add each item of group to array of matches
// add each item of group to array of matches
matches_1 = matches_1.concat(limited
.filter(function (option) { return getValueFromObject(option, _this.typeaheadGroupField) === group; })
.map(function (option) { return new TypeaheadMatch(option, getValueFromObject(option, _this.typeaheadOptionField)); }));
});
this._matches = matches_1;
}
else {
this._matches = limited.map(function (option) { return new TypeaheadMatch(option, getValueFromObject(option, _this.typeaheadOptionField)); });
}
};
/**
* @return {?}
*/
TypeaheadDirective.prototype.hasMatches = /**
* @return {?}
*/
function () {
return this._matches.length > 0;
};
TypeaheadDirective.decorators = [
{ type: Directive, args: [{ selector: '[typeahead]', exportAs: 'hx-typeahead' },] },
];
/** @nocollapse */
TypeaheadDirective.ctorParameters = function () { return [
{ type: NgControl, },
{ type: ViewContainerRef, },
{ type: ElementRef, },
{ type: Renderer2, },
{ type: ComponentLoaderFactory, },
]; };
TypeaheadDirective.propDecorators = {
"typeahead": [{ type: Input },],
"typeaheadMinLength": [{ type: Input },],
"typeaheadWaitMs": [{ type: Input },],
"typeaheadOptionsLimit": [{ type: Input },],
"typeaheadOptionField": [{ type: Input },],
"typeaheadGroupField": [{ type: Input },],
"typeaheadAsync": [{ type: Input },],
"typeaheadLatinize": [{ type: Input },],
"typeaheadSingleWords": [{ type: Input },],
"typeaheadWordDelimiters": [{ type: Input },],
"typeaheadPhraseDelimiters": [{ type: Input },],
"typeaheadItemTemplate": [{ type: Input },],
"optionsListTemplate": [{ type: Input },],
"typeaheadLoading": [{ type: Output },],
"typeaheadNoResults": [{ type: Output },],
"typeaheadOnSelect": [{ type: Output },],
"typeaheadOnBlur": [{ type: Output },],
"container": [{ type: Input },],
"onChange": [{ type: HostListener, args: ['keyup', ['$event'],] },],
"onFocus": [{ type: HostListener, args: ['focus',] },],
"onBlur": [{ type: HostListener, args: ['blur',] },],
"onKeydown": [{ type: HostListener, args: ['keydown', ['$event'],] },],
};
return TypeaheadDirective;
}());
export { TypeaheadDirective };
function TypeaheadDirective_tsickle_Closure_declarations() {
/** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */
TypeaheadDirective.decorators;
/**
* @nocollapse
* @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>}
*/
TypeaheadDirective.ctorParameters;
/** @type {!Object<string,!Array<{type: !Function, args: (undefined|!Array<?>)}>>} */
TypeaheadDirective.propDecorators;
/**
* options source, can be Array of strings, objects or an Observable for external matching process
* @type {?}
*/
TypeaheadDirective.prototype.typeahead;
/**
* minimal no of characters that needs to be entered before typeahead kicks-in. When set to 0, typeahead shows on focus with full list of options (limited as normal by typeaheadOptionsLimit)
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadMinLength;
/**
* minimal wait time after last character typed before typeahead kicks-in
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadWaitMs;
/**
* maximum length of options items list
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadOptionsLimit;
/**
* when options source is an array of objects, the name of field that contains the options value, we use array item as option in case of this field is missing. Supports nested properties and methods.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadOptionField;
/**
* when options source is an array of objects, the name of field that contains the group value, matches are grouped by this field when set.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadGroupField;
/**
* should be used only in case of typeahead attribute is array. If true - loading of options will be async, otherwise - sync. true make sense if options array is large.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadAsync;
/**
* match latin symbols. If true the word súper would match super and vice versa.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadLatinize;
/**
* break words with spaces. If true the text "exact phrase" here match would match with match exact phrase here but not with phrase here exact match (kind of "google style").
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadSingleWords;
/**
* should be used only in case typeaheadSingleWords attribute is true. Sets the word delimiter to break words. Defaults to space.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadWordDelimiters;
/**
* should be used only in case typeaheadSingleWords attribute is true. Sets the word delimiter to match exact phrase. Defaults to simple and double quotes.
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadPhraseDelimiters;
/**
* used to specify a custom item template. Template variables exposed are called item and index;
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadItemTemplate;
/**
* used to specify a custom options list template. Template variables: matches, itemTemplate, query
* @type {?}
*/
TypeaheadDirective.prototype.optionsListTemplate;
/**
* fired when 'busy' state of this component was changed, fired on async mode only, returns boolean
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadLoading;
/**
* fired on every key event and returns true in case of matches are not detected
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadNoResults;
/**
* fired when option was selected, return object with data of this option
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadOnSelect;
/**
* fired when blur event occurres. returns the active item
* @type {?}
*/
TypeaheadDirective.prototype.typeaheadOnBlur;
/**
* A selector specifying the element the typeahead should be appended to.
* Currently only supports "body".
* @type {?}
*/
TypeaheadDirective.prototype.container;
/**
* if false don't focus the input element the typeahead directive is associated with on selection
* @type {?}
*/
TypeaheadDirective.prototype._container;
/** @type {?} */
TypeaheadDirective.prototype.isTypeaheadOptionsListActive;
/** @type {?} */
TypeaheadDirective.prototype.keyUpEventEmitter;
/** @type {?} */
TypeaheadDirective.prototype._matches;
/** @type {?} */
TypeaheadDirective.prototype.placement;
/** @type {?} */
TypeaheadDirective.prototype.ngControl;
/** @type {?} */
TypeaheadDirective.prototype.viewContainerRef;
/** @type {?} */
TypeaheadDirective.prototype.element;
/** @type {?} */
TypeaheadDirective.prototype.renderer;
/** @type {?} */
TypeaheadDirective.prototype._typeahead;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZWFoZWFkLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0BoeHVpL2FuZ3VsYXIvIiwic291cmNlcyI6WyJsaWIvdHlwZWFoZWFkL3R5cGVhaGVhZC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUN4RCxNQUFNLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxnQkFBZ0IsRUFDakQsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFlLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hELE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzlFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFM0UsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDeEMsT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3pFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw4Q0FBOEMsQ0FBQzs7Z0NBcUpqRSxPQUFrQixFQUFFLGdCQUFrQyxFQUFFLE9BQW1CLEVBQUUsUUFBbUIsRUFBRSxHQUEyQjs7OztrQ0E3SW5HLEtBQUssQ0FBQzs7Ozs4QkFVVCxLQUFLLENBQUM7Ozs7aUNBRVosSUFBSTs7OztvQ0FFRCxJQUFJOzs7O3VDQUVELEdBQUc7Ozs7eUNBRUQsS0FBSzs7OztnQ0FPVSxJQUFJLFlBQVksRUFBRTs7OztrQ0FFaEIsSUFBSSxZQUFZLEVBQUU7Ozs7aUNBRVosSUFBSSxZQUFZLEVBQUU7Ozs7K0JBRS9CLElBQUksWUFBWSxFQUFF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O0tBQ2pDOztnQkFyV0YsU0FBUyxTQUFDLEVBQUMsUUFBUSxFQUFFLGFBQWEsRUFBRSxRQUFRLEVBQUUsY0FBYyxFQUFDOzs7O2dCQVZ4QyxTQUFTO2dCQUZHLGdCQUFnQjtnQkFEckMsVUFBVTtnQkFDYixTQUFTO2dCQVNWLHNCQUFzQjs7OzhCQU01QixLQUFLO3VDQUVMLEtBQUs7b0NBRUwsS0FBSzswQ0FFTCxLQUFLO3lDQUVMLEtBQUs7d0NBRUwsS0FBSzttQ0FFTCxLQUFLO3NDQUVMLEtBQUs7eUNBRUwsS0FBSzs0Q0FFTCxLQUFLOzhDQUVMLEtBQUs7MENBRUwsS0FBSzt3Q0FFTCxLQUFLO3FDQUdMLE1BQU07dUNBRU4sTUFBTTtzQ0FFTixNQUFNO29DQUVOLE1BQU07OEJBTU4sS0FBSzs2QkErQkwsWUFBWSxTQUFDLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQzs0QkEyQ2hDLFlBQVksU0FBQyxPQUFPOzJCQVFwQixZQUFZLFNBQUMsTUFBTTs4QkFRbkIsWUFBWSxTQUFDLFNBQVMsRUFBRSxDQUFDLFFBQVEsQ0FBQzs7NkJBbEpyQzs7U0FlYSxrQkFBa0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIERpcmVjdGl2ZSwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBIb3N0TGlzdGVuZXIsIElucHV0LCBPbkRlc3Ryb3ksIE9uSW5pdCxcclxuICBPdXRwdXQsIFJlbmRlcmVyMiwgVGVtcGxhdGVSZWYsIFZpZXdDb250YWluZXJSZWZcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIE5nQ29udHJvbCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgVHlwZWFoZWFkQ29udGFpbmVyQ29tcG9uZW50IH0gZnJvbSAnLi90eXBlYWhlYWQtY29udGFpbmVyLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IGdldFZhbHVlRnJvbU9iamVjdCwgbGF0aW5pemUsIHRva2VuaXplIH0gZnJvbSAnLi90eXBlYWhlYWQtdXRpbHMnO1xyXG5cclxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgZnJvbSB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUsIG1lcmdlTWFwLCBmaWx0ZXIsIHRvQXJyYXkgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7IFR5cGVhaGVhZE1hdGNoIH0gZnJvbSAnLi90eXBlYWhlYWQtbWF0Y2guY2xhc3MnO1xyXG5pbXBvcnQgeyBDb21wb25lbnRMb2FkZXJGYWN0b3J5IH0gZnJvbSAnLi4vY29tcG9uZW50LWxvYWRlci9jb21wb25lbnQtbG9hZGVyLmZhY3RvcnknO1xyXG5pbXBvcnQgeyBDb21wb25lbnRMb2FkZXIgfSBmcm9tICcuLi9jb21wb25lbnQtbG9hZGVyL2NvbXBvbmVudC1sb2FkZXIuY2xhc3MnO1xyXG5cclxuQERpcmVjdGl2ZSh7c2VsZWN0b3I6ICdbdHlwZWFoZWFkXScsIGV4cG9ydEFzOiAnaHgtdHlwZWFoZWFkJ30pXHJcbmV4cG9ydCBjbGFzcyBUeXBlYWhlYWREaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XHJcbiAgLyoqIG9wdGlvbnMgc291cmNlLCBjYW4gYmUgQXJyYXkgb2Ygc3RyaW5ncywgb2JqZWN0cyBvciBhbiBPYnNlcnZhYmxlIGZvciBleHRlcm5hbCBtYXRjaGluZyBwcm9jZXNzICovXHJcbiAgQElucHV0KCkgcHVibGljIHR5cGVhaGVhZDogYW55O1xyXG4gIC8qKiBtaW5pbWFsIG5vIG9mIGNoYXJhY3RlcnMgdGhhdCBuZWVkcyB0byBiZSBlbnRlcmVkIGJlZm9yZSB0eXBlYWhlYWQga2lja3MtaW4uIFdoZW4gc2V0IHRvIDAsIHR5cGVhaGVhZCBzaG93cyBvbiBmb2N1cyB3aXRoIGZ1bGwgbGlzdCBvZiBvcHRpb25zIChsaW1pdGVkIGFzIG5vcm1hbCBieSB0eXBlYWhlYWRPcHRpb25zTGltaXQpICovXHJcbiAgQElucHV0KCkgcHVibGljIHR5cGVhaGVhZE1pbkxlbmd0aDogbnVtYmVyID0gdm9pZCAwO1xyXG4gIC8qKiBtaW5pbWFsIHdhaXQgdGltZSBhZnRlciBsYXN0IGNoYXJhY3RlciB0eXBlZCBiZWZvcmUgdHlwZWFoZWFkIGtpY2tzLWluICovXHJcbiAgQElucHV0KCkgcHVibGljIHR5cGVhaGVhZFdhaXRNczogbnVtYmVyO1xyXG4gIC8qKiBtYXhpbXVtIGxlbmd0aCBvZiBvcHRpb25zIGl0ZW1zIGxpc3QgKi9cclxuICBASW5wdXQoKSBwdWJsaWMgdHlwZWFoZWFkT3B0aW9uc0xpbWl0OiBudW1iZXI7XHJcbiAgLyoqIHdoZW4gb3B0aW9ucyBzb3VyY2UgaXMgYW4gYXJyYXkgb2Ygb2JqZWN0cywgdGhlIG5hbWUgb2YgZmllbGQgdGhhdCBjb250YWlucyB0aGUgb3B0aW9ucyB2YWx1ZSwgd2UgdXNlIGFycmF5IGl0ZW0gYXMgb3B0aW9uIGluIGNhc2Ugb2YgdGhpcyBmaWVsZCBpcyBtaXNzaW5nLiBTdXBwb3J0cyBuZXN0ZWQgcHJvcGVydGllcyBhbmQgbWV0aG9kcy4gKi9cclxuICBASW5wdXQoKSBwdWJsaWMgdHlwZWFoZWFkT3B0aW9uRmllbGQ6IHN0cmluZztcclxuICAvKiogd2hlbiBvcHRpb25zIHNvdXJjZSBpcyBhbiBhcnJheSBvZiBvYmplY3RzLCB0aGUgbmFtZSBvZiBmaWVsZCB0aGF0IGNvbnRhaW5zIHRoZSBncm91cCB2YWx1ZSwgbWF0Y2hlcyBhcmUgZ3JvdXBlZCBieSB0aGlzIGZpZWxkIHdoZW4gc2V0LiAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRHcm91cEZpZWxkOiBzdHJpbmc7XHJcbiAgLyoqIHNob3VsZCBiZSB1c2VkIG9ubHkgaW4gY2FzZSBvZiB0eXBlYWhlYWQgYXR0cmlidXRlIGlzIGFycmF5LiBJZiB0cnVlIC0gbG9hZGluZyBvZiBvcHRpb25zIHdpbGwgYmUgYXN5bmMsIG90aGVyd2lzZSAtIHN5bmMuIHRydWUgbWFrZSBzZW5zZSBpZiBvcHRpb25zIGFycmF5IGlzIGxhcmdlLiAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRBc3luYzogYm9vbGVhbiA9IHZvaWQgMDtcclxuICAvKiogbWF0Y2ggbGF0aW4gc3ltYm9scy4gSWYgdHJ1ZSB0aGUgd29yZCBzw7pwZXIgd291bGQgbWF0Y2ggc3VwZXIgYW5kIHZpY2UgdmVyc2EuICovXHJcbiAgQElucHV0KCkgcHVibGljIHR5cGVhaGVhZExhdGluaXplID0gdHJ1ZTtcclxuICAvKiogYnJlYWsgd29yZHMgd2l0aCBzcGFjZXMuIElmIHRydWUgdGhlIHRleHQgXCJleGFjdCBwaHJhc2VcIiBoZXJlIG1hdGNoIHdvdWxkIG1hdGNoIHdpdGggbWF0Y2ggZXhhY3QgcGhyYXNlIGhlcmUgYnV0IG5vdCB3aXRoIHBocmFzZSBoZXJlIGV4YWN0IG1hdGNoIChraW5kIG9mIFwiZ29vZ2xlIHN0eWxlXCIpLiAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRTaW5nbGVXb3JkcyA9IHRydWU7XHJcbiAgLyoqIHNob3VsZCBiZSB1c2VkIG9ubHkgaW4gY2FzZSB0eXBlYWhlYWRTaW5nbGVXb3JkcyBhdHRyaWJ1dGUgaXMgdHJ1ZS4gU2V0cyB0aGUgd29yZCBkZWxpbWl0ZXIgdG8gYnJlYWsgd29yZHMuIERlZmF1bHRzIHRvIHNwYWNlLiAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRXb3JkRGVsaW1pdGVycyA9ICcgJztcclxuICAvKiogc2hvdWxkIGJlIHVzZWQgb25seSBpbiBjYXNlIHR5cGVhaGVhZFNpbmdsZVdvcmRzIGF0dHJpYnV0ZSBpcyB0cnVlLiBTZXRzIHRoZSB3b3JkIGRlbGltaXRlciB0byBtYXRjaCBleGFjdCBwaHJhc2UuIERlZmF1bHRzIHRvIHNpbXBsZSBhbmQgZG91YmxlIHF1b3Rlcy4gKi9cclxuICBASW5wdXQoKSBwdWJsaWMgdHlwZWFoZWFkUGhyYXNlRGVsaW1pdGVycyA9ICdcXCdcIic7XHJcbiAgLyoqIHVzZWQgdG8gc3BlY2lmeSBhIGN1c3RvbSBpdGVtIHRlbXBsYXRlLiBUZW1wbGF0ZSB2YXJpYWJsZXMgZXhwb3NlZCBhcmUgY2FsbGVkIGl0ZW0gYW5kIGluZGV4OyAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyB0eXBlYWhlYWRJdGVtVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgLyoqIHVzZWQgdG8gc3BlY2lmeSBhIGN1c3RvbSBvcHRpb25zIGxpc3QgdGVtcGxhdGUuIFRlbXBsYXRlIHZhcmlhYmxlczogbWF0Y2hlcywgaXRlbVRlbXBsYXRlLCBxdWVyeSAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyBvcHRpb25zTGlzdFRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG5cclxuICAvKiogZmlyZWQgd2hlbiAnYnVzeScgc3RhdGUgb2YgdGhpcyBjb21wb25lbnQgd2FzIGNoYW5nZWQsIGZpcmVkIG9uIGFzeW5jIG1vZGUgb25seSwgcmV0dXJucyBib29sZWFuICovXHJcbiAgQE91dHB1dCgpIHB1YmxpYyB0eXBlYWhlYWRMb2FkaW5nOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcbiAgLyoqIGZpcmVkIG9uIGV2ZXJ5IGtleSBldmVudCBhbmQgcmV0dXJucyB0cnVlIGluIGNhc2Ugb2YgbWF0Y2hlcyBhcmUgbm90IGRldGVjdGVkICovXHJcbiAgQE91dHB1dCgpIHB1YmxpYyB0eXBlYWhlYWROb1Jlc3VsdHM6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcclxuICAvKiogZmlyZWQgd2hlbiBvcHRpb24gd2FzIHNlbGVjdGVkLCByZXR1cm4gb2JqZWN0IHdpdGggZGF0YSBvZiB0aGlzIG9wdGlvbiAqL1xyXG4gIEBPdXRwdXQoKSBwdWJsaWMgdHlwZWFoZWFkT25TZWxlY3Q6IEV2ZW50RW1pdHRlcjxUeXBlYWhlYWRNYXRjaD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcbiAgLyoqIGZpcmVkIHdoZW4gYmx1ciBldmVudCBvY2N1cnJlcy4gcmV0dXJucyB0aGUgYWN0aXZlIGl0ZW0gKi9cclxuICBAT3V0cHV0KCkgcHVibGljIHR5cGVhaGVhZE9uQmx1cjogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEEgc2VsZWN0b3Igc3BlY2lmeWluZyB0aGUgZWxlbWVudCB0aGUgdHlwZWFoZWFkIHNob3VsZCBiZSBhcHBlbmRlZCB0by5cclxuICAgKiBDdXJyZW50bHkgb25seSBzdXBwb3J0cyBcImJvZHlcIi5cclxuICAgKi9cclxuICBASW5wdXQoKSBwdWJsaWMgY29udGFpbmVyOiBzdHJpbmc7XHJcblxyXG4gIC8vIG5vdCB5ZXQgaW1wbGVtZW50ZWRcclxuICAvKiogaWYgZmFsc2UgcmVzdHJpY3QgbW9kZWwgdmFsdWVzIHRvIHRoZSBvbmVzIHNlbGVjdGVkIGZyb20gdGhlIHBvcHVwIG9ubHkgd2lsbCBiZSBwcm92aWRlZCAqL1xyXG4gIC8vIEBJbnB1dCgpIHByb3RlY3RlZCB0eXBlYWhlYWRFZGl0YWJsZTpib29sZWFuO1xyXG4gIC8qKiBpZiBmYWxzZSB0aGUgZmlyc3QgbWF0Y2ggYXV0b21hdGljYWxseSB3aWxsIG5vdCBiZSBmb2N1c2VkIGFzIHlvdSB0eXBlICovXHJcbiAgLy8gQElucHV0KCkgcHJvdGVjdGVkIHR5cGVhaGVhZEZvY3VzRmlyc3Q6Ym9vbGVhbjtcclxuICAvKiogZm9ybWF0IHRoZSBuZy1tb2RlbCByZXN1bHQgYWZ0ZXIgc2VsZWN0aW9uICovXHJcbiAgLy8gQElucHV0KCkgcHJvdGVjdGVkIHR5cGVhaGVhZElucHV0Rm9ybWF0dGVyOmFueTtcclxuICAvKiogaWYgdHJ1ZSBhdXRvbWF0aWNhbGx5IHNlbGVjdCBhbiBpdGVtIHdoZW4gdGhlcmUgaXMgb25lIG9wdGlvbiB0aGF0IGV4YWN0bHkgbWF0Y2hlcyB0aGUgdXNlciBpbnB1dCAqL1xyXG4gIC8vIEBJbnB1dCgpIHByb3RlY3RlZCB0eXBlYWhlYWRTZWxlY3RPbkV4YWN0OmJvb2xlYW47XHJcbiAgLyoqICBpZiB0cnVlIHNlbGVjdCB0aGUgY3VycmVudGx5IGhpZ2hsaWdodGVkIG1hdGNoIG9uIGJsdXIgKi9cclxuICAvLyBASW5wdXQoKSBwcm90ZWN0ZWQgdHlwZWFoZWFkU2VsZWN0T25CbHVyOmJvb2xlYW47XHJcbiAgLyoqICBpZiBmYWxzZSBkb24ndCBmb2N1cyB0aGUgaW5wdXQgZWxlbWVudCB0aGUgdHlwZWFoZWFkIGRpcmVjdGl2ZSBpcyBhc3NvY2lhdGVkIHdpdGggb24gc2VsZWN0aW9uICovXHJcbiAgICAvLyBASW5wdXQoKSBwcm90ZWN0ZWQgdHlwZWFoZWFkRm9jdXNPblNlbGVjdDpib29sZWFuO1xyXG5cclxuICBwdWJsaWMgX2NvbnRhaW5lcjogVHlwZWFoZWFkQ29udGFpbmVyQ29tcG9uZW50O1xyXG4gIHB1YmxpYyBpc1R5cGVhaGVhZE9wdGlvbnNMaXN0QWN0aXZlID0gZmFsc2U7XHJcblxyXG4gIHByb3RlY3RlZCBrZXlVcEV2ZW50RW1pdHRlcjogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XHJcbiAgcHJvdGVjdGVkIF9tYXRjaGVzOiBUeXBlYWhlYWRNYXRjaFtdO1xyXG4gIHByb3RlY3RlZCBwbGFjZW1lbnQgPSAnYm90dG9tLWxlZnQnO1xyXG4gIC8vIHByb3RlY3RlZCBwb3B1cDpDb21wb25lbnRSZWY8VHlwZWFoZWFkQ29udGFpbmVyQ29tcG9uZW50PjtcclxuXHJcbiAgcHJvdGVjdGVkIG5nQ29udHJvbDogTmdDb250cm9sO1xyXG4gIHByb3RlY3RlZCB2aWV3Q29udGFpbmVyUmVmOiBWaWV3Q29udGFpbmVyUmVmO1xyXG4gIHByb3RlY3RlZCBlbGVtZW50OiBFbGVtZW50UmVmO1xyXG4gIHByb3RlY3RlZCByZW5kZXJlcjogUmVuZGVyZXIyO1xyXG5cclxuICBwcml2YXRlIF90eXBlYWhlYWQ6IENvbXBvbmVudExvYWRlcjxUeXBlYWhlYWRDb250YWluZXJDb21wb25lbnQ+O1xyXG5cclxuICBASG9zdExpc3RlbmVyKCdrZXl1cCcsIFsnJGV2ZW50J10pXHJcbiAgcHVibGljIG9uQ2hhbmdlKGU6IGFueSk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuX2NvbnRhaW5lcikge1xyXG4gICAgICAvLyBlc2NcclxuICAgICAgaWYgKGUua2V5Q29kZSA9PT0gMjcpIHtcclxuICAgICAgICB0aGlzLmhpZGUoKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIHVwXHJcbiAgICAgIGlmIChlLmtleUNvZGUgPT09IDM4KSB7XHJcbiAgICAgICAgdGhpcy5fY29udGFpbmVyLnByZXZBY3RpdmVNYXRjaCgpO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gZG93blxyXG4gICAgICBpZiAoZS5rZXlDb2RlID09PSA0MCkge1xyXG4gICAgICAgIHRoaXMuX2NvbnRhaW5lci5uZXh0QWN0aXZlTWF0Y2goKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIGVudGVyXHJcbiAgICAgIGlmIChlLmtleUNvZGUgPT09IDEzKSB7XHJcbiAgICAgICAgdGhpcy5fY29udGFpbmVyLnNlbGVjdEFjdGl2ZU1hdGNoKCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRm9yIGA8aW5wdXQ+YHMsIHVzZSB0aGUgYHZhbHVlYCBwcm9wZXJ0eS4gRm9yIG90aGVycyB0aGF0IGRvbid0IGhhdmUgYVxyXG4gICAgLy8gYHZhbHVlYCAoc3VjaCBhcyBgPHNwYW4gY29udGVudGVkaXRhYmxlPVwidHJ1ZVwiPmAsIHVzZSBgaW5uZXJUZXh0YC5cclxuICAgIGNvbnN0IHZhbHVlID0gZS50YXJnZXQudmFsdWUgIT09IHVuZGVmaW5lZFxyXG4gICAgICA/IGUudGFyZ2V0LnZhbHVlXHJcbiAgICAgIDogZS50YXJnZXQuaW5uZXJUZXh0O1xyXG4gICAgaWYgKHZhbHVlLnRyaW0oKS5sZW5ndGggPj0gdGhpcy50eXBlYWhlYWRNaW5MZW5ndGgpIHtcclxuICAgICAgdGhpcy50eXBlYWhlYWRMb2FkaW5nLmVtaXQodHJ1ZSk7XHJcbiAgICAgIHRoaXMua2V5VXBFdmVudEVtaXR0ZXIuZW1pdChlLnRhcmdldC52YWx1ZSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnR5cGVhaGVhZExvYWRpbmcuZW1pdChmYWxzZSk7XHJcbiAgICAgIHRoaXMudHlwZWFoZWFkTm9SZXN1bHRzLmVtaXQoZmFsc2UpO1xyXG4gICAgICB0aGlzLmhpZGUoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIEBIb3N0TGlzdGVuZXIoJ2ZvY3VzJylcclxuICBwdWJsaWMgb25Gb2N1cygpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnR5cGVhaGVhZE1pbkxlbmd0aCA9PT0gMCkge1xyXG4gICAgICB0aGlzLnR5cGVhaGVhZExvYWRpbmcuZW1pdCh0cnVlKTtcclxuICAgICAgdGhpcy5rZXlVcEV2ZW50RW1pdHRlci5lbWl0KCcnKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIEBIb3N0TGlzdGVuZXIoJ2JsdXInKVxyXG4gIHB1YmxpYyBvbkJsdXIoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5fY29udGFpbmVyICYmICF0aGlzLl9jb250YWluZXIuaXNGb2N1c2VkKSB7XHJcbiAgICAgIHRoaXMudHlwZWFoZWFkT25CbHVyLmVtaXQodGhpcy5fY29udGFpbmVyLmFjdGl2ZSk7XHJcbiAgICAgIHRoaXMuaGlkZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcigna2V5ZG93bicsIFsnJGV2ZW50J10pXHJcbiAgcHVibGljIG9uS2V5ZG93bihlOiBhbnkpOiB2b2lkIHtcclxuICAgIC8vIG5vIGNvbnRhaW5lciAtIG5vIHByb2JsZW1zXHJcbiAgICBpZiAoIXRoaXMuX2NvbnRhaW5lcikge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gaWYgaXRlbXMgaXMgdmlzaWJsZSAtIHByZXZlbnQgZm9ybSBzdWJtaXRpb25cclxuICAgIGlmIChlLmtleUNvZGUgPT09IDEzKSB7XHJcbiAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHVibGljIGNvbnN0cnVjdG9yKGNvbnRyb2w6IE5nQ29udHJvbCwgdmlld0NvbnRhaW5lclJlZjogVmlld0NvbnRhaW5lclJlZiwgZWxlbWVudDogRWxlbWVudFJlZiwgcmVuZGVyZXI6IFJlbmRlcmVyMiwgY2lzOiBDb21wb25lbnRMb2FkZXJGYWN0b3J5KSB7XHJcbiAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xyXG4gICAgdGhpcy5uZ0NvbnRyb2wgPSBjb250cm9sO1xyXG4gICAgdGhpcy52aWV3Q29udGFpbmVyUmVmID0gdmlld0NvbnRhaW5lclJlZjtcclxuICAgIHRoaXMucmVuZGVyZXIgPSByZW5kZXJlcjtcclxuICAgIHRoaXMuX3R5cGVhaGVhZCA9IGNpc1xyXG4gICAgICAuY3JlYXRlTG9hZGVyPFR5cGVhaGVhZENvbnRhaW5lckNvbXBvbmVudD4oZWxlbWVudCwgdmlld0NvbnRhaW5lclJlZiwgcmVuZGVyZXIpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy50eXBlYWhlYWRPcHRpb25zTGltaXQgPSB0aGlzLnR5cGVhaGVhZE9wdGlvbnNMaW1pdCB8fCAyMDtcclxuICAgIHRoaXMudHlwZWFoZWFkTWluTGVuZ3RoID0gdGhpcy50eXBlYWhlYWRNaW5MZW5ndGggPT09IHZvaWQgMFxyXG4gICAgICA/IDFcclxuICAgICAgOiB0aGlzLnR5cGVhaGVhZE1pbkxlbmd0aDtcclxuICAgIHRoaXMudHlwZWFoZWFkV2FpdE1zID0gdGhpcy50eXBlYWhlYWRXYWl0TXMgfHwgMDtcclxuXHJcbiAgICAvLyBhc3luYyBzaG91bGQgYmUgZmFsc2UgaW4gY2FzZSBvZiBhcnJheVxyXG4gICAgaWYgKHRoaXMudHlwZWFoZWFkQXN5bmMgPT09IHVuZGVmaW5lZCAmJiAhKHRoaXMudHlwZWFoZWFkIGluc3RhbmNlb2YgT2JzZXJ2YWJsZSkpIHtcclxuICAgICAgdGhpcy50eXBlYWhlYWRBc3luYyA9IGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLnR5cGVhaGVhZCBpbnN0YW5jZW9mIE9ic2VydmFibGUpIHtcclxuICAgICAgdGhpcy50eXBlYWhlYWRBc3luYyA9IHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMudHlwZWFoZWFkQXN5bmMpIHtcclxuICAgICAgdGhpcy5hc3luY0FjdGlvbnMoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuc3luY0FjdGlvbnMoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyBjaGFuZ2VNb2RlbChtYXRjaDogVHlwZWFoZWFkTWF0Y2gpOiB2b2lkIHtcclxuICAgIGNvbnN0IHZhbHVlU3RyOiBzdHJpbmcgPSBtYXRjaC52YWx1ZTtcclxuICAgIHRoaXMubmdDb250cm9sLnZpZXdUb01vZGVsVXBkYXRlKHZhbHVlU3RyKTtcclxuICAgICh0aGlzLm5nQ29udHJvbC5jb250cm9sIGFzIEZvcm1Db250cm9sKS5zZXRWYWx1ZSh2YWx1ZVN0cik7XHJcbiAgICB0aGlzLmhpZGUoKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBnZXQgbWF0Y2hlcygpOiBhbnlbXSB7XHJcbiAgICByZXR1cm4gdGhpcy5fbWF0Y2hlcztcclxuICB9XHJcblxyXG4gIHB1YmxpYyBzaG93KCk6IHZvaWQge1xyXG4gICAgdGhpcy5fdHlwZWFoZWFkXHJcbiAgICAgIC5hdHRhY2goVHlwZWFoZWFkQ29udGFpbmVyQ29tcG9uZW50KVxyXG4gICAgICAvLyB0b2RvOiBhZGQgYXBwZW5kIHRvIGJvZHksIGFmdGVyIHVwZGF0aW5nIHBvc2l0aW9uaW5nIHNlcnZpY2VcclxuICAgICAgLnRvKHRoaXMuY29udGFpbmVyKVxyXG4gICAgICAucG9zaXRpb24oe2F0dGFjaG1lbnQ6ICdib3R0b20gbGVmdCd9KVxyXG4gICAgICAuc2hvdyh7XHJcbiAgICAgICAgdHlwZWFoZWFkUmVmOiB0aGlzLFxyXG4gICAgICAgIHBsYWNlbWVudDogdGhpcy5wbGFjZW1lbnQsXHJcbiAgICAgICAgYW5pbWF0aW9uOiBmYWxzZVxyXG4gICAgICB9KTtcclxuXHJcbiAgICB0aGlzLl9jb250YWluZXIgPSB0aGlzLl90eXBlYWhlYWQuaW5zdGFuY2U7XHJcbiAgICB0aGlzLl9jb250YWluZXIucGFyZW50ID0gdGhpcztcclxuICAgIC8vIFRoaXMgaW1wcm92ZXMgdGhlIHNwZWVkIGFzIGl0IHdvbid0IGhhdmUgdG8gYmUgZG9uZSBmb3IgZWFjaCBsaXN0IGl0ZW1cclxuICAgIGNvbnN0IG5vcm1hbGl6ZWRRdWVyeSA9ICh0aGlzLnR5cGVhaGVhZExhdGluaXplXHJcbiAgICAgID8gbGF0aW5pemUodGhpcy5uZ0NvbnRyb2wuY29udHJvbC52YWx1ZSlcclxuICAgICAgOiB0aGlzLm5nQ29udHJvbC5jb250cm9sLnZhbHVlKS50b1N0cmluZygpXHJcbiAgICAgIC50b0xvd2VyQ2FzZSgpO1xyXG4gICAgdGhpcy5fY29udGFpbmVyLnF1ZXJ5ID0gdGhpcy50eXBlYWhlYWRTaW5nbGVXb3Jkc1xyXG4gICAgICA/IHRva2VuaXplKG5vcm1hbGl6ZWRRdWVyeSwgdGhpcy50eXBlYWhlYWRXb3JkRGVsaW1pdGVycywgdGhpcy50eXBlYWhlYWRQaHJhc2VEZWxpbWl0ZXJzKVxyXG4gICAgICA6IG5vcm1hbGl6ZWRRdWVyeTtcclxuICAgIHRoaXMuX2NvbnRhaW5lci5tYXRjaGVzID0gdGhpcy5fbWF0Y2hlcztcclxuICAgIHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgaGlkZSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLl90eXBlYWhlYWQuaXNTaG93bikge1xyXG4gICAgICB0aGlzLl90eXBlYWhlYWQuaGlkZSgpO1xyXG4gICAgICB0aGlzLl9jb250YWluZXIgPSBudWxsO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHVibGljIG5nT25EZXN0cm95KCk6IGFueSB7XHJcbiAgICB0aGlzLl90eXBlYWhlYWQuZGlzcG9zZSgpO1xyXG4gIH1cclxuXHJcbiAgcHJvdGVjdGVkIGFzeW5jQWN0aW9ucygpOiB2b2lkIHtcclxuICAgIHRoaXMua2V5VXBFdmVudEVtaXR0ZXIucGlwZShcclxuICAgICAgZGVib3VuY2VUaW1lKHRoaXMudHlwZWFoZWFkV2FpdE1zKSxcclxuICAgICAgbWVyZ2VNYXAoKCkgPT4gdGhpcy50eXBlYWhlYWQpXHJcbiAgICApLnN1YnNjcmliZShcclxuICAgICAgICAobWF0Y2hlczogYW55W10pID0+IHtcclxuICAgICAgICAgIHRoaXMuZmluYWxpemVBc3luY0NhbGwobWF0Y2hlcyk7XHJcbiAgICAgICAgfSxcclxuICAgICAgICAoZXJyOiBhbnkpID0+IHtcclxuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcclxuICAgICAgICB9XHJcbiAgICAgICk7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgc3luY0FjdGlvbnMoKTogdm9pZCB7XHJcbiAgICB0aGlzLmtleVVwRXZlbnRFbWl0dGVyLnBpcGUoXHJcbiAgICAgIGRlYm91bmNlVGltZSh0aGlzLnR5cGVhaGVhZFdhaXRNcyksXHJcbiAgICAgIG1lcmdlTWFwKCh2YWx1ZTogc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFF1ZXJ5ID0gdGhpcy5ub3JtYWxpemVRdWVyeSh2YWx1ZSk7XHJcblxyXG4gICAgICAgIHJldHVybiBmcm9tKHRoaXMudHlwZWFoZWFkKS5waXBlKFxyXG4gICAgICAgICAgZmlsdGVyKChvcHRpb246IGFueSkgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gb3B0aW9uICYmIHRoaXMudGVzdE1hdGNoKHRoaXMubm9ybWFsaXplT3B0aW9uKG9wdGlvbiksIG5vcm1hbGl6ZWRRdWVyeSk7XHJcbiAgICAgICAgICB9KSxcclxuICAgICAgICAgIHRvQXJyYXkoKVxyXG4gICAgICAgICk7XHJcbiAgICAgIH0pKVxyXG4gICAgICAuc3Vic2NyaWJlKFxyXG4gICAgICAgIChtYXRjaGVzOiBhbnlbXSkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5maW5hbGl6ZUFzeW5jQ2FsbChtYXRjaGVzKTtcclxuICAgICAgICB9LFxyXG4gICAgICAgIChlcnI6IGFueSkgPT4ge1xyXG4gICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xyXG4gICAgICAgIH1cclxuICAgICAgKTtcclxuICB9XHJcblxyXG4gIHByb3RlY3RlZCBub3JtYWxpemVPcHRpb24ob3B0aW9uOiBhbnkpOiBhbnkge1xyXG4gICAgY29uc3Qgb3B0aW9uVmFsdWU6IHN0cmluZyA9IGdldFZhbHVlRnJvbU9iamVjdChvcHRpb24sIHRoaXMudHlwZWFoZWFkT3B0aW9uRmllbGQpO1xyXG4gICAgY29uc3Qgbm9ybWFsaXplZE9wdGlvbiA9IHRoaXMudHlwZWFoZWFkTGF0aW5pemVcclxuICAgICAgPyBsYXRpbml6ZShvcHRpb25WYWx1ZSlcclxuICAgICAgOiBvcHRpb25WYWx1ZTtcclxuXHJcbiAgICByZXR1cm4gbm9ybWFsaXplZE9wdGlvbi50b0xvd2VyQ2FzZSgpO1xyXG4gIH1cclxuXHJcbiAgcHJvdGV