ngx-paypal-with-intent
Version:
Paypal integration for Angular 6, 7 and beyond
458 lines • 46.5 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
import { ChangeDetectionStrategy, Component, ElementRef, Input, ViewChild, } from '@angular/core';
import { interval, Subject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { PayPalFunding } from '../models/paypal-funding';
import { PayPalIntegrationType } from '../models/paypal-integration';
import { PayPalConfig } from '../models/paypal-models';
var NgxPaypalComponent = /** @class */ (function () {
function NgxPaypalComponent() {
/**
* Indicates if global configuration (provided via 'forRoot') is used
*/
this.useGlobalConfig = false;
/**
* Used for indicating delayed rendered if container is not yet ready in DOM
*/
this.registerPayPalScriptWhenContainerIsReady = false;
/**
* Polling interval if paypal script is pending
*/
this.defaultPollInterval = 50;
/**
* Polling will stop after polling reaches this number
*/
this.maximumPollWaitTime = 5000;
/**
* Name of the global variable where paypal is stored
*/
this.paypalWindowName = 'paypal';
/**
* Name of the global variable indicating that script was initiated (added to page)
*/
this.paypalWindowScriptInitiated = 'ngx-paypal-script-initiated';
/**
* PayPal integration script url
*/
this.paypalScriptUrl = 'https://www.paypalobjects.com/api/checkout.js';
this.payPalButtonContainerIdPrefix = 'ngx-paypal-button-container-';
this.ngUnsubscribe = new Subject();
}
Object.defineProperty(NgxPaypalComponent.prototype, "payPalButtonContainerElem", {
set: /**
* @param {?} content
* @return {?}
*/
function (content) {
if (content) {
this._payPalButtonContainerElem = content;
}
},
enumerable: true,
configurable: true
});
/**
* @param {?} changes
* @return {?}
*/
NgxPaypalComponent.prototype.ngOnChanges = /**
* @param {?} changes
* @return {?}
*/
function (changes) {
// init when config once its available
if (this.config) {
this.initPayPal();
}
};
/**
* @return {?}
*/
NgxPaypalComponent.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
// register script if element is ready in dom
if (this.registerPayPalScriptWhenContainerIsReady && this._payPalButtonContainerElem) {
this.setupScript();
this.registerPayPalScriptWhenContainerIsReady = false;
}
};
/**
* @return {?}
*/
NgxPaypalComponent.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
};
/**
* @return {?}
*/
NgxPaypalComponent.prototype.initPayPal = /**
* @return {?}
*/
function () {
// set unique paypal container button id
this.payPalButtonContainerId = "" + this.payPalButtonContainerIdPrefix + this.getPseudoUniqueNumber();
// check if paypal was already register and if so, don't add it to page again
if (!window[this.paypalWindowName]) {
// check if script is pending
if (window[this.paypalWindowScriptInitiated] === true) {
this.pollUntilScriptAvailable();
}
else {
// register script and set global flag
window[this.paypalWindowScriptInitiated] = true;
this.addPayPalScriptToPage();
}
}
else {
// just register payment
this.handleScriptRegistering();
}
};
/**
* @return {?}
*/
NgxPaypalComponent.prototype.getPseudoUniqueNumber = /**
* @return {?}
*/
function () {
return new Date().valueOf();
};
/**
* Used when there are multiple paypal components on the same page beacuse only 1 of them
* may register paypal script. The other has to be polling until paypal is available or component destroyed
*/
/**
* Used when there are multiple paypal components on the same page beacuse only 1 of them
* may register paypal script. The other has to be polling until paypal is available or component destroyed
* @return {?}
*/
NgxPaypalComponent.prototype.pollUntilScriptAvailable = /**
* Used when there are multiple paypal components on the same page beacuse only 1 of them
* may register paypal script. The other has to be polling until paypal is available or component destroyed
* @return {?}
*/
function () {
var _this = this;
/** @type {?} */
var obs = interval(this.defaultPollInterval)
.pipe(takeUntil(this.ngUnsubscribe), map(function (x) {
if (x >= _this.maximumPollWaitTime) {
console.warn("PayPal script was not loaded after '" + _this.maximumPollWaitTime + "' maximum polling time.");
obs.unsubscribe();
return;
}
// check if paypal script exists
if (window[_this.paypalWindowName]) {
// register script
_this.handleScriptRegistering();
// stop execution
obs.unsubscribe();
}
}))
.subscribe();
};
/**
* @return {?}
*/
NgxPaypalComponent.prototype.addPayPalScriptToPage = /**
* @return {?}
*/
function () {
var _this = this;
/** @type {?} */
var script = document.createElement('script');
script.innerHTML = '';
script.src = this.paypalScriptUrl;
script.onload = function () { return _this.handleScriptRegistering(); };
script.async = true;
script.defer = true;
this.paypalScriptElem.nativeElement.appendChild(script);
};
/**
* @return {?}
*/
NgxPaypalComponent.prototype.handleScriptRegistering = /**
* @return {?}
*/
function () {
// check if container with requested id exists
// this is here because dynamically switching between components would cause PayPal to
// throw an error if the container already existed before
if (this._payPalButtonContainerElem && this._payPalButtonContainerElem.nativeElement &&
this._payPalButtonContainerElem.nativeElement.id === this.payPalButtonContainerId) {
// container is ready, setup script right away
this.setupScript();
}
else {
// container is not ready, delay registering until it is
this.registerPayPalScriptWhenContainerIsReady = true;
}
};
/**
* @return {?}
*/
NgxPaypalComponent.prototype.setupScript = /**
* @return {?}
*/
function () {
var _this = this;
// first clear container
if (!this._payPalButtonContainerElem) {
throw Error("Cannot setup script because paypal button container with id '" + this.payPalButtonContainerId + "' is not yet ready");
}
this._payPalButtonContainerElem.nativeElement.innerHTML = '';
if (!window[this.paypalWindowName]) {
throw Error('PayPal script is not available');
}
// render PayPal button as per their docs at
// https://developer.paypal.com/docs/integration/direct/express-checkout/integration-jsv4/add-paypal-button/
window[this.paypalWindowName].Button.render({
// set environment
env: this.config.environment.toString(),
// Show the buyer a 'Pay Now' button in the checkout flow
commit: this.config.commit,
// init client for client side integration
client: this.getClient(),
// set button config if available
style: this.config.button,
// set funding if available
funding: this.getFunding(),
// payment() is called when the button is clicked
payment: function (data, actions) {
if (_this.config.integrationType === PayPalIntegrationType.ServerSideREST) {
// client needs to create payment on server side
if (!_this.config.payment) {
throw Error("You need set up a create payment method and return\n PayPal's payment id when using server side integration");
}
// Paypal expects promise with payment id (string) to be returned
return _this.config.payment().toPromise()
.then(function (paymentId) {
return paymentId;
});
}
if (_this.config.integrationType === PayPalIntegrationType.ClientSideREST) {
if (!_this.config.transactions || !Array.isArray(_this.config.transactions) || _this.config.transactions.length <= 0) {
throw Error("You need to provide at least 1 transaction for client side integration");
}
/** @type {?} */
var experienceConfig = _this.config.experience;
return actions.payment.create({
payment: {
// Allow user to specifify intent, else use default 'sale'.
intent: _this.config.intent ? _this.config.intent : 'sale',
transactions: _this.config.transactions
},
experience: {
input_fields: {
no_shipping: (experienceConfig && experienceConfig.noShipping) ? 1 : 0
},
presentation: {
brand_name: (experienceConfig && experienceConfig.brandName) ? experienceConfig.brandName : null,
logo_image: (experienceConfig && experienceConfig.logoImage) ? experienceConfig.logoImage : null,
locale_code: (experienceConfig && experienceConfig.localeCode) ? experienceConfig.localeCode : null
}
}
});
}
},
// onAuthorize() is called when the buyer approves the payment
onAuthorize: function (data, actions) {
if (_this.config.integrationType === PayPalIntegrationType.ServerSideREST) {
// client needs to server to execute the payment
if (!_this.config.onAuthorize) {
throw Error("You need set up an execute method when using server side integration");
}
// Paypal expects promise
return _this.config.onAuthorize(data, actions).toPromise();
}
if (_this.config.integrationType === PayPalIntegrationType.ClientSideREST) {
// Make a call to the REST api to execute the payment
return actions.payment.execute().then(function () {
if (!_this.config.onPaymentComplete) {
throw Error("You should provide some callback when payment is finished when using client side integration");
}
_this.config.onPaymentComplete(data, actions);
});
}
},
onError: function (err) {
if (_this.config.onError) {
_this.config.onError(err);
}
},
onCancel: function (data, actions) {
if (_this.config.onCancel) {
_this.config.onCancel(data, actions);
}
},
onClick: function () {
if (_this.config.onClick) {
_this.config.onClick();
}
},
validate: function (actions) {
if (_this.config.validate) {
_this.config.validate(actions);
}
}
}, "#" + this.payPalButtonContainerId);
};
/**
* @return {?}
*/
NgxPaypalComponent.prototype.getClient = /**
* @return {?}
*/
function () {
if (this.config.integrationType === PayPalIntegrationType.ClientSideREST) {
if (!this.config.client) {
throw Error("You need to setup client information when using client side integration");
}
return {
production: this.config.client.production,
sandbox: this.config.client.sandbox
};
}
return undefined;
};
/**
* @return {?}
*/
NgxPaypalComponent.prototype.getFunding = /**
* @return {?}
*/
function () {
var _this = this;
// resolve funding to use paypal's properties
if (!this.config.funding) {
// no funding provided
return undefined;
}
/** @type {?} */
var allowed = [];
/** @type {?} */
var disallowed = [];
if (this.config.funding.allowed) {
this.config.funding.allowed.forEach(function (type) {
allowed.push(_this.mapFundingType(type));
});
}
if (this.config.funding.disallowed) {
this.config.funding.disallowed.forEach(function (type) {
disallowed.push(_this.mapFundingType(type));
});
}
return {
allowed: allowed,
disallowed: disallowed
};
};
/**
* @param {?} type
* @return {?}
*/
NgxPaypalComponent.prototype.mapFundingType = /**
* @param {?} type
* @return {?}
*/
function (type) {
if (type === PayPalFunding.Card) {
return paypal.FUNDING.CARD;
}
if (type === PayPalFunding.Credit) {
return paypal.FUNDING.CREDIT;
}
if (type === PayPalFunding.Elv) {
return paypal.FUNDING.ELV;
}
throw Error("Unsupported funding type '" + type + "'");
};
NgxPaypalComponent.decorators = [
{ type: Component, args: [{
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'ngx-paypal',
template: "\n <div #payPalScriptElem></div>\n <div #payPalButtonContainerElem [id]=\"payPalButtonContainerId\"></div>\n "
}] }
];
/** @nocollapse */
NgxPaypalComponent.ctorParameters = function () { return []; };
NgxPaypalComponent.propDecorators = {
config: [{ type: Input }],
useGlobalConfig: [{ type: Input }],
paypalScriptElem: [{ type: ViewChild, args: ['payPalScriptElem',] }],
payPalButtonContainerElem: [{ type: ViewChild, args: ['payPalButtonContainerElem',] }]
};
return NgxPaypalComponent;
}());
export { NgxPaypalComponent };
if (false) {
/**
* Configuration for paypal.
* @type {?}
*/
NgxPaypalComponent.prototype.config;
/**
* Indicates if global configuration (provided via 'forRoot') is used
* @type {?}
*/
NgxPaypalComponent.prototype.useGlobalConfig;
/**
* Container for paypal script
* @type {?}
*/
NgxPaypalComponent.prototype.paypalScriptElem;
/**
* Used for indicating delayed rendered if container is not yet ready in DOM
* @type {?}
*/
NgxPaypalComponent.prototype.registerPayPalScriptWhenContainerIsReady;
/**
* Holds current container element
* @type {?}
*/
NgxPaypalComponent.prototype._payPalButtonContainerElem;
/**
* Polling interval if paypal script is pending
* @type {?}
*/
NgxPaypalComponent.prototype.defaultPollInterval;
/**
* Polling will stop after polling reaches this number
* @type {?}
*/
NgxPaypalComponent.prototype.maximumPollWaitTime;
/**
* Name of the global variable where paypal is stored
* @type {?}
*/
NgxPaypalComponent.prototype.paypalWindowName;
/**
* Name of the global variable indicating that script was initiated (added to page)
* @type {?}
*/
NgxPaypalComponent.prototype.paypalWindowScriptInitiated;
/**
* PayPal integration script url
* @type {?}
*/
NgxPaypalComponent.prototype.paypalScriptUrl;
/**
* Id of the element where PayPal button will be rendered
* @type {?}
*/
NgxPaypalComponent.prototype.payPalButtonContainerId;
/** @type {?} */
NgxPaypalComponent.prototype.payPalButtonContainerIdPrefix;
/** @type {?} */
NgxPaypalComponent.prototype.ngUnsubscribe;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF5cGFsLWNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25neC1wYXlwYWwtd2l0aC1pbnRlbnQvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9wYXlwYWwtY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBRUgsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsS0FBSyxFQUlMLFNBQVMsR0FDWixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN6QyxPQUFPLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRWhELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUNyRSxPQUFPLEVBQTZDLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBT2xHO0lBMEVJOzs7O1FBeERTLG9CQUFlLEdBQUcsS0FBSyxDQUFDOzs7O1FBVXpCLDZDQUF3QyxHQUFHLEtBQUssQ0FBQzs7OztRQWV4Qyx3QkFBbUIsR0FBRyxFQUFFLENBQUM7Ozs7UUFLekIsd0JBQW1CLEdBQUcsSUFBSSxDQUFDOzs7O1FBSzNCLHFCQUFnQixHQUFHLFFBQVEsQ0FBQzs7OztRQUs1QixnQ0FBMkIsR0FBRyw2QkFBNkIsQ0FBQzs7OztRQUs1RCxvQkFBZSxHQUFHLCtDQUErQyxDQUFDO1FBT2xFLGtDQUE2QixHQUFHLDhCQUE4QixDQUFDO1FBRS9ELGtCQUFhLEdBQWtCLElBQUksT0FBTyxFQUFRLENBQUM7SUFJcEUsQ0FBQztJQTFDRCxzQkFBNEMseURBQXlCOzs7OztRQUFyRSxVQUFzRSxPQUFtQjtZQUNyRixJQUFJLE9BQU8sRUFBRTtnQkFDVCxJQUFJLENBQUMsMEJBQTBCLEdBQUcsT0FBTyxDQUFDO2FBQzdDO1FBQ0wsQ0FBQzs7O09BQUE7Ozs7O0lBd0NELHdDQUFXOzs7O0lBQVgsVUFBWSxPQUFzQjtRQUM5QixzQ0FBc0M7UUFDdEMsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ2IsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1NBQ3JCO0lBQ0wsQ0FBQzs7OztJQUVELDRDQUFlOzs7SUFBZjtRQUNJLDZDQUE2QztRQUM3QyxJQUFJLElBQUksQ0FBQyx3Q0FBd0MsSUFBSSxJQUFJLENBQUMsMEJBQTBCLEVBQUU7WUFDbEYsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ25CLElBQUksQ0FBQyx3Q0FBd0MsR0FBRyxLQUFLLENBQUM7U0FDekQ7SUFDTCxDQUFDOzs7O0lBRUQsd0NBQVc7OztJQUFYO1FBQ0ksSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUMxQixJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2xDLENBQUM7Ozs7SUFFTyx1Q0FBVTs7O0lBQWxCO1FBQ0ksd0NBQXdDO1FBQ3hDLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxLQUFHLElBQUksQ0FBQyw2QkFBNkIsR0FBRyxJQUFJLENBQUMscUJBQXFCLEVBQUksQ0FBQztRQUN0Ryw2RUFBNkU7UUFDN0UsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRTtZQUNoQyw2QkFBNkI7WUFDN0IsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLDJCQUEyQixDQUFDLEtBQUssSUFBSSxFQUFFO2dCQUNuRCxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQzthQUNuQztpQkFBTTtnQkFDSCxzQ0FBc0M7Z0JBQ3RDLE1BQU0sQ0FBQyxJQUFJLENBQUMsMkJBQTJCLENBQUMsR0FBRyxJQUFJLENBQUM7Z0JBQ2hELElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO2FBQ2hDO1NBRUo7YUFBTTtZQUNILHdCQUF3QjtZQUN4QixJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztTQUNsQztJQUNMLENBQUM7Ozs7SUFFTyxrREFBcUI7OztJQUE3QjtRQUNJLE9BQU8sSUFBSSxJQUFJLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNoQyxDQUFDO0lBRUQ7OztPQUdHOzs7Ozs7SUFDSyxxREFBd0I7Ozs7O0lBQWhDO1FBQUEsaUJBc0JDOztZQXJCUyxHQUFHLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQzthQUN6QyxJQUFJLENBQ0QsU0FBUyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsRUFDN0IsR0FBRyxDQUFDLFVBQUMsQ0FBQztZQUNGLElBQUksQ0FBQyxJQUFJLEtBQUksQ0FBQyxtQkFBbUIsRUFBRTtnQkFDL0IsT0FBTyxDQUFDLElBQUksQ0FBQyx5Q0FBdUMsS0FBSSxDQUFDLG1CQUFtQiw0QkFBeUIsQ0FBQyxDQUFDO2dCQUN2RyxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQ2xCLE9BQU87YUFDVjtZQUVELGdDQUFnQztZQUNoQyxJQUFJLE1BQU0sQ0FBQyxLQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRTtnQkFDL0Isa0JBQWtCO2dCQUNsQixLQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztnQkFFL0IsaUJBQWlCO2dCQUNqQixHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7YUFDckI7UUFDTCxDQUFDLENBQUMsQ0FDTDthQUNBLFNBQVMsRUFBRTtJQUNwQixDQUFDOzs7O0lBRU8sa0RBQXFCOzs7SUFBN0I7UUFBQSxpQkFTQzs7WUFSUyxNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUM7UUFDL0MsTUFBTSxDQUFDLFNBQVMsR0FBRyxFQUFFLENBQUM7UUFDdEIsTUFBTSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDO1FBQ2xDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsY0FBTSxPQUFBLEtBQUksQ0FBQyx1QkFBdUIsRUFBRSxFQUE5QixDQUE4QixDQUFDO1FBQ3JELE1BQU0sQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBRXBCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzVELENBQUM7Ozs7SUFFTyxvREFBdUI7OztJQUEvQjtRQUNJLDhDQUE4QztRQUM5QyxzRkFBc0Y7UUFDdEYseURBQXlEO1FBQ3pELElBQUksSUFBSSxDQUFDLDBCQUEwQixJQUFJLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxhQUFhO1lBQ2hGLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxhQUFhLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQyx1QkFBdUIsRUFBRTtZQUNuRiw4Q0FBOEM7WUFDOUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1NBQ3RCO2FBQU07WUFDSCx3REFBd0Q7WUFDeEQsSUFBSSxDQUFDLHdDQUF3QyxHQUFHLElBQUksQ0FBQztTQUN4RDtJQUNMLENBQUM7Ozs7SUFFTyx3Q0FBVzs7O0lBQW5CO1FBQUEsaUJBcUhDO1FBcEhHLHdCQUF3QjtRQUN4QixJQUFJLENBQUMsSUFBSSxDQUFDLDBCQUEwQixFQUFFO1lBQ2xDLE1BQU0sS0FBSyxDQUFDLGtFQUFnRSxJQUFJLENBQUMsdUJBQXVCLHVCQUFvQixDQUFDLENBQUM7U0FDakk7UUFFRCxJQUFJLENBQUMsMEJBQTBCLENBQUMsYUFBYSxDQUFDLFNBQVMsR0FBRyxFQUFFLENBQUM7UUFFN0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsRUFBRTtZQUNoQyxNQUFNLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1NBQ2pEO1FBRUQsNENBQTRDO1FBQzVDLDRHQUE0RztRQUM1RyxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQzs7WUFFeEMsR0FBRyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRTs7WUFHdkMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTTs7WUFHMUIsTUFBTSxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUU7O1lBR3hCLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU07O1lBR3pCLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFOztZQUcxQixPQUFPLEVBQUUsVUFBQyxJQUFJLEVBQUUsT0FBTztnQkFDbkIsSUFBSSxLQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsS0FBSyxxQkFBcUIsQ0FBQyxjQUFjLEVBQUU7b0JBQ3RFLGdEQUFnRDtvQkFDaEQsSUFBSSxDQUFDLEtBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO3dCQUN0QixNQUFNLEtBQUssQ0FBQyx3SUFDK0MsQ0FBQyxDQUFDO3FCQUNoRTtvQkFFRCxpRUFBaUU7b0JBQ2pFLE9BQU8sS0FBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxTQUFTLEVBQUU7eUJBQ25DLElBQUksQ0FBQyxVQUFBLFNBQVM7d0JBQ1gsT0FBTyxTQUFTLENBQUM7b0JBQ3JCLENBQUMsQ0FBQyxDQUFDO2lCQUNWO2dCQUVELElBQUksS0FBSSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEtBQUsscUJBQXFCLENBQUMsY0FBYyxFQUFFO29CQUN0RSxJQUFJLENBQUMsS0FBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksS0FBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsTUFBTSxJQUFJLENBQUMsRUFBRTt3QkFDL0csTUFBTSxLQUFLLENBQUMsd0VBQXdFLENBQUMsQ0FBQztxQkFDekY7O3dCQUVLLGdCQUFnQixHQUFHLEtBQUksQ0FBQyxNQUFNLENBQUMsVUFBVTtvQkFDL0MsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQzt3QkFDMUIsT0FBTyxFQUFFOzs0QkFFTCxNQUFNLEVBQUUsS0FBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNOzRCQUN4RCxZQUFZLEVBQUUsS0FBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZO3lCQUN6Qzt3QkFDRCxVQUFVLEVBQUU7NEJBQ1IsWUFBWSxFQUFFO2dDQUNWLFdBQVcsRUFBRSxDQUFDLGdCQUFnQixJQUFJLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7NkJBQ3pFOzRCQUNELFlBQVksRUFBRTtnQ0FDVixVQUFVLEVBQUUsQ0FBQyxnQkFBZ0IsSUFBSSxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dDQUNoRyxVQUFVLEVBQUUsQ0FBQyxnQkFBZ0IsSUFBSSxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJO2dDQUNoRyxXQUFXLEVBQUUsQ0FBQyxnQkFBZ0IsSUFBSSxnQkFBZ0IsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJOzZCQUN0Rzt5QkFDSjtxQkFDSixDQUFDLENBQUM7aUJBQ047WUFDTCxDQUFDOztZQUdELFdBQVcsRUFBRSxVQUFDLElBQWdDLEVBQUUsT0FBWTtnQkFDeEQsSUFBSSxLQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsS0FBSyxxQkFBcUIsQ0FBQyxjQUFjLEVBQUU7b0JBQ3RFLGdEQUFnRDtvQkFDaEQsSUFBSSxDQUFDLEtBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFO3dCQUMxQixNQUFNLEtBQUssQ0FBQyxzRUFBc0UsQ0FBQyxDQUFDO3FCQUN2RjtvQkFFRCx5QkFBeUI7b0JBQ3pCLE9BQU8sS0FBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDO2lCQUM3RDtnQkFFRCxJQUFJLEtBQUksQ0FBQyxNQUFNLENBQUMsZUFBZSxLQUFLLHFCQUFxQixDQUFDLGNBQWMsRUFBRTtvQkFDdEUscURBQXFEO29CQUNyRCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDO3dCQUNsQyxJQUFJLENBQUMsS0FBSSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsRUFBRTs0QkFDaEMsTUFBTSxLQUFLLENBQUMsOEZBQThGLENBQUMsQ0FBQzt5QkFDL0c7d0JBQ0QsS0FBSSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7b0JBQ2pELENBQUMsQ0FBQyxDQUFDO2lCQUNOO1lBQ0wsQ0FBQztZQUVELE9BQU8sRUFBRSxVQUFDLEdBQUc7Z0JBQ1QsSUFBSSxLQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTtvQkFDckIsS0FBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7aUJBQzVCO1lBQ0wsQ0FBQztZQUVELFFBQVEsRUFBRSxVQUFDLElBQUksRUFBRSxPQUFPO2dCQUNwQixJQUFJLEtBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO29CQUN0QixLQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUM7aUJBQ3ZDO1lBQ0wsQ0FBQztZQUNELE9BQU8sRUFBRTtnQkFDTCxJQUFJLEtBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO29CQUNyQixLQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO2lCQUN6QjtZQUNMLENBQUM7WUFDRCxRQUFRLEVBQUUsVUFBQyxPQUFPO2dCQUNkLElBQUksS0FBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUU7b0JBQ3RCLEtBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2lCQUNqQztZQUNMLENBQUM7U0FDSixFQUFFLE1BQUksSUFBSSxDQUFDLHVCQUF5QixDQUFDLENBQUM7SUFDM0MsQ0FBQzs7OztJQUVPLHNDQUFTOzs7SUFBakI7UUFDSSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsZUFBZSxLQUFLLHFCQUFxQixDQUFDLGNBQWMsRUFBRTtZQUN0RSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUU7Z0JBQ3JCLE1BQU0sS0FBSyxDQUFDLHlFQUF5RSxDQUFDLENBQUM7YUFDMUY7WUFFRCxPQUFPO2dCQUNILFVBQVUsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVO2dCQUN6QyxPQUFPLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTzthQUN0QyxDQUFDO1NBQ0w7UUFFRCxPQUFPLFNBQVMsQ0FBQztJQUNyQixDQUFDOzs7O0lBRU8sdUNBQVU7OztJQUFsQjtRQUFBLGlCQTZCQztRQXpCRyw2Q0FBNkM7UUFDN0MsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1lBQ3RCLHNCQUFzQjtZQUN0QixPQUFPLFNBQVMsQ0FBQztTQUNwQjs7WUFFSyxPQUFPLEdBQVUsRUFBRTs7WUFDbkIsVUFBVSxHQUFVLEVBQUU7UUFFNUIsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUU7WUFDN0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxVQUFBLElBQUk7Z0JBQ3BDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzVDLENBQUMsQ0FBQyxDQUFDO1NBQ047UUFFRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRTtZQUNoQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLFVBQUEsSUFBSTtnQkFDdkMsVUFBVSxDQUFDLElBQUksQ0FBQyxLQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDL0MsQ0FBQyxDQUFDLENBQUM7U0FDTjtRQUVELE9BQU87WUFDSCxPQUFPLEVBQUUsT0FBTztZQUNoQixVQUFVLEVBQUUsVUFBVTtTQUN6QixDQUFDO0lBQ04sQ0FBQzs7Ozs7SUFFTywyQ0FBYzs7OztJQUF0QixVQUF1QixJQUFtQjtRQUN0QyxJQUFJLElBQUksS0FBSyxhQUFhLENBQUMsSUFBSSxFQUFFO1lBQzdCLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7U0FDOUI7UUFDRCxJQUFJLElBQUksS0FBSyxhQUFhLENBQUMsTUFBTSxFQUFFO1lBQy9CLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7U0FDaEM7UUFDRCxJQUFJLElBQUksS0FBSyxhQUFhLENBQUMsR0FBRyxFQUFFO1lBQzVCLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUM7U0FDN0I7UUFDRCxNQUFNLEtBQUssQ0FBQywrQkFBNkIsSUFBSSxNQUFHLENBQUMsQ0FBQztJQUN0RCxDQUFDOztnQkEvVkosU0FBUyxTQUFDO29CQUNQLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO29CQUMvQyxRQUFRLEVBQUUsWUFBWTtvQkFDdEIsUUFBUSxFQUFFLHdIQUdUO2lCQUNKOzs7Ozt5QkFNSSxLQUFLO2tDQUtMLEtBQUs7bUNBS0wsU0FBUyxTQUFDLGtCQUFrQjs0Q0FXNUIsU0FBUyxTQUFDLDJCQUEyQjs7SUE4VDFDLHlCQUFDO0NBQUEsQUFoV0QsSUFnV0M7U0F4Vlksa0JBQWtCOzs7Ozs7SUFLM0Isb0NBQThCOzs7OztJQUs5Qiw2Q0FBaUM7Ozs7O0lBS2pDLDhDQUE0RDs7Ozs7SUFLNUQsc0VBQXlEOzs7OztJQUt6RCx3REFBZ0Q7Ozs7O0lBVWhELGlEQUEwQzs7Ozs7SUFLMUMsaURBQTRDOzs7OztJQUs1Qyw4Q0FBNkM7Ozs7O0lBSzdDLHlEQUE2RTs7Ozs7SUFLN0UsNkNBQW1GOzs7OztJQUtuRixxREFBd0M7O0lBRXhDLDJEQUFnRjs7SUFFaEYsMkNBQW9FIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBBZnRlclZpZXdJbml0LFxuICAgIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICAgIENvbXBvbmVudCxcbiAgICBFbGVtZW50UmVmLFxuICAgIElucHV0LFxuICAgIE9uQ2hhbmdlcyxcbiAgICBPbkRlc3Ryb3ksXG4gICAgU2ltcGxlQ2hhbmdlcyxcbiAgICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaW50ZXJ2YWwsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBQYXlQYWxGdW5kaW5nIH0gZnJvbSAnLi4vbW9kZWxzL3BheXBhbC1mdW5kaW5nJztcbmltcG9ydCB7IFBheVBhbEludGVncmF0aW9uVHlwZSB9IGZyb20gJy4uL21vZGVscy9wYXlwYWwtaW50ZWdyYXRpb24nO1xuaW1wb3J0IHsgSVBheXBhbENsaWVudCwgSVBheVBhbFBheW1lbnRDb21wbGV0ZURhdGEsIFBheVBhbENvbmZpZyB9IGZyb20gJy4uL21vZGVscy9wYXlwYWwtbW9kZWxzJztcblxuLyoqXG4gKiBHbG9iYWwgdmFyaWFibGUgd2hlcmUgUGF5UGFsIGlzIGxvYWRlZCB0b1xuICovXG5kZWNsYXJlIHZhciBwYXlwYWw6IGFueTtcblxuQENvbXBvbmVudCh7XG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gICAgc2VsZWN0b3I6ICduZ3gtcGF5cGFsJyxcbiAgICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgI3BheVBhbFNjcmlwdEVsZW0+PC9kaXY+XG4gICAgPGRpdiAjcGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbSBbaWRdPVwicGF5UGFsQnV0dG9uQ29udGFpbmVySWRcIj48L2Rpdj5cbiAgICBgXG59KVxuZXhwb3J0IGNsYXNzIE5neFBheXBhbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcblxuICAgIC8qKlxuICAgICAqIENvbmZpZ3VyYXRpb24gZm9yIHBheXBhbC5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBjb25maWc6IFBheVBhbENvbmZpZztcblxuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyBpZiBnbG9iYWwgY29uZmlndXJhdGlvbiAocHJvdmlkZWQgdmlhICdmb3JSb290JykgaXMgdXNlZFxuICAgICAqL1xuICAgIEBJbnB1dCgpIHVzZUdsb2JhbENvbmZpZyA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQ29udGFpbmVyIGZvciBwYXlwYWwgc2NyaXB0XG4gICAgICovXG4gICAgQFZpZXdDaGlsZCgncGF5UGFsU2NyaXB0RWxlbScpIHBheXBhbFNjcmlwdEVsZW06IEVsZW1lbnRSZWY7XG5cbiAgICAvKipcbiAgICAgKiBVc2VkIGZvciBpbmRpY2F0aW5nIGRlbGF5ZWQgcmVuZGVyZWQgaWYgY29udGFpbmVyIGlzIG5vdCB5ZXQgcmVhZHkgaW4gRE9NXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWdpc3RlclBheVBhbFNjcmlwdFdoZW5Db250YWluZXJJc1JlYWR5ID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBIb2xkcyBjdXJyZW50IGNvbnRhaW5lciBlbGVtZW50XG4gICAgICovXG4gICAgcHJpdmF0ZSBfcGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbT86IEVsZW1lbnRSZWY7XG4gICAgQFZpZXdDaGlsZCgncGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbScpIHNldCBwYXlQYWxCdXR0b25Db250YWluZXJFbGVtKGNvbnRlbnQ6IEVsZW1lbnRSZWYpIHtcbiAgICAgICAgaWYgKGNvbnRlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuX3BheVBhbEJ1dHRvbkNvbnRhaW5lckVsZW0gPSBjb250ZW50O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUG9sbGluZyBpbnRlcnZhbCBpZiBwYXlwYWwgc2NyaXB0IGlzIHBlbmRpbmdcbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHRQb2xsSW50ZXJ2YWwgPSA1MDtcblxuICAgIC8qKlxuICAgICAqIFBvbGxpbmcgd2lsbCBzdG9wIGFmdGVyIHBvbGxpbmcgcmVhY2hlcyB0aGlzIG51bWJlclxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgbWF4aW11bVBvbGxXYWl0VGltZSA9IDUwMDA7XG5cbiAgICAvKipcbiAgICAqIE5hbWUgb2YgdGhlIGdsb2JhbCB2YXJpYWJsZSB3aGVyZSBwYXlwYWwgaXMgc3RvcmVkXG4gICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IHBheXBhbFdpbmRvd05hbWUgPSAncGF5cGFsJztcblxuICAgIC8qKlxuICAgICAqIE5hbWUgb2YgdGhlIGdsb2JhbCB2YXJpYWJsZSBpbmRpY2F0aW5nIHRoYXQgc2NyaXB0IHdhcyBpbml0aWF0ZWQgKGFkZGVkIHRvIHBhZ2UpXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBwYXlwYWxXaW5kb3dTY3JpcHRJbml0aWF0ZWQgPSAnbmd4LXBheXBhbC1zY3JpcHQtaW5pdGlhdGVkJztcblxuICAgIC8qKlxuICAgICAqIFBheVBhbCBpbnRlZ3JhdGlvbiBzY3JpcHQgdXJsXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBwYXlwYWxTY3JpcHRVcmwgPSAnaHR0cHM6Ly93d3cucGF5cGFsb2JqZWN0cy5jb20vYXBpL2NoZWNrb3V0LmpzJztcblxuICAgIC8qKlxuICAgICAqIElkIG9mIHRoZSBlbGVtZW50IHdoZXJlIFBheVBhbCBidXR0b24gd2lsbCBiZSByZW5kZXJlZFxuICAgICAqL1xuICAgIHB1YmxpYyBwYXlQYWxCdXR0b25Db250YWluZXJJZD86IHN0cmluZztcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgcGF5UGFsQnV0dG9uQ29udGFpbmVySWRQcmVmaXggPSAnbmd4LXBheXBhbC1idXR0b24tY29udGFpbmVyLSc7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IG5nVW5zdWJzY3JpYmU6IFN1YmplY3Q8dm9pZD4gPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgKSB7XG4gICAgfVxuXG4gICAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgICAgICAvLyBpbml0IHdoZW4gY29uZmlnIG9uY2UgaXRzIGF2YWlsYWJsZVxuICAgICAgICBpZiAodGhpcy5jb25maWcpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFBheVBhbCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgICAvLyByZWdpc3RlciBzY3JpcHQgaWYgZWxlbWVudCBpcyByZWFkeSBpbiBkb21cbiAgICAgICAgaWYgKHRoaXMucmVnaXN0ZXJQYXlQYWxTY3JpcHRXaGVuQ29udGFpbmVySXNSZWFkeSAmJiB0aGlzLl9wYXlQYWxCdXR0b25Db250YWluZXJFbGVtKSB7XG4gICAgICAgICAgICB0aGlzLnNldHVwU2NyaXB0KCk7XG4gICAgICAgICAgICB0aGlzLnJlZ2lzdGVyUGF5UGFsU2NyaXB0V2hlbkNvbnRhaW5lcklzUmVhZHkgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLm5nVW5zdWJzY3JpYmUubmV4dCgpO1xuICAgICAgICB0aGlzLm5nVW5zdWJzY3JpYmUuY29tcGxldGUoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRQYXlQYWwoKTogdm9pZCB7XG4gICAgICAgIC8vIHNldCB1bmlxdWUgcGF5cGFsIGNvbnRhaW5lciBidXR0b24gaWRcbiAgICAgICAgdGhpcy5wYXlQYWxCdXR0b25Db250YWluZXJJZCA9IGAke3RoaXMucGF5UGFsQnV0dG9uQ29udGFpbmVySWRQcmVmaXh9JHt0aGlzLmdldFBzZXVkb1VuaXF1ZU51bWJlcigpfWA7XG4gICAgICAgIC8vIGNoZWNrIGlmIHBheXBhbCB3YXMgYWxyZWFkeSByZWdpc3RlciBhbmQgaWYgc28sIGRvbid0IGFkZCBpdCB0byBwYWdlIGFnYWluXG4gICAgICAgIGlmICghd2luZG93W3RoaXMucGF5cGFsV2luZG93TmFtZV0pIHtcbiAgICAgICAgICAgIC8vIGNoZWNrIGlmIHNjcmlwdCBpcyBwZW5kaW5nXG4gICAgICAgICAgICBpZiAod2luZG93W3RoaXMucGF5cGFsV2luZG93U2NyaXB0SW5pdGlhdGVkXSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMucG9sbFVudGlsU2NyaXB0QXZhaWxhYmxlKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIHJlZ2lzdGVyIHNjcmlwdCBhbmQgc2V0IGdsb2JhbCBmbGFnXG4gICAgICAgICAgICAgICAgd2luZG93W3RoaXMucGF5cGFsV2luZG93U2NyaXB0SW5pdGlhdGVkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRQYXlQYWxTY3JpcHRUb1BhZ2UoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8ganVzdCByZWdpc3RlciBwYXltZW50XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVNjcmlwdFJlZ2lzdGVyaW5nKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFBzZXVkb1VuaXF1ZU51bWJlcigpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gbmV3IERhdGUoKS52YWx1ZU9mKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlZCB3aGVuIHRoZXJlIGFyZSBtdWx0aXBsZSBwYXlwYWwgY29tcG9uZW50cyBvbiB0aGUgc2FtZSBwYWdlIGJlYWN1c2Ugb25seSAxIG9mIHRoZW1cbiAgICAgKiBtYXkgcmVnaXN0ZXIgcGF5cGFsIHNjcmlwdC4gVGhlIG90aGVyIGhhcyB0byBiZSBwb2xsaW5nIHVudGlsIHBheXBhbCBpcyBhdmFpbGFibGUgb3IgY29tcG9uZW50IGRlc3Ryb3llZFxuICAgICAqL1xuICAgIHByaXZhdGUgcG9sbFVudGlsU2NyaXB0QXZhaWxhYmxlKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBvYnMgPSBpbnRlcnZhbCh0aGlzLmRlZmF1bHRQb2xsSW50ZXJ2YWwpXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICB0YWtlVW50aWwodGhpcy5uZ1Vuc3Vic2NyaWJlKSxcbiAgICAgICAgICAgICAgICBtYXAoKHgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHggPj0gdGhpcy5tYXhpbXVtUG9sbFdhaXRUaW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYFBheVBhbCBzY3JpcHQgd2FzIG5vdCBsb2FkZWQgYWZ0ZXIgJyR7dGhpcy5tYXhpbXVtUG9sbFdhaXRUaW1lfScgbWF4aW11bSBwb2xsaW5nIHRpbWUuYCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYnMudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIHBheXBhbCBzY3JpcHQgZXhpc3RzXG4gICAgICAgICAgICAgICAgICAgIGlmICh3aW5kb3dbdGhpcy5wYXlwYWxXaW5kb3dOYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVnaXN0ZXIgc2NyaXB0XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZVNjcmlwdFJlZ2lzdGVyaW5nKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0b3AgZXhlY3V0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBvYnMudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhZGRQYXlQYWxTY3JpcHRUb1BhZ2UoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuICAgICAgICBzY3JpcHQuaW5uZXJIVE1MID0gJyc7XG4gICAgICAgIHNjcmlwdC5zcmMgPSB0aGlzLnBheXBhbFNjcmlwdFVybDtcbiAgICAgICAgc2NyaXB0Lm9ubG9hZCA9ICgpID0+IHRoaXMuaGFuZGxlU2NyaXB0UmVnaXN0ZXJpbmcoKTtcbiAgICAgICAgc2NyaXB0LmFzeW5jID0gdHJ1ZTtcbiAgICAgICAgc2NyaXB0LmRlZmVyID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLnBheXBhbFNjcmlwdEVsZW0ubmF0aXZlRWxlbWVudC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGFuZGxlU2NyaXB0UmVnaXN0ZXJpbmcoKTogdm9pZCB7XG4gICAgICAgIC8vIGNoZWNrIGlmIGNvbnRhaW5lciB3aXRoIHJlcXVlc3RlZCBpZCBleGlzdHNcbiAgICAgICAgLy8gdGhpcyBpcyBoZXJlIGJlY2F1c2UgZHluYW1pY2FsbHkgc3dpdGNoaW5nIGJldHdlZW4gY29tcG9uZW50cyB3b3VsZCBjYXVzZSBQYXlQYWwgdG9cbiAgICAgICAgLy8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIGNvbnRhaW5lciBhbHJlYWR5IGV4aXN0ZWQgYmVmb3JlXG4gICAgICAgIGlmICh0aGlzLl9wYXlQYWxCdXR0b25Db250YWluZXJFbGVtICYmIHRoaXMuX3BheVBhbEJ1dHRvbkNvbnRhaW5lckVsZW0ubmF0aXZlRWxlbWVudCAmJlxuICAgICAgICAgICAgdGhpcy5fcGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbS5uYXRpdmVFbGVtZW50LmlkID09PSB0aGlzLnBheVBhbEJ1dHRvbkNvbnRhaW5lcklkKSB7XG4gICAgICAgICAgICAvLyBjb250YWluZXIgaXMgcmVhZHksIHNldHVwIHNjcmlwdCByaWdodCBhd2F5XG4gICAgICAgICAgICB0aGlzLnNldHVwU2NyaXB0KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBjb250YWluZXIgaXMgbm90IHJlYWR5LCBkZWxheSByZWdpc3RlcmluZyB1bnRpbCBpdCBpc1xuICAgICAgICAgICAgdGhpcy5yZWdpc3RlclBheVBhbFNjcmlwdFdoZW5Db250YWluZXJJc1JlYWR5ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc2V0dXBTY3JpcHQoKTogdm9pZCB7XG4gICAgICAgIC8vIGZpcnN0IGNsZWFyIGNvbnRhaW5lclxuICAgICAgICBpZiAoIXRoaXMuX3BheVBhbEJ1dHRvbkNvbnRhaW5lckVsZW0pIHtcbiAgICAgICAgICAgIHRocm93IEVycm9yKGBDYW5ub3Qgc2V0dXAgc2NyaXB0IGJlY2F1c2UgcGF5cGFsIGJ1dHRvbiBjb250YWluZXIgd2l0aCBpZCAnJHt0aGlzLnBheVBhbEJ1dHRvbkNvbnRhaW5lcklkfScgaXMgbm90IHlldCByZWFkeWApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fcGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbS5uYXRpdmVFbGVtZW50LmlubmVySFRNTCA9ICcnO1xuXG4gICAgICAgIGlmICghd2luZG93W3RoaXMucGF5cGFsV2luZG93TmFtZV0pIHtcbiAgICAgICAgICAgIHRocm93IEVycm9yKCdQYXlQYWwgc2NyaXB0IGlzIG5vdCBhdmFpbGFibGUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJlbmRlciBQYXlQYWwgYnV0dG9uIGFzIHBlciB0aGVpciBkb2NzIGF0XG4gICAgICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLnBheXBhbC5jb20vZG9jcy9pbnRlZ3JhdGlvbi9kaXJlY3QvZXhwcmVzcy1jaGVja291dC9pbnRlZ3JhdGlvbi1qc3Y0L2FkZC1wYXlwYWwtYnV0dG9uL1xuICAgICAgICB3aW5kb3dbdGhpcy5wYXlwYWxXaW5kb3dOYW1lXS5CdXR0b24ucmVuZGVyKHtcbiAgICAgICAgICAgIC8vIHNldCBlbnZpcm9ubWVudFxuICAgICAgICAgICAgZW52OiB0aGlzLmNvbmZpZy5lbnZpcm9ubWVudC50b1N0cmluZygpLFxuXG4gICAgICAgICAgICAvLyBTaG93IHRoZSBidXllciBhICdQYXkgTm93JyBidXR0b24gaW4gdGhlIGNoZWNrb3V0IGZsb3dcbiAgICAgICAgICAgIGNvbW1pdDogdGhpcy5jb25maWcuY29tbWl0LFxuXG4gICAgICAgICAgICAvLyBpbml0IGNsaWVudCBmb3IgY2xpZW50IHNpZGUgaW50ZWdyYXRpb25cbiAgICAgICAgICAgIGNsaWVudDogdGhpcy5nZXRDbGllbnQoKSxcblxuICAgICAgICAgICAgLy8gc2V0IGJ1dHRvbiBjb25maWcgaWYgYXZhaWxhYmxlXG4gICAgICAgICAgICBzdHlsZTogdGhpcy5jb25maWcuYnV0dG9uLFxuXG4gICAgICAgICAgICAvLyBzZXQgZnVuZGluZyBpZiBhdmFpbGFibGVcbiAgICAgICAgICAgIGZ1bmRpbmc6IHRoaXMuZ2V0RnVuZGluZygpLFxuXG4gICAgICAgICAgICAvLyBwYXltZW50KCkgaXMgY2FsbGVkIHdoZW4gdGhlIGJ1dHRvbiBpcyBjbGlja2VkXG4gICAgICAgICAgICBwYXltZW50OiAoZGF0YSwgYWN0aW9ucykgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5pbnRlZ3JhdGlvblR5cGUgPT09IFBheVBhbEludGVncmF0aW9uVHlwZS5TZXJ2ZXJTaWRlUkVTVCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBjbGllbnQgbmVlZHMgdG8gY3JlYXRlIHBheW1lbnQgb24gc2VydmVyIHNpZGVcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5wYXltZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcihgWW91IG5lZWQgc2V0IHVwIGEgY3JlYXRlIHBheW1lbnQgbWV0aG9kIGFuZCByZXR1cm5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQYXlQYWwncyBwYXltZW50IGlkIHdoZW4gdXNpbmcgc2VydmVyIHNpZGUgaW50ZWdyYXRpb25gKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFBheXBhbCBleHBlY3RzIHByb21pc2Ugd2l0aCBwYXltZW50IGlkIChzdHJpbmcpIHRvIGJlIHJldHVybmVkXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5wYXltZW50KCkudG9Qcm9taXNlKClcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKHBheW1lbnRJZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBheW1lbnRJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5pbnRlZ3JhdGlvblR5cGUgPT09IFBheVBhbEludGVncmF0aW9uVHlwZS5DbGllbnRTaWRlUkVTVCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29uZmlnLnRyYW5zYWN0aW9ucyB8fCAhQXJyYXkuaXNBcnJheSh0aGlzLmNvbmZpZy50cmFuc2FjdGlvbnMpIHx8IHRoaXMuY29uZmlnLnRyYW5zYWN0aW9ucy5sZW5ndGggPD0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgRXJyb3IoYFlvdSBuZWVkIHRvIHByb3ZpZGUgYXQgbGVhc3QgMSB0cmFuc2FjdGlvbiBmb3IgY2xpZW50IHNpZGUgaW50ZWdyYXRpb25gKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4cGVyaWVuY2VDb25maWcgPSB0aGlzLmNvbmZpZy5leHBlcmllbmNlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWN0aW9ucy5wYXltZW50LmNyZWF0ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXltZW50OiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWxsb3cgdXNlciB0byBzcGVjaWZpZnkgaW50ZW50LCBlbHNlIHVzZSBkZWZhdWx0ICdzYWxlJy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlbnQ6IHRoaXMuY29uZmlnLmludGVudCA/IHRoaXMuY29uZmlnLmludGVudCA6ICdzYWxlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2FjdGlvbnM6IHRoaXMuY29uZmlnLnRyYW5zYWN0aW9uc1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVyaWVuY2U6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dF9maWVsZHM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9fc2hpcHBpbmc6IChleHBlcmllbmNlQ29uZmlnICYmIGV4cGVyaWVuY2VDb25maWcubm9TaGlwcGluZykgPyAxIDogMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlc2VudGF0aW9uOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyYW5kX25hbWU6IChleHBlcmllbmNlQ29uZmlnICYmIGV4cGVyaWVuY2VDb25maWcuYnJhbmROYW1lKSA/IGV4cGVyaWVuY2VDb25maWcuYnJhbmROYW1lIDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nb19pbWFnZTogKGV4cGVyaWVuY2VDb25maWcgJiYgZXhwZXJpZW5jZUNvbmZpZy5sb2dvSW1hZ2UpID8gZXhwZXJpZW5jZUNvbmZpZy5sb2dvSW1hZ2UgOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbGVfY29kZTogKGV4cGVyaWVuY2VDb25maWcgJiYgZXhwZXJpZW5jZUNvbmZpZy5sb2NhbGVDb2RlKSA/IGV4cGVyaWVuY2VDb25maWcubG9jYWxlQ29kZSA6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8vIG9uQXV0aG9yaXplKCkgaXMgY2FsbGVkIHdoZW4gdGhlIGJ1eWVyIGFwcHJvdmVzIHRoZSBwYXltZW50XG4gICAgICAgICAgICBvbkF1dGhvcml6ZTogKGRhdGE6IElQYXlQYWxQYXltZW50Q29tcGxldGVEYXRhLCBhY3Rpb25zOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcuaW50ZWdyYXRpb25UeXBlID09PSBQYXlQYWxJbnRlZ3JhdGlvblR5cGUuU2VydmVyU2lkZVJFU1QpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY2xpZW50IG5lZWRzIHRvIHNlcnZlciB0byBleGVjdXRlIHRoZSBwYXltZW50XG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb25maWcub25BdXRob3JpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IEVycm9yKGBZb3UgbmVlZCBzZXQgdXAgYW4gZXhlY3V0ZSBtZXRob2Qgd2hlbiB1c2luZyBzZXJ2ZXIgc2lkZSBpbnRlZ3JhdGlvbmApO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gUGF5cGFsIGV4cGVjdHMgcHJvbWlzZVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb25maWcub25BdXRob3JpemUoZGF0YSwgYWN0aW9ucykudG9Qcm9taXNlKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmludGVncmF0aW9uVHlwZSA9PT0gUGF5UGFsSW50ZWdyYXRpb25UeXBlLkNsaWVudFNpZGVSRVNUKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYSBjYWxsIHRvIHRoZSBSRVNUIGFwaSB0byBleGVjdXRlIHRoZSBwYXltZW50XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhY3Rpb25zLnBheW1lbnQuZXhlY3V0ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5vblBheW1lbnRDb21wbGV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IEVycm9yKGBZb3Ugc2hvdWxkIHByb3ZpZGUgc29tZSBjYWxsYmFjayB3aGVuIHBheW1lbnQgaXMgZmluaXNoZWQgd2hlbiB1c2luZyBjbGllbnQgc2lkZSBpbnRlZ3JhdGlvbmApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWcub25QYXltZW50Q29tcGxldGUoZGF0YSwgYWN0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uRXJyb3I6IChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcub25FcnJvcikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5vbkVycm9yKGVycik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb25DYW5jZWw6IChkYXRhLCBhY3Rpb25zKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLm9uQ2FuY2VsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm9uQ2FuY2VsKGRhdGEsIGFjdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkNsaWNrOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLm9uQ2xpY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWcub25DbGljaygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2YWxpZGF0ZTogKGFjdGlvbnMpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcudmFsaWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWcudmFsaWRhdGUoYWN0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCBgIyR7dGhpcy5wYXlQYWxCdXR0b25Db250YWluZXJJZH1gKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENsaWVudCgpOiBJUGF5cGFsQ2xpZW50IHwgdW5kZWZpbmVkIHtcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmludGVncmF0aW9uVHlwZSA9PT0gUGF5UGFsSW50ZWdyYXRpb25UeXBlLkNsaWVudFNpZGVSRVNUKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29uZmlnLmNsaWVudCkge1xuICAgICAgICAgICAgICAgIHRocm93IEVycm9yKGBZb3UgbmVlZCB0byBzZXR1cCBjbGllbnQgaW5mb3JtYXRpb24gd2hlbiB1c2luZyBjbGllbnQgc2lkZSBpbnRlZ3JhdGlvbmApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHByb2R1Y3Rpb246IHRoaXMuY29uZmlnLmNsaWVudC5wcm9kdWN0aW9uLFxuICAgICAgICAgICAgICAgIHNhbmRib3g6IHRoaXMuY29uZmlnLmNsaWVudC5zYW5kYm94XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEZ1bmRpbmcoKToge1xuICAgICAgICBhbGxvd2VkOiBhbnlbXSxcbiAgICAgICAgZGlzYWxsb3dlZDogYW55W11cbiAgICB9IHwgdW5kZWZpbmVkIHtcbiAgICAgICAgLy8gcmVzb2x2ZSBmdW5kaW5nIHRvIHVzZSBwYXlwYWwncyBwcm9wZXJ0aWVzXG4gICAgICAgIGlmICghdGhpcy5jb25maWcuZnVuZGluZykge1xuICAgICAgICAgICAgLy8gbm8gZnVuZGluZyBwcm92aWRlZFxuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFsbG93ZWQ6IGFueVtdID0gW107XG4gICAgICAgIGNvbnN0IGRpc2FsbG93ZWQ6IGFueVtdID0gW107XG5cbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmZ1bmRpbmcuYWxsb3dlZCkge1xuICAgICAgICAgICAgdGhpcy5jb25maWcuZnVuZGluZy5hbGxvd2VkLmZvckVhY2godHlwZSA9PiB7XG4gICAgICAgICAgICAgICAgYWxsb3dlZC5wdXNoKHRoaXMubWFwRnVuZGluZ1R5cGUodHlwZSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5jb25maWcuZnVuZGluZy5kaXNhbGxvd2VkKSB7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5mdW5kaW5nLmRpc2FsbG93ZWQuZm9yRWFjaCh0eXBlID0+IHtcbiAgICAgICAgICAgICAgICBkaXNhbGxvd2VkLnB1c2godGhpcy5tYXBGdW5kaW5nVHlwZSh0eXBlKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBhbGxvd2VkOiBhbGxvd2VkLFxuICAgICAgICAgICAgZGlzYWxsb3dlZDogZGlzYWxsb3dlZFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgbWFwRnVuZGluZ1R5cGUodHlwZTogUGF5UGFsRnVuZGluZyk6IGFueSB7XG4gICAgICAgIGlmICh0eXBlID09PSBQYXlQYWxGdW5kaW5nLkNhcmQpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXlwYWwuRlVORElORy5DQVJEO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSBQYXlQYWxGdW5kaW5nLkNyZWRpdCkge1xuICAgICAgICAgICAgcmV0dXJuIHBheXBhbC5GVU5ESU5HLkNSRURJVDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gUGF5UGFsRnVuZGluZy5FbHYpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXlwYWwuRlVORElORy5FTFY7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgRXJyb3IoYFVuc3VwcG9ydGVkIGZ1bmRpbmcgdHlwZSAnJHt0eXBlfSdgKTtcbiAgICB9XG59XG5cbiJdfQ==