UNPKG

theme-lib

Version:

This is a simple example Angular Library published to npm.

779 lines 49.4 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /* * @license * Copyright Akveo. All Rights Reserved. * Licensed under the MIT License. See License.txt in the project root for license information. */ import { Directive, ElementRef, forwardRef, Inject, InjectionToken, Input } from '@angular/core'; import { NG_VALIDATORS, NG_VALUE_ACCESSOR, Validators, } from '@angular/forms'; import { fromEvent, merge } from 'rxjs'; import { map, takeWhile, filter, take } from 'rxjs/operators'; import { NB_DOCUMENT } from '../../theme.options'; import { NbDateService } from '../calendar-kit'; /* * The `NbDatepickerAdapter` instances provide way how to parse, format and validate * different date types. * */ /** * @abstract * @template D */ var /* * The `NbDatepickerAdapter` instances provide way how to parse, format and validate * different date types. * */ /** * @abstract * @template D */ NbDatepickerAdapter = /** @class */ (function () { function NbDatepickerAdapter() { } return NbDatepickerAdapter; }()); /* * The `NbDatepickerAdapter` instances provide way how to parse, format and validate * different date types. * */ /** * @abstract * @template D */ export { NbDatepickerAdapter }; if (false) { /** @type {?} */ NbDatepickerAdapter.prototype.picker; /** * @abstract * @param {?} value * @param {?} format * @return {?} */ NbDatepickerAdapter.prototype.parse = function (value, format) { }; /** * @abstract * @param {?} value * @param {?} format * @return {?} */ NbDatepickerAdapter.prototype.format = function (value, format) { }; /** * @abstract * @param {?} value * @param {?} format * @return {?} */ NbDatepickerAdapter.prototype.isValid = function (value, format) { }; } /** * @record * @template D */ export function NbPickerValidatorConfig() { } if (false) { /** @type {?} */ NbPickerValidatorConfig.prototype.min; /** @type {?} */ NbPickerValidatorConfig.prototype.max; /** @type {?} */ NbPickerValidatorConfig.prototype.filter; } /* * Datepicker is an control that can pick any values anyway. * It has to be bound to the datepicker directive through nbDatepicker input. * */ /** * @abstract * @template T */ var /* * Datepicker is an control that can pick any values anyway. * It has to be bound to the datepicker directive through nbDatepicker input. * */ /** * @abstract * @template T */ NbDatepicker = /** @class */ (function () { function NbDatepicker() { } return NbDatepicker; }()); /* * Datepicker is an control that can pick any values anyway. * It has to be bound to the datepicker directive through nbDatepicker input. * */ /** * @abstract * @template T */ export { NbDatepicker }; if (false) { /** @type {?} */ NbDatepicker.prototype.format; /** * @abstract * @return {?} */ NbDatepicker.prototype.value = function () { }; /** * @abstract * @param {?} value * @return {?} */ NbDatepicker.prototype.value = function (value) { }; /** * @abstract * @return {?} */ NbDatepicker.prototype.valueChange = function () { }; /** * @abstract * @param {?} hostRef * @return {?} */ NbDatepicker.prototype.attach = function (hostRef) { }; /** * @abstract * @return {?} */ NbDatepicker.prototype.getValidatorConfig = function () { }; /** * @abstract * @return {?} */ NbDatepicker.prototype.show = function () { }; /** * @abstract * @return {?} */ NbDatepicker.prototype.hide = function () { }; /** * @abstract * @return {?} */ NbDatepicker.prototype.shouldHide = function () { }; /** * @abstract * @return {?} */ NbDatepicker.prototype.isShown = function () { }; /** * @abstract * @return {?} */ NbDatepicker.prototype.blur = function () { }; } /** @type {?} */ export var NB_DATE_ADAPTER = new InjectionToken('Datepicker Adapter'); /* * The `NbDatepickerDirective` is form control that gives you ability to select dates and ranges. The datepicker * is shown when input receives a `focus` event. * * ```html * <input [nbDatepicker]="datepicker"> * <nb-datepicker #datepicker></nb-datepicker> * ``` * * @stacked-example(Showcase, datepicker/datepicker-showcase.component) * * ### Installation * * Import `NbDatepickerModule.forRoot()` to your root module. * ```ts * @NgModule({ * imports: [ * // ... * NbDatepickerModule.forRoot(), * ], * }) * export class AppModule { } * ``` * And `NbDatepickerModule` to your feature module. * ```ts * @NgModule({ * imports: [ * // ... * NbDatepickerModule, * ], * }) * export class PageModule { } * ``` * ### Usage * * If you want to use range selection, you have to use `NbRangepickerComponent` instead: * * ```html * <input [nbDatepicker]="rangepicker"> * <nb-rangepicker #rangepicker></nb-rangepicker> * ``` * * Both range and date pickers support all parameters as calendar, so, check `NbCalendarComponent` for additional * info. * * @stacked-example(Range showcase, datepicker/rangepicker-showcase.component) * * Datepicker is the form control so it can be bound with angular forms through ngModel and form controls. * * @stacked-example(Forms, datepicker/datepicker-forms.component) * * `NbDatepickerDirective` may be validated using `min` and `max` dates passed to the datepicker. * And `filter` predicate that receives date object and has to return a boolean value. * * @stacked-example(Validation, datepicker/datepicker-validation.component) * * The `NbDatepickerComponent` supports date formatting: * * ```html * <input [nbDatepicker]="datepicker"> * <nb-datepicker #datepicker format="MM\dd\yyyy"></nb-datepicker> * ``` * * ## Formatting Issue * * By default, datepicker uses angulars `LOCALE_ID` token for localization and `DatePipe` for dates formatting. * And native `Date.parse(...)` for dates parsing. But native `Date.parse` function doesn't support formats. * To provide custom formatting you have to use one of the following packages: * * - `@nebular/moment` - provides moment date adapter that uses moment for date objects. This means datepicker than * will operate only moment date objects. If you want to use it you have to install it: `npm i @nebular/moment`, and * import `NbMomentDateModule` from this package. * * - `@nebular/date-fns` - adapter for popular date-fns library. This way is preferred if you need only date formatting. * Because date-fns is treeshakable, tiny and operates native date objects. If you want to use it you have to * install it: `npm i @nebular/date-fns`, and import `NbDateFnsDateModule` from this package. * * @styles * * datepicker-fg * datepicker-bg * datepicker-border * datepicker-border-radius * datepicker-shadow * datepicker-arrow-size * */ /** * @template D */ var NbDatepickerDirective = /** @class */ (function () { function NbDatepickerDirective(document, datepickerAdapters, hostRef, dateService) { var _this = this; this.document = document; this.datepickerAdapters = datepickerAdapters; this.hostRef = hostRef; this.dateService = dateService; this.alive = true; this.onChange = function () { }; this.onTouched = function () { }; /* * Form control validators will be called in validators context, so, we need to bind them. * */ this.validator = Validators.compose([ this.parseValidator, this.minValidator, this.maxValidator, this.filterValidator, ].map(function (fn) { return fn.bind(_this); })); this.subscribeOnInputChange(); } Object.defineProperty(NbDatepickerDirective.prototype, "setPicker", { /* * Provides datepicker component. * */ set: /* * Provides datepicker component. * */ /** * @param {?} picker * @return {?} */ function (picker) { this.picker = picker; this.setupPicker(); }, enumerable: true, configurable: true }); Object.defineProperty(NbDatepickerDirective.prototype, "input", { /* * Returns html input element. * */ get: /* * Returns html input element. * */ /** * @return {?} */ function () { return this.hostRef.nativeElement; }, enumerable: true, configurable: true }); Object.defineProperty(NbDatepickerDirective.prototype, "inputValue", { /* * Returns host input value. * */ get: /* * Returns host input value. * */ /** * @return {?} */ function () { return this.input.value; }, enumerable: true, configurable: true }); /** * @return {?} */ NbDatepickerDirective.prototype.ngOnDestroy = /** * @return {?} */ function () { this.alive = false; }; /* * Writes value in picker and html input element. * */ /* * Writes value in picker and html input element. * */ /** * @param {?} value * @return {?} */ NbDatepickerDirective.prototype.writeValue = /* * Writes value in picker and html input element. * */ /** * @param {?} value * @return {?} */ function (value) { this.writePicker(value); this.writeInput(value); }; /** * @param {?} fn * @return {?} */ NbDatepickerDirective.prototype.registerOnChange = /** * @param {?} fn * @return {?} */ function (fn) { this.onChange = fn; }; /** * @param {?} fn * @return {?} */ NbDatepickerDirective.prototype.registerOnTouched = /** * @param {?} fn * @return {?} */ function (fn) { this.onTouched = fn; }; /** * @param {?} isDisabled * @return {?} */ NbDatepickerDirective.prototype.setDisabledState = /** * @param {?} isDisabled * @return {?} */ function (isDisabled) { this.input.disabled = isDisabled; }; /* * Form control validation based on picker validator config. * */ /* * Form control validation based on picker validator config. * */ /** * @return {?} */ NbDatepickerDirective.prototype.validate = /* * Form control validation based on picker validator config. * */ /** * @return {?} */ function () { return this.validator(null); }; /* * Hides picker, focuses the input */ /* * Hides picker, focuses the input */ /** * @protected * @return {?} */ NbDatepickerDirective.prototype.hidePicker = /* * Hides picker, focuses the input */ /** * @protected * @return {?} */ function () { this.input.focus(); this.picker.hide(); }; /* * Validates that we can parse value correctly. * */ /* * Validates that we can parse value correctly. * */ /** * @protected * @return {?} */ NbDatepickerDirective.prototype.parseValidator = /* * Validates that we can parse value correctly. * */ /** * @protected * @return {?} */ function () { /** @type {?} */ var isValid = this.datepickerAdapter.isValid(this.inputValue, this.picker.format); return isValid ? null : { nbDatepickerParse: { value: this.inputValue } }; }; /* * Validates passed value is greater than min. * */ /* * Validates passed value is greater than min. * */ /** * @protected * @return {?} */ NbDatepickerDirective.prototype.minValidator = /* * Validates passed value is greater than min. * */ /** * @protected * @return {?} */ function () { /** @type {?} */ var config = this.picker.getValidatorConfig(); /** @type {?} */ var date = this.datepickerAdapter.parse(this.inputValue, this.picker.format); return (!config.min || !date || this.dateService.compareDates(config.min, date) <= 0) ? null : { nbDatepickerMin: { min: config.min, actual: date } }; }; /* * Validates passed value is smaller than max. * */ /* * Validates passed value is smaller than max. * */ /** * @protected * @return {?} */ NbDatepickerDirective.prototype.maxValidator = /* * Validates passed value is smaller than max. * */ /** * @protected * @return {?} */ function () { /** @type {?} */ var config = this.picker.getValidatorConfig(); /** @type {?} */ var date = this.datepickerAdapter.parse(this.inputValue, this.picker.format); return (!config.max || !date || this.dateService.compareDates(config.max, date) >= 0) ? null : { nbDatepickerMax: { max: config.max, actual: date } }; }; /* * Validates passed value satisfy the filter. * */ /* * Validates passed value satisfy the filter. * */ /** * @protected * @return {?} */ NbDatepickerDirective.prototype.filterValidator = /* * Validates passed value satisfy the filter. * */ /** * @protected * @return {?} */ function () { /** @type {?} */ var config = this.picker.getValidatorConfig(); /** @type {?} */ var date = this.datepickerAdapter.parse(this.inputValue, this.picker.format); return (!config.filter || !date || config.filter(date)) ? null : { nbDatepickerFilter: true }; }; /* * Chooses datepicker adapter based on passed picker component. * */ /* * Chooses datepicker adapter based on passed picker component. * */ /** * @protected * @return {?} */ NbDatepickerDirective.prototype.chooseDatepickerAdapter = /* * Chooses datepicker adapter based on passed picker component. * */ /** * @protected * @return {?} */ function () { var _this = this; this.datepickerAdapter = this.datepickerAdapters.find(function (_a) { var picker = _a.picker; return _this.picker instanceof picker; }); if (this.noDatepickerAdapterProvided()) { throw new Error('No datepickerAdapter provided for picker'); } }; /* * Attaches picker to the host input element and subscribes on value changes. * */ /* * Attaches picker to the host input element and subscribes on value changes. * */ /** * @protected * @return {?} */ NbDatepickerDirective.prototype.setupPicker = /* * Attaches picker to the host input element and subscribes on value changes. * */ /** * @protected * @return {?} */ function () { var _this = this; this.chooseDatepickerAdapter(); this.picker.attach(this.hostRef); if (this.hostRef.nativeElement.value) { this.picker.value = this.datepickerAdapter.parse(this.hostRef.nativeElement.value, this.picker.format); } this.picker.valueChange .pipe(takeWhile(function () { return _this.alive; })) .subscribe(function (value) { _this.writePicker(value); _this.writeInput(value); _this.onChange(value); if (_this.picker.shouldHide()) { _this.hidePicker(); } }); merge(this.picker.blur, fromEvent(this.input, 'blur').pipe(filter(function () { return !_this.picker.isShown && _this.document.activeElement !== _this.input; }))).pipe(takeWhile(function () { return _this.alive; }), take(1)).subscribe(function () { return _this.onTouched(); }); }; /** * @protected * @param {?} value * @return {?} */ NbDatepickerDirective.prototype.writePicker = /** * @protected * @param {?} value * @return {?} */ function (value) { this.picker.value = value; }; /** * @protected * @param {?} value * @return {?} */ NbDatepickerDirective.prototype.writeInput = /** * @protected * @param {?} value * @return {?} */ function (value) { /** @type {?} */ var stringRepresentation = this.datepickerAdapter.format(value, this.picker.format); this.hostRef.nativeElement.value = stringRepresentation; }; /* * Validates if no datepicker adapter provided. * */ /* * Validates if no datepicker adapter provided. * */ /** * @protected * @return {?} */ NbDatepickerDirective.prototype.noDatepickerAdapterProvided = /* * Validates if no datepicker adapter provided. * */ /** * @protected * @return {?} */ function () { return !this.datepickerAdapter || !(this.datepickerAdapter instanceof NbDatepickerAdapter); }; /** * @protected * @return {?} */ NbDatepickerDirective.prototype.subscribeOnInputChange = /** * @protected * @return {?} */ function () { var _this = this; fromEvent(this.input, 'input') .pipe(map(function () { return _this.inputValue; }), takeWhile(function () { return _this.alive; })) .subscribe(function (value) { return _this.handleInputChange(value); }); }; /* * Parses input value and write if it isn't null. * */ /* * Parses input value and write if it isn't null. * */ /** * @protected * @param {?} value * @return {?} */ NbDatepickerDirective.prototype.handleInputChange = /* * Parses input value and write if it isn't null. * */ /** * @protected * @param {?} value * @return {?} */ function (value) { /** @type {?} */ var date = this.parseInputValue(value); this.onChange(date); this.writePicker(date); }; /** * @protected * @param {?} value * @return {?} */ NbDatepickerDirective.prototype.parseInputValue = /** * @protected * @param {?} value * @return {?} */ function (value) { if (this.datepickerAdapter.isValid(value, this.picker.format)) { return this.datepickerAdapter.parse(value, this.picker.format); } return null; }; NbDatepickerDirective.decorators = [ { type: Directive, args: [{ selector: 'input[nbDatepicker]', providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(function () { return NbDatepickerDirective; }), multi: true, }, { provide: NG_VALIDATORS, useExisting: forwardRef(function () { return NbDatepickerDirective; }), multi: true, }, ], },] } ]; /** @nocollapse */ NbDatepickerDirective.ctorParameters = function () { return [ { type: undefined, decorators: [{ type: Inject, args: [NB_DOCUMENT,] }] }, { type: Array, decorators: [{ type: Inject, args: [NB_DATE_ADAPTER,] }] }, { type: ElementRef }, { type: NbDateService } ]; }; NbDatepickerDirective.propDecorators = { setPicker: [{ type: Input, args: ['nbDatepicker',] }] }; return NbDatepickerDirective; }()); export { NbDatepickerDirective }; if (false) { /** * @type {?} * @protected */ NbDatepickerDirective.prototype.datepickerAdapter; /** * @type {?} * @protected */ NbDatepickerDirective.prototype.picker; /** * @type {?} * @protected */ NbDatepickerDirective.prototype.alive; /** * @type {?} * @protected */ NbDatepickerDirective.prototype.onChange; /** * @type {?} * @protected */ NbDatepickerDirective.prototype.onTouched; /** * @type {?} * @protected */ NbDatepickerDirective.prototype.validator; /** * @type {?} * @protected */ NbDatepickerDirective.prototype.document; /** * @type {?} * @protected */ NbDatepickerDirective.prototype.datepickerAdapters; /** * @type {?} * @protected */ NbDatepickerDirective.prototype.hostRef; /** * @type {?} * @protected */ NbDatepickerDirective.prototype.dateService; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZXBpY2tlci5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290Ijoibmc6Ly90aGVtZS1saWIvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9kYXRlcGlja2VyL2RhdGVwaWNrZXIuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQU1BLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLEtBQUssRUFBYSxNQUFNLGVBQWUsQ0FBQztBQUM1RyxPQUFPLEVBRUwsYUFBYSxFQUNiLGlCQUFpQixFQUlqQixVQUFVLEdBQ1gsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQUUsU0FBUyxFQUFjLEtBQUssRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNwRCxPQUFPLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFOUQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7Ozs7O0FBT2hEOzs7Ozs7Ozs7SUFBQTtJQW9CQSxDQUFDO0lBQUQsMEJBQUM7QUFBRCxDQUFDLEFBcEJELElBb0JDOzs7Ozs7Ozs7Ozs7SUFoQkMscUNBQTJCOzs7Ozs7O0lBSzNCLG1FQUFpRDs7Ozs7OztJQUtqRCxvRUFBa0Q7Ozs7Ozs7SUFLbEQscUVBQXlEOzs7Ozs7QUFNM0QsNkNBZUM7OztJQVhDLHNDQUFPOztJQUtQLHNDQUFPOztJQUtQLHlDQUF1Qjs7Ozs7Ozs7OztBQU96Qjs7Ozs7Ozs7O0lBQUE7SUErQkEsQ0FBQztJQUFELG1CQUFDO0FBQUQsQ0FBQyxBQS9CRCxJQStCQzs7Ozs7Ozs7Ozs7O0lBM0JDLDhCQUF3Qjs7Ozs7SUFFeEIsK0NBQXdCOzs7Ozs7SUFFeEIsb0RBQTZCOzs7OztJQUU3QixxREFBMEM7Ozs7OztJ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LEtBQUssU0FBQyxjQUFjOztJQXNOdkIsNEJBQUM7Q0FBQSxBQXpPRCxJQXlPQztTQTFOWSxxQkFBcUI7Ozs7OztJQWFoQyxrREFBb0Q7Ozs7O0lBS3BELHVDQUFrQzs7Ozs7SUFDbEMsc0NBQWdDOzs7OztJQUNoQyx5Q0FBMkM7Ozs7O0lBQzNDLDBDQUEyQzs7Ozs7SUFLM0MsMENBSzRCOzs7OztJQUVoQix5Q0FBdUM7Ozs7O0lBQ3ZDLG1EQUErRTs7Ozs7SUFDL0Usd0NBQTZCOzs7OztJQUM3Qiw0Q0FBdUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxyXG4gKiBAbGljZW5zZVxyXG4gKiBDb3B5cmlnaHQgQWt2ZW8uIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXHJcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS4gU2VlIExpY2Vuc2UudHh0IGluIHRoZSBwcm9qZWN0IHJvb3QgZm9yIGxpY2Vuc2UgaW5mb3JtYXRpb24uXHJcbiAqL1xyXG5cclxuaW1wb3J0IHsgRGlyZWN0aXZlLCBFbGVtZW50UmVmLCBmb3J3YXJkUmVmLCBJbmplY3QsIEluamVjdGlvblRva2VuLCBJbnB1dCwgT25EZXN0cm95IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7XHJcbiAgQ29udHJvbFZhbHVlQWNjZXNzb3IsXHJcbiAgTkdfVkFMSURBVE9SUyxcclxuICBOR19WQUxVRV9BQ0NFU1NPUixcclxuICBWYWxpZGF0aW9uRXJyb3JzLFxyXG4gIFZhbGlkYXRvcixcclxuICBWYWxpZGF0b3JGbixcclxuICBWYWxpZGF0b3JzLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgVHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvc3JjL3R5cGUnO1xyXG5pbXBvcnQgeyBmcm9tRXZlbnQsIE9ic2VydmFibGUsIG1lcmdlIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IG1hcCwgdGFrZVdoaWxlLCBmaWx0ZXIsIHRha2UgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcblxyXG5pbXBvcnQgeyBOQl9ET0NVTUVOVCB9IGZyb20gJy4uLy4uL3RoZW1lLm9wdGlvbnMnO1xyXG5pbXBvcnQgeyBOYkRhdGVTZXJ2aWNlIH0gZnJvbSAnLi4vY2FsZW5kYXIta2l0JztcclxuXHJcblxyXG4vKlxyXG4gKiBUaGUgYE5iRGF0ZXBpY2tlckFkYXB0ZXJgIGluc3RhbmNlcyBwcm92aWRlIHdheSBob3cgdG8gcGFyc2UsIGZvcm1hdCBhbmQgdmFsaWRhdGVcclxuICogZGlmZmVyZW50IGRhdGUgdHlwZXMuXHJcbiAqICovXHJcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBOYkRhdGVwaWNrZXJBZGFwdGVyPEQ+IHtcclxuICAvKlxyXG4gICAqIFBpY2tlciBjb21wb25lbnQgY2xhc3MuXHJcbiAgICogKi9cclxuICBhYnN0cmFjdCBwaWNrZXI6IFR5cGU8YW55PjtcclxuXHJcbiAgLypcclxuICAgKiBQYXJzZSBkYXRlIHN0cmluZyBhY2NvcmRpbmcgdG8gdGhlIGZvcm1hdC5cclxuICAgKiAqL1xyXG4gIGFic3RyYWN0IHBhcnNlKHZhbHVlOiBzdHJpbmcsIGZvcm1hdDogc3RyaW5nKTogRDtcclxuXHJcbiAgLypcclxuICAgKiBGb3JtYXQgZGF0ZSBhY2NvcmRpbmcgdG8gdGhlIGZvcm1hdC5cclxuICAgKiAqL1xyXG4gIGFic3RyYWN0IGZvcm1hdCh2YWx1ZTogRCwgZm9ybWF0OiBzdHJpbmcpOiBzdHJpbmc7XHJcblxyXG4gIC8qXHJcbiAgICogVmFsaWRhdGVzIGRhdGUgc3RyaW5nIGFjY29yZGluZyB0byB0aGUgcGFzc2VkIGZvcm1hdC5cclxuICAgKiAqL1xyXG4gIGFic3RyYWN0IGlzVmFsaWQodmFsdWU6IHN0cmluZywgZm9ybWF0OiBzdHJpbmcpOiBib29sZWFuO1xyXG59XHJcblxyXG4vKlxyXG4gKiBWYWxpZGF0b3JzIGNvbmZpZyB0aGF0IHdpbGwgYmUgdXNlZCBieSBmb3JtIGNvbnRyb2wgdG8gcGVyZm9ybSBwcm9wZXIgdmFsaWRhdGlvbi5cclxuICogKi9cclxuZXhwb3J0IGludGVyZmFjZSBOYlBpY2tlclZhbGlkYXRvckNvbmZpZzxEPiB7XHJcbiAgLypcclxuICAgKiBNaW5pbXVtIGRhdGUgYXZhaWxhYmxlIGluIHBpY2tlci5cclxuICAgKiAqL1xyXG4gIG1pbjogRDtcclxuXHJcbiAgLypcclxuICAgKiBNYXhpbXVtIGRhdGUgYXZhaWxhYmxlIGluIHBpY2tlci5cclxuICAgKiAqL1xyXG4gIG1heDogRDtcclxuXHJcbiAgLypcclxuICAgKiBQcmVkaWNhdGUgdGhhdCBkZXRlcm1pbmVzIGlzIHZhbHVlIGF2YWlsYWJsZSBmb3IgcGlja2luZy5cclxuICAgKiAqL1xyXG4gIGZpbHRlcjogKEQpID0+IGJvb2xlYW47XHJcbn1cclxuXHJcbi8qXHJcbiAqIERhdGVwaWNrZXIgaXMgYW4gY29udHJvbCB0aGF0IGNhbiBwaWNrIGFueSB2YWx1ZXMgYW55d2F5LlxyXG4gKiBJdCBoYXMgdG8gYmUgYm91bmQgdG8gdGhlIGRhdGVwaWNrZXIgZGlyZWN0aXZlIHRocm91Z2ggbmJEYXRlcGlja2VyIGlucHV0LlxyXG4gKiAqL1xyXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgTmJEYXRlcGlja2VyPFQ+IHtcclxuICAvKlxyXG4gICAqIEhUTUwgaW5wdXQgZWxlbWVudCBkYXRlIGZvcm1hdC5cclxuICAgKiAqL1xyXG4gIGFic3RyYWN0IGZvcm1hdDogc3RyaW5nO1xyXG5cclxuICBhYnN0cmFjdCBnZXQgdmFsdWUoKTogVDtcclxuXHJcbiAgYWJzdHJhY3Qgc2V0IHZhbHVlKHZhbHVlOiBUKTtcclxuXHJcbiAgYWJzdHJhY3QgZ2V0IHZhbHVlQ2hhbmdlKCk6IE9ic2VydmFibGU8VD47XHJcblxyXG4gIC8qXHJcbiAgICogQXR0YWNoZXMgZGF0ZXBpY2tlciB0byB0aGUgbmF0aXZlIGlucHV0IGVsZW1lbnQuXHJcbiAgICogKi9cclxuICBhYnN0cmFjdCBhdHRhY2goaG9zdFJlZjogRWxlbWVudFJlZik7XHJcblxyXG4gIC8qXHJcbiAgICogUmV0dXJucyB2YWxpZGF0b3IgY29uZmlndXJhdGlvbiBiYXNlZCBvbiB0aGUgaW5wdXQgcHJvcGVydGllcy5cclxuICAgKiAqL1xyXG4gIGFic3RyYWN0IGdldFZhbGlkYXRvckNvbmZpZygpOiBOYlBpY2tlclZhbGlkYXRvckNvbmZpZzxUPjtcclxuXHJcbiAgYWJzdHJhY3Qgc2hvdygpO1xyXG5cclxuICBhYnN0cmFjdCBoaWRlKCk7XHJcblxyXG4gIGFic3RyYWN0IHNob3VsZEhpZGUoKTogYm9vbGVhbjtcclxuXHJcbiAgYWJzdHJhY3QgZ2V0IGlzU2hvd24oKTogYm9vbGVhbjtcclxuXHJcbiAgYWJzdHJhY3QgZ2V0IGJsdXIoKTogT2JzZXJ2YWJsZTx2b2lkPjtcclxufVxyXG5cclxuZXhwb3J0IGNvbnN0IE5CX0RBVEVfQURBUFRFUiA9IG5ldyBJbmplY3Rpb25Ub2tlbjxOYkRhdGVwaWNrZXJBZGFwdGVyPGFueT4+KCdEYXRlcGlja2VyIEFkYXB0ZXInKTtcclxuXHJcblxyXG4vKlxyXG4gKiBUaGUgYE5iRGF0ZXBpY2tlckRpcmVjdGl2ZWAgaXMgZm9ybSBjb250cm9sIHRoYXQgZ2l2ZXMgeW91IGFiaWxpdHkgdG8gc2VsZWN0IGRhdGVzIGFuZCByYW5nZXMuIFRoZSBkYXRlcGlja2VyXHJcbiAqIGlzIHNob3duIHdoZW4gaW5wdXQgcmVjZWl2ZXMgYSBgZm9jdXNgIGV2ZW50LlxyXG4gKlxyXG4gKiBgYGBodG1sXHJcbiAqIDxpbnB1dCBbbmJEYXRlcGlja2VyXT1cImRhdGVwaWNrZXJcIj5cclxuICogPG5iLWRhdGVwaWNrZXIgI2RhdGVwaWNrZXI+PC9uYi1kYXRlcGlja2VyPlxyXG4gKiBgYGBcclxuICpcclxuICogQHN0YWNrZWQtZXhhbXBsZShTaG93Y2FzZSwgZGF0ZXBpY2tlci9kYXRlcGlja2VyLXNob3djYXNlLmNvbXBvbmVudClcclxuICpcclxuICogIyMjIEluc3RhbGxhdGlvblxyXG4gKlxyXG4gKiBJbXBvcnQgYE5iRGF0ZXBpY2tlck1vZHVsZS5mb3JSb290KClgIHRvIHlvdXIgcm9vdCBtb2R1bGUuXHJcbiAqIGBgYHRzXHJcbiAqIEBOZ01vZHVsZSh7XHJcbiAqICAgaW1wb3J0czogW1xyXG4gKiAgIFx0Ly8gLi4uXHJcbiAqICAgICBOYkRhdGVwaWNrZXJNb2R1bGUuZm9yUm9vdCgpLFxyXG4gKiAgIF0sXHJcbiAqIH0pXHJcbiAqIGV4cG9ydCBjbGFzcyBBcHBNb2R1bGUgeyB9XHJcbiAqIGBgYFxyXG4gKiBBbmQgYE5iRGF0ZXBpY2tlck1vZHVsZWAgdG8geW91ciBmZWF0dXJlIG1vZHVsZS5cclxuICogYGBgdHNcclxuICogQE5nTW9kdWxlKHtcclxuICogICBpbXBvcnRzOiBbXHJcbiAqICAgXHQvLyAuLi5cclxuICogICAgIE5iRGF0ZXBpY2tlck1vZHVsZSxcclxuICogICBdLFxyXG4gKiB9KVxyXG4gKiBleHBvcnQgY2xhc3MgUGFnZU1vZHVsZSB7IH1cclxuICogYGBgXHJcbiAqICMjIyBVc2FnZVxyXG4gKlxyXG4gKiBJZiB5b3Ugd2FudCB0byB1c2UgcmFuZ2Ugc2VsZWN0aW9uLCB5b3UgaGF2ZSB0byB1c2UgYE5iUmFuZ2VwaWNrZXJDb21wb25lbnRgIGluc3RlYWQ6XHJcbiAqXHJcbiAqIGBgYGh0bWxcclxuICogPGlucHV0IFtuYkRhdGVwaWNrZXJdPVwicmFuZ2VwaWNrZXJcIj5cclxuICogPG5iLXJhbmdlcGlja2VyICNyYW5nZXBpY2tlcj48L25iLXJhbmdlcGlja2VyPlxyXG4gKiBgYGBcclxuICpcclxuICogQm90aCByYW5nZSBhbmQgZGF0ZSBwaWNrZXJzIHN1cHBvcnQgYWxsIHBhcmFtZXRlcnMgYXMgY2FsZW5kYXIsIHNvLCBjaGVjayBgTmJDYWxlbmRhckNvbXBvbmVudGAgZm9yIGFkZGl0aW9uYWxcclxuICogaW5mby5cclxuICpcclxuICogQHN0YWNrZWQtZXhhbXBsZShSYW5nZSBzaG93Y2FzZSwgZGF0ZXBpY2tlci9yYW5nZXBpY2tlci1zaG93Y2FzZS5jb21wb25lbnQpXHJcbiAqXHJcbiAqIERhdGVwaWNrZXIgaXMgdGhlIGZvcm0gY29udHJvbCBzbyBpdCBjYW4gYmUgYm91bmQgd2l0aCBhbmd1bGFyIGZvcm1zIHRocm91Z2ggbmdNb2RlbCBhbmQgZm9ybSBjb250cm9scy5cclxuICpcclxuICogQHN0YWNrZWQtZXhhbXBsZShGb3JtcywgZGF0ZXBpY2tlci9kYXRlcGlja2VyLWZvcm1zLmNvbXBvbmVudClcclxuICpcclxuICogYE5iRGF0ZXBpY2tlckRpcmVjdGl2ZWAgbWF5IGJlIHZhbGlkYXRlZCB1c2luZyBgbWluYCBhbmQgYG1heGAgZGF0ZXMgcGFzc2VkIHRvIHRoZSBkYXRlcGlja2VyLlxyXG4gKiBBbmQgYGZpbHRlcmAgcHJlZGljYXRlIHRoYXQgcmVjZWl2ZXMgZGF0ZSBvYmplY3QgYW5kIGhhcyB0byByZXR1cm4gYSBib29sZWFuIHZhbHVlLlxyXG4gKlxyXG4gKiBAc3RhY2tlZC1leGFtcGxlKFZhbGlkYXRpb24sIGRhdGVwaWNrZXIvZGF0ZXBpY2tlci12YWxpZGF0aW9uLmNvbXBvbmVudClcclxuICpcclxuICogVGhlIGBOYkRhdGVwaWNrZXJDb21wb25lbnRgIHN1cHBvcnRzIGRhdGUgZm9ybWF0dGluZzpcclxuICpcclxuICogYGBgaHRtbFxyXG4gKiA8aW5wdXQgW25iRGF0ZXBpY2tlcl09XCJkYXRlcGlja2VyXCI+XHJcbiAqIDxuYi1kYXRlcGlja2VyICNkYXRlcGlja2VyIGZvcm1hdD1cIk1NXFxkZFxceXl5eVwiPjwvbmItZGF0ZXBpY2tlcj5cclxuICogYGBgXHJcbiAqXHJcbiAqICMjIEZvcm1hdHRpbmcgSXNzdWVcclxuICpcclxuICogQnkgZGVmYXVsdCwgZGF0ZXBpY2tlciB1c2VzIGFuZ3VsYXJzIGBMT0NBTEVfSURgIHRva2VuIGZvciBsb2NhbGl6YXRpb24gYW5kIGBEYXRlUGlwZWAgZm9yIGRhdGVzIGZvcm1hdHRpbmcuXHJcbiAqIEFuZCBuYXRpdmUgYERhdGUucGFyc2UoLi4uKWAgZm9yIGRhdGVzIHBhcnNpbmcuIEJ1dCBuYXRpdmUgYERhdGUucGFyc2VgIGZ1bmN0aW9uIGRvZXNuJ3Qgc3VwcG9ydCBmb3JtYXRzLlxyXG4gKiBUbyBwcm92aWRlIGN1c3RvbSBmb3JtYXR0aW5nIHlvdSBoYXZlIHRvIHVzZSBvbmUgb2YgdGhlIGZvbGxvd2luZyBwYWNrYWdlczpcclxuICpcclxuICogLSBgQG5lYnVsYXIvbW9tZW50YCAtIHByb3ZpZGVzIG1vbWVudCBkYXRlIGFkYXB0ZXIgdGhhdCB1c2VzIG1vbWVudCBmb3IgZGF0ZSBvYmplY3RzLiBUaGlzIG1lYW5zIGRhdGVwaWNrZXIgdGhhblxyXG4gKiB3aWxsIG9wZXJhdGUgb25seSBtb21lbnQgZGF0ZSBvYmplY3RzLiBJZiB5b3Ugd2FudCB0byB1c2UgaXQgeW91IGhhdmUgdG8gaW5zdGFsbCBpdDogYG5wbSBpIEBuZWJ1bGFyL21vbWVudGAsIGFuZFxyXG4gKiBpbXBvcnQgYE5iTW9tZW50RGF0ZU1vZHVsZWAgZnJvbSB0aGlzIHBhY2thZ2UuXHJcbiAqXHJcbiAqIC0gYEBuZWJ1bGFyL2RhdGUtZm5zYCAtIGFkYXB0ZXIgZm9yIHBvcHVsYXIgZGF0ZS1mbnMgbGlicmFyeS4gVGhpcyB3YXkgaXMgcHJlZmVycmVkIGlmIHlvdSBuZWVkIG9ubHkgZGF0ZSBmb3JtYXR0aW5nLlxyXG4gKiBCZWNhdXNlIGRhdGUtZm5zIGlzIHRyZWVzaGFrYWJsZSwgdGlueSBhbmQgb3BlcmF0ZXMgbmF0aXZlIGRhdGUgb2JqZWN0cy4gSWYgeW91IHdhbnQgdG8gdXNlIGl0IHlvdSBoYXZlIHRvXHJcbiAqIGluc3RhbGwgaXQ6IGBucG0gaSBAbmVidWxhci9kYXRlLWZuc2AsIGFuZCBpbXBvcnQgYE5iRGF0ZUZuc0RhdGVNb2R1bGVgIGZyb20gdGhpcyBwYWNrYWdlLlxyXG4gKlxyXG4gKiBAc3R5bGVzXHJcbiAqXHJcbiAqIGRhdGVwaWNrZXItZmdcclxuICogZGF0ZXBpY2tlci1iZ1xyXG4gKiBkYXRlcGlja2VyLWJvcmRlclxyXG4gKiBkYXRlcGlja2VyLWJvcmRlci1yYWRpdXNcclxuICogZGF0ZXBpY2tlci1zaGFkb3dcclxuICogZGF0ZXBpY2tlci1hcnJvdy1zaXplXHJcbiAqICovXHJcbkBEaXJlY3RpdmUoe1xyXG4gIHNlbGVjdG9yOiAnaW5wdXRbbmJEYXRlcGlja2VyXScsXHJcbiAgcHJvdmlkZXJzOiBbXHJcbiAgICB7XHJcbiAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxyXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBOYkRhdGVwaWNrZXJEaXJlY3RpdmUpLFxyXG4gICAgICBtdWx0aTogdHJ1ZSxcclxuICAgIH0sXHJcbiAgICB7XHJcbiAgICAgIHByb3ZpZGU6IE5HX1ZBTElEQVRPUlMsXHJcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IE5iRGF0ZXBpY2tlckRpcmVjdGl2ZSksXHJcbiAgICAgIG11bHRpOiB0cnVlLFxyXG4gICAgfSxcclxuICBdLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTmJEYXRlcGlja2VyRGlyZWN0aXZlPEQ+IGltcGxlbWVudHMgT25EZXN0cm95LCBDb250cm9sVmFsdWVBY2Nlc3NvciwgVmFsaWRhdG9yIHtcclxuICAvKlxyXG4gICAqIFByb3ZpZGVzIGRhdGVwaWNrZXIgY29tcG9uZW50LlxyXG4gICAqICovXHJcbiAgQElucHV0KCduYkRhdGVwaWNrZXInKVxyXG4gIHNldCBzZXRQaWNrZXIocGlja2VyOiBOYkRhdGVwaWNrZXI8RD4pIHtcclxuICAgIHRoaXMucGlja2VyID0gcGlja2VyO1xyXG4gICAgdGhpcy5zZXR1cFBpY2tlcigpO1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBEYXRlcGlja2VyIGFkYXB0ZXIuXHJcbiAgICogKi9cclxuICBwcm90ZWN0ZWQgZGF0ZXBpY2tlckFkYXB0ZXI6IE5iRGF0ZXBpY2tlckFkYXB0ZXI8RD47XHJcblxyXG4gIC8qXHJcbiAgICogRGF0ZXBpY2tlciBpbnN0YW5jZS5cclxuICAgKiAqL1xyXG4gIHByb3RlY3RlZCBwaWNrZXI6IE5iRGF0ZXBpY2tlcjxEPjtcclxuICBwcm90ZWN0ZWQgYWxpdmU6IGJvb2xlYW4gPSB0cnVlO1xyXG4gIHByb3RlY3RlZCBvbkNoYW5nZTogKEQpID0+IHZvaWQgPSAoKSA9PiB7fTtcclxuICBwcm90ZWN0ZWQgb25Ub3VjaGVkOiAoKSA9PiB2b2lkID0gKCkgPT4ge307XHJcblxyXG4gIC8qXHJcbiAgICogRm9ybSBjb250cm9sIHZhbGlkYXRvcnMgd2lsbCBiZSBjYWxsZWQgaW4gdmFsaWRhdG9ycyBjb250ZXh0LCBzbywgd2UgbmVlZCB0byBiaW5kIHRoZW0uXHJcbiAgICogKi9cclxuICBwcm90ZWN0ZWQgdmFsaWRhdG9yOiBWYWxpZGF0b3JGbiA9IFZhbGlkYXRvcnMuY29tcG9zZShbXHJcbiAgICB0aGlzLnBhcnNlVmFsaWRhdG9yLFxyXG4gICAgdGhpcy5taW5WYWxpZGF0b3IsXHJcbiAgICB0aGlzLm1heFZhbGlkYXRvcixcclxuICAgIHRoaXMuZmlsdGVyVmFsaWRhdG9yLFxyXG4gIF0ubWFwKGZuID0+IGZuLmJpbmQodGhpcykpKTtcclxuXHJcbiAgY29uc3RydWN0b3IoQEluamVjdChOQl9ET0NVTUVOVCkgcHJvdGVjdGVkIGRvY3VtZW50LFxyXG4gICAgICAgICAgICAgIEBJbmplY3QoTkJfREFURV9BREFQVEVSKSBwcm90ZWN0ZWQgZGF0ZXBpY2tlckFkYXB0ZXJzOiBOYkRhdGVwaWNrZXJBZGFwdGVyPEQ+W10sXHJcbiAgICAgICAgICAgICAgcHJvdGVjdGVkIGhvc3RSZWY6IEVsZW1lbnRSZWYsXHJcbiAgICAgICAgICAgICAgcHJvdGVjdGVkIGRhdGVTZXJ2aWNlOiBOYkRhdGVTZXJ2aWNlPEQ+KSB7XHJcbiAgICB0aGlzLnN1YnNjcmliZU9uSW5wdXRDaGFuZ2UoKTtcclxuICB9XHJcblxyXG4gIC8qXHJcbiAgICogUmV0dXJucyBodG1sIGlucHV0IGVsZW1lbnQuXHJcbiAgICogKi9cclxuICBnZXQgaW5wdXQoKTogSFRNTElucHV0RWxlbWVudCB7XHJcbiAgICByZXR1cm4gdGhpcy5ob3N0UmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIFJldHVybnMgaG9zdCBpbnB1dCB2YWx1ZS5cclxuICAgKiAqL1xyXG4gIGdldCBpbnB1dFZhbHVlKCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5pbnB1dC52YWx1ZTtcclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCkge1xyXG4gICAgdGhpcy5hbGl2ZSA9IGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBXcml0ZXMgdmFsdWUgaW4gcGlja2VyIGFuZCBodG1sIGlucHV0IGVsZW1lbnQuXHJcbiAgICogKi9cclxuICB3cml0ZVZhbHVlKHZhbHVlOiBEKSB7XHJcbiAgICB0aGlzLndyaXRlUGlja2VyKHZhbHVlKTtcclxuICAgIHRoaXMud3JpdGVJbnB1dCh2YWx1ZSk7XHJcbiAgfVxyXG5cclxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpOiB2b2lkIHtcclxuICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcclxuICB9XHJcblxyXG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiBhbnkpOiB2b2lkIHtcclxuICAgIHRoaXMub25Ub3VjaGVkID0gZm47XHJcbiAgfVxyXG5cclxuICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIHRoaXMuaW5wdXQuZGlzYWJsZWQgPSBpc0Rpc2FibGVkO1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBGb3JtIGNvbnRyb2wgdmFsaWRhdGlvbiBiYXNlZCBvbiBwaWNrZXIgdmFsaWRhdG9yIGNvbmZpZy5cclxuICAgKiAqL1xyXG4gIHZhbGlkYXRlKCk6IFZhbGlkYXRpb25FcnJvcnMgfCBudWxsIHtcclxuICAgIHJldHVybiB0aGlzLnZhbGlkYXRvcihudWxsKTtcclxuICB9XHJcblxyXG4gIC8qXHJcbiAgICogSGlkZXMgcGlja2VyLCBmb2N1c2VzIHRoZSBpbnB1dFxyXG4gICAqL1xyXG4gIHByb3RlY3RlZCBoaWRlUGlja2VyKCkge1xyXG4gICAgdGhpcy5pbnB1dC5mb2N1cygpO1xyXG4gICAgdGhpcy5waWNrZXIuaGlkZSgpO1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBWYWxpZGF0ZXMgdGhhdCB3ZSBjYW4gcGFyc2UgdmFsdWUgY29ycmVjdGx5LlxyXG4gICAqICovXHJcbiAgcHJvdGVjdGVkIHBhcnNlVmFsaWRhdG9yKCk6IFZhbGlkYXRpb25FcnJvcnMgfCBudWxsIHtcclxuICAgIGNvbnN0IGlzVmFsaWQgPSB0aGlzLmRhdGVwaWNrZXJBZGFwdGVyLmlzVmFsaWQodGhpcy5pbnB1dFZhbHVlLCB0aGlzLnBpY2tlci5mb3JtYXQpO1xyXG4gICAgcmV0dXJuIGlzVmFsaWQgPyBudWxsIDogeyBuYkRhdGVwaWNrZXJQYXJzZTogeyB2YWx1ZTogdGhpcy5pbnB1dFZhbHVlIH0gfTtcclxuICB9XHJcblxyXG4gIC8qXHJcbiAgICogVmFsaWRhdGVzIHBhc3NlZCB2YWx1ZSBpcyBncmVhdGVyIHRoYW4gbWluLlxyXG4gICAqICovXHJcbiAgcHJvdGVjdGVkIG1pblZhbGlkYXRvcigpOiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCB7XHJcbiAgICBjb25zdCBjb25maWcgPSB0aGlzLnBpY2tlci5nZXRWYWxpZGF0b3JDb25maWcoKTtcclxuICAgIGNvbnN0IGRhdGUgPSB0aGlzLmRhdGVwaWNrZXJBZGFwdGVyLnBhcnNlKHRoaXMuaW5wdXRWYWx1ZSwgdGhpcy5waWNrZXIuZm9ybWF0KTtcclxuICAgIHJldHVybiAoIWNvbmZpZy5taW4gfHwgIWRhdGUgfHwgdGhpcy5kYXRlU2VydmljZS5jb21wYXJlRGF0ZXMoY29uZmlnLm1pbiwgZGF0ZSkgPD0gMCkgP1xyXG4gICAgICBudWxsIDogeyBuYkRhdGVwaWNrZXJNaW46IHsgbWluOiBjb25maWcubWluLCBhY3R1YWw6IGRhdGUgfSB9O1xyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBWYWxpZGF0ZXMgcGFzc2VkIHZhbHVlIGlzIHNtYWxsZXIgdGhhbiBtYXguXHJcbiAgICogKi9cclxuICBwcm90ZWN0ZWQgbWF4VmFsaWRhdG9yKCk6IFZhbGlkYXRpb25FcnJvcnMgfCBudWxsIHtcclxuICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMucGlja2VyLmdldFZhbGlkYXRvckNvbmZpZygpO1xyXG4gICAgY29uc3QgZGF0ZSA9IHRoaXMuZGF0ZXBpY2tlckFkYXB0ZXIucGFyc2UodGhpcy5pbnB1dFZhbHVlLCB0aGlzLnBpY2tlci5mb3JtYXQpO1xyXG4gICAgcmV0dXJuICghY29uZmlnLm1heCB8fCAhZGF0ZSB8fCB0aGlzLmRhdGVTZXJ2aWNlLmNvbXBhcmVEYXRlcyhjb25maWcubWF4LCBkYXRlKSA+PSAwKSA/XHJcbiAgICAgIG51bGwgOiB7IG5iRGF0ZXBpY2tlck1heDogeyBtYXg6IGNvbmZpZy5tYXgsIGFjdHVhbDogZGF0ZSB9IH07XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIFZhbGlkYXRlcyBwYXNzZWQgdmFsdWUgc2F0aXNmeSB0aGUgZmlsdGVyLlxyXG4gICAqICovXHJcbiAgcHJvdGVjdGVkIGZpbHRlclZhbGlkYXRvcigpOiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCB7XHJcbiAgICBjb25zdCBjb25maWcgPSB0aGlzLnBpY2tlci5nZXRWYWxpZGF0b3JDb25maWcoKTtcclxuICAgIGNvbnN0IGRhdGUgPSB0aGlzLmRhdGVwaWNrZXJBZGFwdGVyLnBhcnNlKHRoaXMuaW5wdXRWYWx1ZSwgdGhpcy5waWNrZXIuZm9ybWF0KTtcclxuICAgIHJldHVybiAoIWNvbmZpZy5maWx0ZXIgfHwgIWRhdGUgfHwgY29uZmlnLmZpbHRlcihkYXRlKSkgP1xyXG4gICAgICBudWxsIDogeyBuYkRhdGVwaWNrZXJGaWx0ZXI6IHRydWUgfTtcclxuICB9XHJcblxyXG4gIC8qXHJcbiAgICogQ2hvb3NlcyBkYXRlcGlja2VyIGFkYXB0ZXIgYmFzZWQgb24gcGFzc2VkIHBpY2tlciBjb21wb25lbnQuXHJcbiAgICogKi9cclxuICBwcm90ZWN0ZWQgY2hvb3NlRGF0ZXBpY2tlckFkYXB0ZXIoKSB7XHJcbiAgICB0aGlzLmRhdGVwaWNrZXJBZGFwdGVyID0gdGhpcy5kYXRlcGlja2VyQWRhcHRlcnMuZmluZCgoeyBwaWNrZXIgfSkgPT4gdGhpcy5waWNrZXIgaW5zdGFuY2VvZiBwaWNrZXIpO1xyXG5cclxuICAgIGlmICh0aGlzLm5vRGF0ZXBpY2tlckFkYXB0ZXJQcm92aWRlZCgpKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gZGF0ZXBpY2tlckFkYXB0ZXIgcHJvdmlkZWQgZm9yIHBpY2tlcicpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLypcclxuICAgKiBBdHRhY2hlcyBwaWNrZXIgdG8gdGhlIGhvc3QgaW5wdXQgZWxlbWVudCBhbmQgc3Vic2NyaWJlcyBvbiB2YWx1ZSBjaGFuZ2VzLlxyXG4gICAqICovXHJcbiAgcHJvdGVjdGVkIHNldHVwUGlja2VyKCkge1xyXG4gICAgdGhpcy5jaG9vc2VEYXRlcGlja2VyQWRhcHRlcigpO1xyXG4gICAgdGhpcy5waWNrZXIuYXR0YWNoKHRoaXMuaG9zdFJlZik7XHJcblxyXG4gICAgaWYgKHRoaXMuaG9zdFJlZi5uYXRpdmVFbGVtZW50LnZhbHVlKSB7XHJcbiAgICAgIHRoaXMucGlja2VyLnZhbHVlID0gdGhpcy5kYXRlcGlja2VyQWRhcHRlci5wYXJzZSh0aGlzLmhvc3RSZWYubmF0aXZlRWxlbWVudC52YWx1ZSwgdGhpcy5waWNrZXIuZm9ybWF0KTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnBpY2tlci52YWx1ZUNoYW5nZVxyXG4gICAgICAucGlwZSh0YWtlV2hpbGUoKCkgPT4gdGhpcy5hbGl2ZSkpXHJcbiAgICAgIC5zdWJzY3JpYmUoKHZhbHVlOiBEKSA9PiB7XHJcbiAgICAgICAgdGhpcy53cml0ZVBpY2tlcih2YWx1ZSk7XHJcbiAgICAgICAgdGhpcy53cml0ZUlucHV0KHZhbHVlKTtcclxuICAgICAgICB0aGlzLm9uQ2hhbmdlKHZhbHVlKTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMucGlja2VyLnNob3VsZEhpZGUoKSkge1xyXG4gICAgICAgICAgdGhpcy5oaWRlUGlja2VyKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICBtZXJnZShcclxuICAgICAgdGhpcy5waWNrZXIuYmx1cixcclxuICAgICAgZnJvbUV2ZW50KHRoaXMuaW5wdXQsICdibHVyJykucGlwZShcclxuICAgICAgICBmaWx0ZXIoKCkgPT4gIXRoaXMucGlja2VyLmlzU2hvd24gJiYgdGhpcy5kb2N1bWVudC5hY3RpdmVFbGVtZW50ICE9PSB0aGlzLmlucHV0KSxcclxuICAgICAgKSxcclxuICAgICkucGlwZShcclxuICAgICAgdGFrZVdoaWxlKCgpID0+IHRoaXMuYWxpdmUpLFxyXG4gICAgICB0YWtlKDEpLFxyXG4gICAgKS5zdWJzY3JpYmUoKCkgPT4gdGhpcy5vblRvdWNoZWQoKSk7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgd3JpdGVQaWNrZXIodmFsdWU6IEQpIHtcclxuICAgIHRoaXMucGlja2VyLnZhbHVlID0gdmFsdWU7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgd3JpdGVJbnB1dCh2YWx1ZTogRCkge1xyXG4gICAgY29uc3Qgc3RyaW5nUmVwcmVzZW50YXRpb24gPSB0aGlzLmRhdGVwaWNrZXJBZGFwdGVyLmZvcm1hdCh2YWx1ZSwgdGhpcy5waWNrZXIuZm9ybWF0KTtcclxuICAgIHRoaXMuaG9zdFJlZi5uYXRpdmVFbGVtZW50LnZhbHVlID0gc3RyaW5nUmVwcmVzZW50YXRpb247XHJcbiAgfVxyXG5cclxuICAvKlxyXG4gICAqIFZhbGlkYXRlcyBpZiBubyBkYXRlcGlja2VyIGFkYXB0ZXIgcHJvdmlkZWQuXHJcbiAgICogKi9cclxuICBwcm90ZWN0ZWQgbm9EYXRlcGlja2VyQWRhcHRlclByb3ZpZGVkKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuICF0aGlzLmRhdGVwaWNrZXJBZGFwdGVyIHx8ICEodGhpcy5kYXRlcGlja2VyQWRhcHRlciBpbnN0YW5jZW9mIE5iRGF0ZXBpY2tlckFkYXB0ZXIpO1xyXG4gIH1cclxuXHJcbiAgcHJvdGVjdGVkIHN1YnNjcmliZU9uSW5wdXRDaGFuZ2UoKSB7XHJcbiAgICBmcm9tRXZlbnQodGhpcy5pbnB1dCwgJ2lucHV0JylcclxuICAgICAgLnBpcGUoXHJcbiAgICAgICAgbWFwKCgpID0+IHRoaXMuaW5wdXRWYWx1ZSksXHJcbiAgICAgICAgdGFrZVdoaWxlKCgpID0+IHRoaXMuYWxpdmUpLFxyXG4gICAgICApXHJcbiAgICAgIC5zdWJzY3JpYmUoKHZhbHVlOiBzdHJpbmcpID0+IHRoaXMuaGFuZGxlSW5wdXRDaGFuZ2UodmFsdWUpKTtcclxuICB9XHJcblxyXG4gIC8qXHJcbiAgICogUGFyc2VzIGlucHV0IHZhbHVlIGFuZCB3cml0ZSBpZiBpdCBpc24ndCBudWxsLlxyXG4gICAqICovXHJcbiAgcHJvdGVjdGVkIGhhbmRsZUlucHV0Q2hhbmdlKHZhbHVlOiBzdHJpbmcpIHtcclxuICAgIGNvbnN0IGRhdGUgPSB0aGlzLnBhcnNlSW5wdXRWYWx1ZSh2YWx1ZSk7XHJcblxyXG4gICAgdGhpcy5vbkNoYW5nZShkYXRlKTtcclxuICAgIHRoaXMud3JpdGVQaWNrZXIoZGF0ZSk7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgcGFyc2VJbnB1dFZhbHVlKHZhbHVlKTogRCB8IG51bGwge1xyXG4gICAgaWYgKHRoaXMuZGF0ZXBpY2tlckFkYXB0ZXIuaXNWYWxpZCh2YWx1ZSwgdGhpcy5waWNrZXIuZm9ybWF0KSkge1xyXG4gICAgICByZXR1cm4gdGhpcy5kYXRlcGlja2VyQWRhcHRlci5wYXJzZSh2YWx1ZSwgdGhpcy5waWNrZXIuZm9ybWF0KTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcbn1cclxuIl19