UNPKG

ngx-paypal-with-intent

Version:

Paypal integration for Angular 6, 7 and beyond

458 lines 46.5 kB
/** * @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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF5cGFsLWNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25neC1wYXlwYWwtd2l0aC1pbnRlbnQvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy9wYXlwYWwtY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBRUgsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsS0FBSyxFQUlMLFNBQVMsR0FDWixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN6QyxPQUFPLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRWhELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUNyRSxPQUFPLEVBQTZDLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBT2xHO0lBMEVJOzs7O1FBeERTLG9CQUFlLEdBQUcsS0FBSyxDQUFDOzs7O1FBVXpCLDZDQUF3QyxHQUFHLEtBQUssQ0FBQzs7OztRQWV4Qyx3QkFBbUIsR0FBRyxFQUFFLENBQUM7Ozs7UUFLekIsd0JBQW1CLEdBQUcsSUFBSSxDQUFDOzs7O1FBSzNCLHFCQUFnQixHQUFHLFFBQVEsQ0FBQzs7OztRQUs1QixnQ0FBMkIsR0FBRyw2QkFBNkIsQ0FBQzs7OztRQUs1RCxvQkFBZSxHQUFHLCtDQUErQyxDQUFDO1FBT2xFLGtDQUE2QixHQUFHLDhCQUE4QixDQUFDO1FBRS9ELGtCQUFhLEdBQWtCLElBQUksT0FBTyxFQUFRLENBQUM7SUFJcEUsQ0FBQztJQTFDRCxzQkFBNEMseURBQXlCOzs7OztRQUFyRSxVQUFzRSxPQUFtQjtZQUNyRixJQUFJLE9BQU8sRUFBRTtnQkFDVCxJQUFJLENBQUMsMEJBQTBCLEdBQUcsT0FBTyxDQUFDO2FBQzdDO1FB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OztJQUtuRixxREFBd0M7O0lBRXhDLDJEQUFnRjs7SUFFaEYsMkNBQW9FIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgICBBZnRlclZpZXdJbml0LFxuICAgIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICAgIENvbXBvbmVudCxcbiAgICBFbGVtZW50UmVmLFxuICAgIElucHV0LFxuICAgIE9uQ2hhbmdlcyxcbiAgICBPbkRlc3Ryb3ksXG4gICAgU2ltcGxlQ2hhbmdlcyxcbiAgICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaW50ZXJ2YWwsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBQYXlQYWxGdW5kaW5nIH0gZnJvbSAnLi4vbW9kZWxzL3BheXBhbC1mdW5kaW5nJztcbmltcG9ydCB7IFBheVBhbEludGVncmF0aW9uVHlwZSB9IGZyb20gJy4uL21vZGVscy9wYXlwYWwtaW50ZWdyYXRpb24nO1xuaW1wb3J0IHsgSVBheXBhbENsaWVudCwgSVBheVBhbFBheW1lbnRDb21wbGV0ZURhdGEsIFBheVBhbENvbmZpZyB9IGZyb20gJy4uL21vZGVscy9wYXlwYWwtbW9kZWxzJztcblxuLyoqXG4gKiBHbG9iYWwgdmFyaWFibGUgd2hlcmUgUGF5UGFsIGlzIGxvYWRlZCB0b1xuICovXG5kZWNsYXJlIHZhciBwYXlwYWw6IGFueTtcblxuQENvbXBvbmVudCh7XG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gICAgc2VsZWN0b3I6ICduZ3gtcGF5cGFsJyxcbiAgICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgI3BheVBhbFNjcmlwdEVsZW0+PC9kaXY+XG4gICAgPGRpdiAjcGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbSBbaWRdPVwicGF5UGFsQnV0dG9uQ29udGFpbmVySWRcIj48L2Rpdj5cbiAgICBgXG59KVxuZXhwb3J0IGNsYXNzIE5neFBheXBhbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcblxuICAgIC8qKlxuICAgICAqIENvbmZpZ3VyYXRpb24gZm9yIHBheXBhbC5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBjb25maWc6IFBheVBhbENvbmZpZztcblxuICAgIC8qKlxuICAgICAqIEluZGljYXRlcyBpZiBnbG9iYWwgY29uZmlndXJhdGlvbiAocHJvdmlkZWQgdmlhICdmb3JSb290JykgaXMgdXNlZFxuICAgICAqL1xuICAgIEBJbnB1dCgpIHVzZUdsb2JhbENvbmZpZyA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogQ29udGFpbmVyIGZvciBwYXlwYWwgc2NyaXB0XG4gICAgICovXG4gICAgQFZpZXdDaGlsZCgncGF5UGFsU2NyaXB0RWxlbScpIHBheXBhbFNjcmlwdEVsZW06IEVsZW1lbnRSZWY7XG5cbiAgICAvKipcbiAgICAgKiBVc2VkIGZvciBpbmRpY2F0aW5nIGRlbGF5ZWQgcmVuZGVyZWQgaWYgY29udGFpbmVyIGlzIG5vdCB5ZXQgcmVhZHkgaW4gRE9NXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWdpc3RlclBheVBhbFNjcmlwdFdoZW5Db250YWluZXJJc1JlYWR5ID0gZmFsc2U7XG5cbiAgICAvKipcbiAgICAgKiBIb2xkcyBjdXJyZW50IGNvbnRhaW5lciBlbGVtZW50XG4gICAgICovXG4gICAgcHJpdmF0ZSBfcGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbT86IEVsZW1lbnRSZWY7XG4gICAgQFZpZXdDaGlsZCgncGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbScpIHNldCBwYXlQYWxCdXR0b25Db250YWluZXJFbGVtKGNvbnRlbnQ6IEVsZW1lbnRSZWYpIHtcbiAgICAgICAgaWYgKGNvbnRlbnQpIHtcbiAgICAgICAgICAgIHRoaXMuX3BheVBhbEJ1dHRvbkNvbnRhaW5lckVsZW0gPSBjb250ZW50O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUG9sbGluZyBpbnRlcnZhbCBpZiBwYXlwYWwgc2NyaXB0IGlzIHBlbmRpbmdcbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHRQb2xsSW50ZXJ2YWwgPSA1MDtcblxuICAgIC8qKlxuICAgICAqIFBvbGxpbmcgd2lsbCBzdG9wIGFmdGVyIHBvbGxpbmcgcmVhY2hlcyB0aGlzIG51bWJlclxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgbWF4aW11bVBvbGxXYWl0VGltZSA9IDUwMDA7XG5cbiAgICAvKipcbiAgICAqIE5hbWUgb2YgdGhlIGdsb2JhbCB2YXJpYWJsZSB3aGVyZSBwYXlwYWwgaXMgc3RvcmVkXG4gICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IHBheXBhbFdpbmRvd05hbWUgPSAncGF5cGFsJztcblxuICAgIC8qKlxuICAgICAqIE5hbWUgb2YgdGhlIGdsb2JhbCB2YXJpYWJsZSBpbmRpY2F0aW5nIHRoYXQgc2NyaXB0IHdhcyBpbml0aWF0ZWQgKGFkZGVkIHRvIHBhZ2UpXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBwYXlwYWxXaW5kb3dTY3JpcHRJbml0aWF0ZWQgPSAnbmd4LXBheXBhbC1zY3JpcHQtaW5pdGlhdGVkJztcblxuICAgIC8qKlxuICAgICAqIFBheVBhbCBpbnRlZ3JhdGlvbiBzY3JpcHQgdXJsXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBwYXlwYWxTY3JpcHRVcmwgPSAnaHR0cHM6Ly93d3cucGF5cGFsb2JqZWN0cy5jb20vYXBpL2NoZWNrb3V0LmpzJztcblxuICAgIC8qKlxuICAgICAqIElkIG9mIHRoZSBlbGVtZW50IHdoZXJlIFBheVBhbCBidXR0b24gd2lsbCBiZSByZW5kZXJlZFxuICAgICAqL1xuICAgIHB1YmxpYyBwYXlQYWxCdXR0b25Db250YWluZXJJZD86IHN0cmluZztcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgcGF5UGFsQnV0dG9uQ29udGFpbmVySWRQcmVmaXggPSAnbmd4LXBheXBhbC1idXR0b24tY29udGFpbmVyLSc7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IG5nVW5zdWJzY3JpYmU6IFN1YmplY3Q8dm9pZD4gPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgKSB7XG4gICAgfVxuXG4gICAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgICAgICAvLyBpbml0IHdoZW4gY29uZmlnIG9uY2UgaXRzIGF2YWlsYWJsZVxuICAgICAgICBpZiAodGhpcy5jb25maWcpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdFBheVBhbCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgICAgICAvLyByZWdpc3RlciBzY3JpcHQgaWYgZWxlbWVudCBpcyByZWFkeSBpbiBkb21cbiAgICAgICAgaWYgKHRoaXMucmVnaXN0ZXJQYXlQYWxTY3JpcHRXaGVuQ29udGFpbmVySXNSZWFkeSAmJiB0aGlzLl9wYXlQYWxCdXR0b25Db250YWluZXJFbGVtKSB7XG4gICAgICAgICAgICB0aGlzLnNldHVwU2NyaXB0KCk7XG4gICAgICAgICAgICB0aGlzLnJlZ2lzdGVyUGF5UGFsU2NyaXB0V2hlbkNvbnRhaW5lcklzUmVhZHkgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLm5nVW5zdWJzY3JpYmUubmV4dCgpO1xuICAgICAgICB0aGlzLm5nVW5zdWJzY3JpYmUuY29tcGxldGUoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRQYXlQYWwoKTogdm9pZCB7XG4gICAgICAgIC8vIHNldCB1bmlxdWUgcGF5cGFsIGNvbnRhaW5lciBidXR0b24gaWRcbiAgICAgICAgdGhpcy5wYXlQYWxCdXR0b25Db250YWluZXJJZCA9IGAke3RoaXMucGF5UGFsQnV0dG9uQ29udGFpbmVySWRQcmVmaXh9JHt0aGlzLmdldFBzZXVkb1VuaXF1ZU51bWJlcigpfWA7XG4gICAgICAgIC8vIGNoZWNrIGlmIHBheXBhbCB3YXMgYWxyZWFkeSByZWdpc3RlciBhbmQgaWYgc28sIGRvbid0IGFkZCBpdCB0byBwYWdlIGFnYWluXG4gICAgICAgIGlmICghd2luZG93W3RoaXMucGF5cGFsV2luZG93TmFtZV0pIHtcbiAgICAgICAgICAgIC8vIGNoZWNrIGlmIHNjcmlwdCBpcyBwZW5kaW5nXG4gICAgICAgICAgICBpZiAod2luZG93W3RoaXMucGF5cGFsV2luZG93U2NyaXB0SW5pdGlhdGVkXSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMucG9sbFVudGlsU2NyaXB0QXZhaWxhYmxlKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIHJlZ2lzdGVyIHNjcmlwdCBhbmQgc2V0IGdsb2JhbCBmbGFnXG4gICAgICAgICAgICAgICAgd2luZG93W3RoaXMucGF5cGFsV2luZG93U2NyaXB0SW5pdGlhdGVkXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRQYXlQYWxTY3JpcHRUb1BhZ2UoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8ganVzdCByZWdpc3RlciBwYXltZW50XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVNjcmlwdFJlZ2lzdGVyaW5nKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFBzZXVkb1VuaXF1ZU51bWJlcigpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gbmV3IERhdGUoKS52YWx1ZU9mKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlZCB3aGVuIHRoZXJlIGFyZSBtdWx0aXBsZSBwYXlwYWwgY29tcG9uZW50cyBvbiB0aGUgc2FtZSBwYWdlIGJlYWN1c2Ugb25seSAxIG9mIHRoZW1cbiAgICAgKiBtYXkgcmVnaXN0ZXIgcGF5cGFsIHNjcmlwdC4gVGhlIG90aGVyIGhhcyB0byBiZSBwb2xsaW5nIHVudGlsIHBheXBhbCBpcyBhdmFpbGFibGUgb3IgY29tcG9uZW50IGRlc3Ryb3llZFxuICAgICAqL1xuICAgIHByaXZhdGUgcG9sbFVudGlsU2NyaXB0QXZhaWxhYmxlKCk6IHZvaWQge1xuICAgICAgICBjb25zdCBvYnMgPSBpbnRlcnZhbCh0aGlzLmRlZmF1bHRQb2xsSW50ZXJ2YWwpXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICB0YWtlVW50aWwodGhpcy5uZ1Vuc3Vic2NyaWJlKSxcbiAgICAgICAgICAgICAgICBtYXAoKHgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHggPj0gdGhpcy5tYXhpbXVtUG9sbFdhaXRUaW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oYFBheVBhbCBzY3JpcHQgd2FzIG5vdCBsb2FkZWQgYWZ0ZXIgJyR7dGhpcy5tYXhpbXVtUG9sbFdhaXRUaW1lfScgbWF4aW11bSBwb2xsaW5nIHRpbWUuYCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYnMudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGlmIHBheXBhbCBzY3JpcHQgZXhpc3RzXG4gICAgICAgICAgICAgICAgICAgIGlmICh3aW5kb3dbdGhpcy5wYXlwYWxXaW5kb3dOYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVnaXN0ZXIgc2NyaXB0XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZVNjcmlwdFJlZ2lzdGVyaW5nKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHN0b3AgZXhlY3V0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBvYnMudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhZGRQYXlQYWxTY3JpcHRUb1BhZ2UoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NjcmlwdCcpO1xuICAgICAgICBzY3JpcHQuaW5uZXJIVE1MID0gJyc7XG4gICAgICAgIHNjcmlwdC5zcmMgPSB0aGlzLnBheXBhbFNjcmlwdFVybDtcbiAgICAgICAgc2NyaXB0Lm9ubG9hZCA9ICgpID0+IHRoaXMuaGFuZGxlU2NyaXB0UmVnaXN0ZXJpbmcoKTtcbiAgICAgICAgc2NyaXB0LmFzeW5jID0gdHJ1ZTtcbiAgICAgICAgc2NyaXB0LmRlZmVyID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLnBheXBhbFNjcmlwdEVsZW0ubmF0aXZlRWxlbWVudC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGFuZGxlU2NyaXB0UmVnaXN0ZXJpbmcoKTogdm9pZCB7XG4gICAgICAgIC8vIGNoZWNrIGlmIGNvbnRhaW5lciB3aXRoIHJlcXVlc3RlZCBpZCBleGlzdHNcbiAgICAgICAgLy8gdGhpcyBpcyBoZXJlIGJlY2F1c2UgZHluYW1pY2FsbHkgc3dpdGNoaW5nIGJldHdlZW4gY29tcG9uZW50cyB3b3VsZCBjYXVzZSBQYXlQYWwgdG9cbiAgICAgICAgLy8gdGhyb3cgYW4gZXJyb3IgaWYgdGhlIGNvbnRhaW5lciBhbHJlYWR5IGV4aXN0ZWQgYmVmb3JlXG4gICAgICAgIGlmICh0aGlzLl9wYXlQYWxCdXR0b25Db250YWluZXJFbGVtICYmIHRoaXMuX3BheVBhbEJ1dHRvbkNvbnRhaW5lckVsZW0ubmF0aXZlRWxlbWVudCAmJlxuICAgICAgICAgICAgdGhpcy5fcGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbS5uYXRpdmVFbGVtZW50LmlkID09PSB0aGlzLnBheVBhbEJ1dHRvbkNvbnRhaW5lcklkKSB7XG4gICAgICAgICAgICAvLyBjb250YWluZXIgaXMgcmVhZHksIHNldHVwIHNjcmlwdCByaWdodCBhd2F5XG4gICAgICAgICAgICB0aGlzLnNldHVwU2NyaXB0KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBjb250YWluZXIgaXMgbm90IHJlYWR5LCBkZWxheSByZWdpc3RlcmluZyB1bnRpbCBpdCBpc1xuICAgICAgICAgICAgdGhpcy5yZWdpc3RlclBheVBhbFNjcmlwdFdoZW5Db250YWluZXJJc1JlYWR5ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc2V0dXBTY3JpcHQoKTogdm9pZCB7XG4gICAgICAgIC8vIGZpcnN0IGNsZWFyIGNvbnRhaW5lclxuICAgICAgICBpZiAoIXRoaXMuX3BheVBhbEJ1dHRvbkNvbnRhaW5lckVsZW0pIHtcbiAgICAgICAgICAgIHRocm93IEVycm9yKGBDYW5ub3Qgc2V0dXAgc2NyaXB0IGJlY2F1c2UgcGF5cGFsIGJ1dHRvbiBjb250YWluZXIgd2l0aCBpZCAnJHt0aGlzLnBheVBhbEJ1dHRvbkNvbnRhaW5lcklkfScgaXMgbm90IHlldCByZWFkeWApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fcGF5UGFsQnV0dG9uQ29udGFpbmVyRWxlbS5uYXRpdmVFbGVtZW50LmlubmVySFRNTCA9ICcnO1xuXG4gICAgICAgIGlmICghd2luZG93W3RoaXMucGF5cGFsV2luZG93TmFtZV0pIHtcbiAgICAgICAgICAgIHRocm93IEVycm9yKCdQYXlQYWwgc2NyaXB0IGlzIG5vdCBhdmFpbGFibGUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJlbmRlciBQYXlQYWwgYnV0dG9uIGFzIHBlciB0aGVpciBkb2NzIGF0XG4gICAgICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLnBheXBhbC5jb20vZG9jcy9pbnRlZ3JhdGlvbi9kaXJlY3QvZXhwcmVzcy1jaGVja291dC9pbnRlZ3JhdGlvbi1qc3Y0L2FkZC1wYXlwYWwtYnV0dG9uL1xuICAgICAgICB3aW5kb3dbdGhpcy5wYXlwYWxXaW5kb3dOYW1lXS5CdXR0b24ucmVuZGVyKHtcbiAgICAgICAgICAgIC8vIHNldCBlbnZpcm9ubWVudFxuICAgICAgICAgICAgZW52OiB0aGlzLmNvbmZpZy5lbnZpcm9ubWVudC50b1N0cmluZygpLFxuXG4gICAgICAgICAgICAvLyBTaG93IHRoZSBidXllciBhICdQYXkgTm93JyBidXR0b24gaW4gdGhlIGNoZWNrb3V0IGZsb3dcbiAgICAgICAgICAgIGNvbW1pdDogdGhpcy5jb25maWcuY29tbWl0LFxuXG4gICAgICAgICAgICAvLyBpbml0IGNsaWVudCBmb3IgY2xpZW50IHNpZGUgaW50ZWdyYXRpb25cbiAgICAgICAgICAgIGNsaWVudDogdGhpcy5nZXRDbGllbnQoKSxcblxuICAgICAgICAgICAgLy8gc2V0IGJ1dHRvbiBjb25maWcgaWYgYXZhaWxhYmxlXG4gICAgICAgICAgICBzdHlsZTogdGhpcy5jb25maWcuYnV0dG9uLFxuXG4gICAgICAgICAgICAvLyBzZXQgZnVuZGluZyBpZiBhdmFpbGFibGVcbiAgICAgICAgICAgIGZ1bmRpbmc6IHRoaXMuZ2V0RnVuZGluZygpLFxuXG4gICAgICAgICAgICAvLyBwYXltZW50KCkgaXMgY2FsbGVkIHdoZW4gdGhlIGJ1dHRvbiBpcyBjbGlja2VkXG4gICAgICAgICAgICBwYXltZW50OiAoZGF0YSwgYWN0aW9ucykgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5pbnRlZ3JhdGlvblR5cGUgPT09IFBheVBhbEludGVncmF0aW9uVHlwZS5TZXJ2ZXJTaWRlUkVTVCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBjbGllbnQgbmVlZHMgdG8gY3JlYXRlIHBheW1lbnQgb24gc2VydmVyIHNpZGVcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5wYXltZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcihgWW91IG5lZWQgc2V0IHVwIGEgY3JlYXRlIHBheW1lbnQgbWV0aG9kIGFuZCByZXR1cm5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQYXlQYWwncyBwYXltZW50IGlkIHdoZW4gdXNpbmcgc2VydmVyIHNpZGUgaW50ZWdyYXRpb25gKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFBheXBhbCBleHBlY3RzIHByb21pc2Ugd2l0aCBwYXltZW50IGlkIChzdHJpbmcpIHRvIGJlIHJldHVybmVkXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5wYXltZW50KCkudG9Qcm9taXNlKClcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKHBheW1lbnRJZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBheW1lbnRJZDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5pbnRlZ3JhdGlvblR5cGUgPT09IFBheVBhbEludGVncmF0aW9uVHlwZS5DbGllbnRTaWRlUkVTVCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29uZmlnLnRyYW5zYWN0aW9ucyB8fCAhQXJyYXkuaXNBcnJheSh0aGlzLmNvbmZpZy50cmFuc2FjdGlvbnMpIHx8IHRoaXMuY29uZmlnLnRyYW5zYWN0aW9ucy5sZW5ndGggPD0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgRXJyb3IoYFlvdSBuZWVkIHRvIHByb3ZpZGUgYXQgbGVhc3QgMSB0cmFuc2FjdGlvbiBmb3IgY2xpZW50IHNpZGUgaW50ZWdyYXRpb25gKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4cGVyaWVuY2VDb25maWcgPSB0aGlzLmNvbmZpZy5leHBlcmllbmNlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWN0aW9ucy5wYXltZW50LmNyZWF0ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXltZW50OiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWxsb3cgdXNlciB0byBzcGVjaWZpZnkgaW50ZW50LCBlbHNlIHVzZSBkZWZhdWx0ICdzYWxlJy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlbnQ6IHRoaXMuY29uZmlnLmludGVudCA/IHRoaXMuY29uZmlnLmludGVudCA6ICdzYWxlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2FjdGlvbnM6IHRoaXMuY29uZmlnLnRyYW5zYWN0aW9uc1xuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVyaWVuY2U6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dF9maWVsZHM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9fc2hpcHBpbmc6IChleHBlcmllbmNlQ29uZmlnICYmIGV4cGVyaWVuY2VDb25maWcubm9TaGlwcGluZykgPyAxIDogMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlc2VudGF0aW9uOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyYW5kX25hbWU6IChleHBlcmllbmNlQ29uZmlnICYmIGV4cGVyaWVuY2VDb25maWcuYnJhbmROYW1lKSA/IGV4cGVyaWVuY2VDb25maWcuYnJhbmROYW1lIDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nb19pbWFnZTogKGV4cGVyaWVuY2VDb25maWcgJiYgZXhwZXJpZW5jZUNvbmZpZy5sb2dvSW1hZ2UpID8gZXhwZXJpZW5jZUNvbmZpZy5sb2dvSW1hZ2UgOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbGVfY29kZTogKGV4cGVyaWVuY2VDb25maWcgJiYgZXhwZXJpZW5jZUNvbmZpZy5sb2NhbGVDb2RlKSA/IGV4cGVyaWVuY2VDb25maWcubG9jYWxlQ29kZSA6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8vIG9uQXV0aG9yaXplKCkgaXMgY2FsbGVkIHdoZW4gdGhlIGJ1eWVyIGFwcHJvdmVzIHRoZSBwYXltZW50XG4gICAgICAgICAgICBvbkF1dGhvcml6ZTogKGRhdGE6IElQYXlQYWxQYXltZW50Q29tcGxldGVEYXRhLCBhY3Rpb25zOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcuaW50ZWdyYXRpb25UeXBlID09PSBQYXlQYWxJbnRlZ3JhdGlvblR5cGUuU2VydmVyU2lkZVJFU1QpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY2xpZW50IG5lZWRzIHRvIHNlcnZlciB0byBleGVjdXRlIHRoZSBwYXltZW50XG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb25maWcub25BdXRob3JpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IEVycm9yKGBZb3UgbmVlZCBzZXQgdXAgYW4gZXhlY3V0ZSBtZXRob2Qgd2hlbiB1c2luZyBzZXJ2ZXIgc2lkZSBpbnRlZ3JhdGlvbmApO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gUGF5cGFsIGV4cGVjdHMgcHJvbWlzZVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb25maWcub25BdXRob3JpemUoZGF0YSwgYWN0aW9ucykudG9Qcm9taXNlKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLmludGVncmF0aW9uVHlwZSA9PT0gUGF5UGFsSW50ZWdyYXRpb25UeXBlLkNsaWVudFNpZGVSRVNUKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYSBjYWxsIHRvIHRoZSBSRVNUIGFwaSB0byBleGVjdXRlIHRoZSBwYXltZW50XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhY3Rpb25zLnBheW1lbnQuZXhlY3V0ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5vblBheW1lbnRDb21wbGV0ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IEVycm9yKGBZb3Ugc2hvdWxkIHByb3ZpZGUgc29tZSBjYWxsYmFjayB3aGVuIHBheW1lbnQgaXMgZmluaXNoZWQgd2hlbiB1c2luZyBjbGllbnQgc2lkZSBpbnRlZ3JhdGlvbmApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWcub25QYXltZW50Q29tcGxldGUoZGF0YSwgYWN0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uRXJyb3I6IChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcub25FcnJvcikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5vbkVycm9yKGVycik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb25DYW5jZWw6IChkYXRhLCBhY3Rpb25zKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLm9uQ2FuY2VsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLm9uQ2FuY2VsKGRhdGEsIGFjdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkNsaWNrOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uZmlnLm9uQ2xpY2spIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWcub25DbGljaygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2YWxpZGF0ZTogKGFjdGlvbnMpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcudmFsaWRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWcudmFsaWRhdGUoYWN0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCBgIyR7dGhpcy5wYXlQYWxCdXR0b25Db250YWluZXJJZH1gKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENsaWVudCgpOiBJUGF5cGFsQ2xpZW50IHwgdW5kZWZpbmVkIHtcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmludGVncmF0aW9uVHlwZSA9PT0gUGF5UGFsSW50ZWdyYXRpb25UeXBlLkNsaWVudFNpZGVSRVNUKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuY29uZmlnLmNsaWVudCkge1xuICAgICAgICAgICAgICAgIHRocm93IEVycm9yKGBZb3UgbmVlZCB0byBzZXR1cCBjbGllbnQgaW5mb3JtYXRpb24gd2hlbiB1c2luZyBjbGllbnQgc2lkZSBpbnRlZ3JhdGlvbmApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHByb2R1Y3Rpb246IHRoaXMuY29uZmlnLmNsaWVudC5wcm9kdWN0aW9uLFxuICAgICAgICAgICAgICAgIHNhbmRib3g6IHRoaXMuY29uZmlnLmNsaWVudC5zYW5kYm94XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEZ1bmRpbmcoKToge1xuICAgICAgICBhbGxvd2VkOiBhbnlbXSxcbiAgICAgICAgZGlzYWxsb3dlZDogYW55W11cbiAgICB9IHwgdW5kZWZpbmVkIHtcbiAgICAgICAgLy8gcmVzb2x2ZSBmdW5kaW5nIHRvIHVzZSBwYXlwYWwncyBwcm9wZXJ0aWVzXG4gICAgICAgIGlmICghdGhpcy5jb25maWcuZnVuZGluZykge1xuICAgICAgICAgICAgLy8gbm8gZnVuZGluZyBwcm92aWRlZFxuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGFsbG93ZWQ6IGFueVtdID0gW107XG4gICAgICAgIGNvbnN0IGRpc2FsbG93ZWQ6IGFueVtdID0gW107XG5cbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmZ1bmRpbmcuYWxsb3dlZCkge1xuICAgICAgICAgICAgdGhpcy5jb25maWcuZnVuZGluZy5hbGxvd2VkLmZvckVhY2godHlwZSA9PiB7XG4gICAgICAgICAgICAgICAgYWxsb3dlZC5wdXNoKHRoaXMubWFwRnVuZGluZ1R5cGUodHlwZSkpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5jb25maWcuZnVuZGluZy5kaXNhbGxvd2VkKSB7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5mdW5kaW5nLmRpc2FsbG93ZWQuZm9yRWFjaCh0eXBlID0+IHtcbiAgICAgICAgICAgICAgICBkaXNhbGxvd2VkLnB1c2godGhpcy5tYXBGdW5kaW5nVHlwZSh0eXBlKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBhbGxvd2VkOiBhbGxvd2VkLFxuICAgICAgICAgICAgZGlzYWxsb3dlZDogZGlzYWxsb3dlZFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgbWFwRnVuZGluZ1R5cGUodHlwZTogUGF5UGFsRnVuZGluZyk6IGFueSB7XG4gICAgICAgIGlmICh0eXBlID09PSBQYXlQYWxGdW5kaW5nLkNhcmQpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXlwYWwuRlVORElORy5DQVJEO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlID09PSBQYXlQYWxGdW5kaW5nLkNyZWRpdCkge1xuICAgICAgICAgICAgcmV0dXJuIHBheXBhbC5GVU5ESU5HLkNSRURJVDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gUGF5UGFsRnVuZGluZy5FbHYpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXlwYWwuRlVORElORy5FTFY7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgRXJyb3IoYFVuc3VwcG9ydGVkIGZ1bmRpbmcgdHlwZSAnJHt0eXBlfSdgKTtcbiAgICB9XG59XG5cbiJdfQ==