@vendasta/store
Version:
Components and data for Store
341 lines • 52.4 kB
JavaScript
import { Component, Input, Inject } from '@angular/core';
import { DisplayPriceService } from '@vendasta/core/shared';
import { BehaviorSubject, combineLatest, Observable, of, EMPTY } from 'rxjs';
import { TranslateService } from '@ngx-translate/core';
import { map, switchMap, expand, reduce, catchError, publishReplay, refCount, filter } from 'rxjs/operators';
import { DiscountService } from '@vendasta/billing';
import * as i0 from "@angular/core";
import * as i1 from "@ngx-translate/core";
import * as i2 from "@vendasta/core/shared";
import * as i3 from "@vendasta/billing";
import * as i4 from "rxjs";
export class VaBasePricingComponent {
constructor(translateService, displayPriceService, partnerId$, discountService) {
this.translateService = translateService;
this.displayPriceService = displayPriceService;
this.partnerId$ = partnerId$;
this.discountService = discountService;
this.pricing = null;
this.wrapFrequency = false;
this.isAddon = false;
this.hasVerifiedContract = false;
this.highlightPrice = true;
this.loaded = true;
this.showAllPrices = false; // When false this will only show the first element in the pricing.prices list
this.useAbbreviatedFrequency = false;
this.showIsStartingAt = false;
this.pricing$$ = new BehaviorSubject(null);
this.billedProduct$$ = new BehaviorSubject(null);
this.hasVerifiedContract$$ = new BehaviorSubject(false);
this.showPricingPopover = false;
this.isFree$ = combineLatest([this.pricing$, this.billedProduct$, this.hasVerifiedContract$]).pipe(map(([pricing, billedProduct, hasVerifiedContract]) => {
const isFreeHelper = (prices) => {
return prices ? prices.every((p) => p.price === 0 || p.price === undefined) : false;
};
if (hasVerifiedContract && billedProduct) {
return billedProduct.pricingTiers.length === 1 ? isFreeHelper(billedProduct.pricingTiers) : false;
}
return !!pricing && isFreeHelper(pricing.prices);
}));
this.shouldContactSales$ = combineLatest([this.pricing$, this.billedProduct$, this.hasVerifiedContract$]).pipe(map(([pricing, billedProduct, hasVerifiedContract]) => {
const nestedPricesIsContactSales = (prices) => {
return prices && prices.length > 0 ? prices.some((p) => p.price === null || p.price < 0) : true;
};
if (hasVerifiedContract && billedProduct) {
return nestedPricesIsContactSales(billedProduct.pricingTiers);
}
if (!pricing) {
return true;
}
return nestedPricesIsContactSales(pricing.prices);
}));
this.isFlatPrice$ = this.billedProduct$.pipe(map((billedProduct) => billedProduct.pricingTiers.length === 1));
this.pricingTierData$ = this.billedProduct$.pipe(switchMap((billedProduct) => {
const pricingTierObservables = billedProduct.pricingTiers.map((pricingTier) => {
return combineLatest([
of(pricingTier.isStartingPrice),
this.buildPricingTierString(pricingTier),
this.buildPricingTierForProduct(pricingTier, billedProduct.billingFrequency),
this.buildPricingTierForAddon(pricingTier),
this.buildPriceStringForTier(pricingTier, billedProduct.billingFrequency, pricingTier.isStartingPrice),
this.buildPriceStringForTier(pricingTier),
]).pipe(map(([isStartingPrice, pricingTierString, pricingTierForProduct, pricingTierForAddon, priceStringForTier, priceStringForTierWithoutFreq,]) => {
return {
isStartingPrice: isStartingPrice,
pricingTierString: pricingTierString,
pricingTierForProduct: pricingTierForProduct,
pricingTierForAddon: pricingTierForAddon,
priceStringForTier: priceStringForTier,
priceStringForTierWithoutFreq: priceStringForTierWithoutFreq,
};
}));
});
return combineLatest([...pricingTierObservables]);
}));
this.priceData$ = this.pricing$.pipe(switchMap((pricing) => {
let filteredPrices = pricing.prices;
if (pricing.prices.length > 1) {
filteredPrices = pricing.prices.filter((price) => price.price > 0).sort(this.sortPricesByFrequency);
}
const priceObservables = filteredPrices.map((price) => {
return combineLatest([
of(price.isStartingPrice),
this.buildPriceStringForPricing(price, pricing.currency, true, false),
this.buildPriceStringForPricing(price, pricing.currency, false, true),
this.buildFrequencyString(price.frequency),
of(this.buildAbbreviatedFrequencyString(price.frequency)),
]).pipe(map(([isStartingPrice, priceStringForPricingWithoutFrequency, priceStringForPricingWithFrequency, frequencyString, abbrevFreq,]) => {
return {
isStartingPrice: isStartingPrice,
priceStringForPricingWithoutFrequency: priceStringForPricingWithoutFrequency,
priceStringForPricingWithFrequency: priceStringForPricingWithFrequency,
frequencyString: frequencyString,
abbreviatedFrequencyString: abbrevFreq,
};
}));
});
return combineLatest([...priceObservables]);
}));
this.commitmentMessage$ = this.buildCommitmentMessage();
this.setupFeeString$ = this.displayPriceService.getSetupFeeString();
this.isFirstTierFree$ = this.billedProduct$.pipe(map((billedProduct) => {
return billedProduct.pricingTiers.length > 1 && billedProduct.pricingTiers.some((item) => item.price === 0);
}));
}
get pricing$() {
return this.pricing$$.asObservable();
}
get billedProduct$() {
return this.billedProduct$$.asObservable();
}
get hasVerifiedContract$() {
return this.hasVerifiedContract$$.asObservable();
}
ngOnChanges(changes) {
if (changes.hasOwnProperty('pricing')) {
this.pricing$$.next(changes.pricing.currentValue);
}
if (changes.hasOwnProperty('billedProduct')) {
this.billedProduct$$.next(changes.billedProduct.currentValue);
}
if (changes.hasOwnProperty('hasVerifiedContract')) {
this.hasVerifiedContract$$.next(changes.hasVerifiedContract.currentValue);
}
}
buildPricingTierString(tier) {
let max = String(tier.rangeMax);
if (tier.rangeMax === -1) {
max = '∞';
if (tier.rangeMin === 0 || tier.rangeMin === 1) {
return of('');
}
}
return this.translateService.stream('FRONTEND.STORE.MIN_TO_MAX', {
minRange: String(tier.rangeMin),
maxRange: max,
});
}
buildPricingTierForProduct(tier, frequency) {
return combineLatest([this.buildPricingTierString(tier), this.buildFrequencyString(frequency)]).pipe(switchMap(([pricingTier, formattedFrequency]) => {
if (pricingTier) {
return this.translateService.stream('FRONTEND.STORE.PRODUCT_PRICING_WITH_FREQUENCY', {
pricingTier: pricingTier,
frequency: formattedFrequency,
});
}
return of(formattedFrequency);
}));
}
buildPricingTierForAddon(tier) {
return this.buildPricingTierString(tier).pipe(map((pricingRange) => (pricingRange ? pricingRange : '')));
}
sortPricesByFrequency(priceA, priceB) {
// this map is coded based on frequency values described by the enums described in the marketplace packages vendasta
// apis and the corresponding translations to strings laced throughout galaxy
const priceFrequencyComparisonMap = new Map([
[
'MONTHLY',
new Map([
['MONTHLY', 0],
['YEARLY', -1],
['ONCE', -1],
['ONE TIME', -1],
['ONE_TIME', -1],
]),
],
[
'YEARLY',
new Map([
['MONTHLY', 1],
['YEARLY', 0],
['ONCE', -1],
['ONE TIME', -1],
['ONE_TIME', -1],
]),
],
[
'ONCE',
new Map([
['MONTHLY', 1],
['YEARLY', 1],
['ONCE', 0],
['ONE TIME', 0],
['ONE_TIME', 0],
]),
],
[
'ONE TIME',
new Map([
['MONTHLY', 1],
['YEARLY', 1],
['ONCE', 0],
['ONE TIME', 0],
['ONE_TIME', 0],
]),
],
[
'ONE_TIME',
new Map([
['MONTHLY', 1],
['YEARLY', 1],
['ONCE', 0],
['ONE TIME', 0],
['ONE_TIME', 0],
]),
],
]);
if (priceFrequencyComparisonMap.get(priceA.frequency.toUpperCase()) === undefined) {
return 0;
}
const compareVal = priceFrequencyComparisonMap
.get(priceA.frequency.toUpperCase())
.get(priceB.frequency.toUpperCase());
return compareVal ? compareVal : 0;
}
buildPriceStringForPricing(price, currency, excludeFrequency, canIncludeStartingAtPrefix) {
return this.displayPriceService.formatDisplayPrice(price.price, currency, (excludeFrequency ? '' : price.frequency), true, true, true, price.isStartingPrice && canIncludeStartingAtPrefix);
}
buildPriceStringForTier(tier, frequency, isStartingPrice) {
return this.displayPriceService.formatDisplayPrice(tier.price, this.billedProduct.currency, frequency, undefined, undefined, undefined, isStartingPrice);
}
buildFrequencyString(frequency) {
return this.displayPriceService.formatBillingFrequency(frequency);
}
buildAbbreviatedFrequencyString(frequency) {
switch ((frequency || '').toLowerCase()) {
case 'daily':
return 'dy';
case 'weekly':
return 'wk';
case 'monthly':
return 'mo';
case 'yearly':
return 'yr';
}
return null;
}
buildCommitmentMessage() {
return combineLatest([
this.translateService.stream('FRONTEND.STORE.PRICING_FREQUENCIES'),
this.billedProduct$,
this.pricing$,
this.isFree$,
this.shouldContactSales$,
]).pipe(switchMap(([frequencyTranslations, billedProduct, pricing, isFree, shouldContactSales]) => {
const frequency = billedProduct
? billedProduct.billingFrequency.toString().toLowerCase()
: pricing && pricing.prices.length > 0
? pricing.prices[0].frequency.toLowerCase()
: '';
let frequencyString = '';
if (frequency === 'yearly') {
frequencyString = frequencyTranslations.YEAR;
}
else if (frequency === 'monthly') {
frequencyString = frequencyTranslations.MONTH;
}
if (!frequencyString || isFree || shouldContactSales) {
return of('');
}
if (billedProduct && billedProduct.commitment) {
const initial = billedProduct.commitment.initial;
const recurring = billedProduct.commitment.recurring;
return this.translateService.stream('FRONTEND.STORE.COMMITMENT_WITH_RENEWAL', {
initial: initial,
frequencyString: frequencyString,
recurring: recurring,
});
}
return of('');
}));
}
fetchAllDiscounts(pid, sku) {
const pageSize = 50;
const filters = {
merchantId: pid,
expiry: new Date(),
skus: [sku],
};
return this.discountService.list(filters, '', pageSize).pipe(expand((resp) => {
if ((resp?.results || []).length >= pageSize) {
return this.discountService.list(filters, resp.nextCursor, pageSize);
}
else {
return EMPTY;
}
}), reduce((prev, curr) => {
const discounts = curr?.results || [];
return prev.concat(discounts);
}, []));
}
getDiscounts() {
return combineLatest([this.partnerId$, this.billedProduct$]).pipe(filter(([pid, billedProduct]) => !!pid && !!billedProduct), switchMap(([pid, billedProduct]) => {
return this.fetchAllDiscounts(pid, billedProduct.productId);
}), catchError((err) => {
console.error('error getting discount information:', err);
return of([]);
}), publishReplay(1), refCount());
}
itemInfoIconEnter() {
if (this.discounts$ === undefined) {
this.discounts$ = this.getDiscounts();
}
this.showPricingPopover = true;
}
itemInfoIconLeave() {
this.showPricingPopover = false;
}
}
VaBasePricingComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: VaBasePricingComponent, deps: [{ token: i1.TranslateService }, { token: i2.DisplayPriceService }, { token: 'PARTNER_ID' }, { token: i3.DiscountService }], target: i0.ɵɵFactoryTarget.Component });
VaBasePricingComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.2", type: VaBasePricingComponent, selector: "app-base-pricing", inputs: { pricing: "pricing", billedProduct: "billedProduct", wrapFrequency: "wrapFrequency", isAddon: "isAddon", hasVerifiedContract: "hasVerifiedContract", highlightPrice: "highlightPrice", loaded: "loaded", showAllPrices: "showAllPrices", useAbbreviatedFrequency: "useAbbreviatedFrequency", showIsStartingAt: "showIsStartingAt" }, usesOnChanges: true, ngImport: i0, template: '', isInline: true });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: VaBasePricingComponent, decorators: [{
type: Component,
args: [{
selector: 'app-base-pricing',
template: '',
}]
}], ctorParameters: function () { return [{ type: i1.TranslateService }, { type: i2.DisplayPriceService }, { type: i4.Observable, decorators: [{
type: Inject,
args: ['PARTNER_ID']
}] }, { type: i3.DiscountService }]; }, propDecorators: { pricing: [{
type: Input
}], billedProduct: [{
type: Input
}], wrapFrequency: [{
type: Input
}], isAddon: [{
type: Input
}], hasVerifiedContract: [{
type: Input
}], highlightPrice: [{
type: Input
}], loaded: [{
type: Input
}], showAllPrices: [{
type: Input
}], useAbbreviatedFrequency: [{
type: Input
}], showIsStartingAt: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1wcmljaW5nLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL2xpYnMvc3RvcmUvc3JjL2xpYi9wcmljaW5nL2Jhc2UtcHJpY2luZy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQTRCLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVuRixPQUFPLEVBQStCLG1CQUFtQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFekYsT0FBTyxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDN0UsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdkQsT0FBTyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsYUFBYSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3RyxPQUFPLEVBQWtELGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDOzs7Ozs7QUFPcEcsTUFBTSxPQUFPLHNCQUFzQjtJQTJEakMsWUFDVSxnQkFBa0MsRUFDbEMsbUJBQXdDLEVBQ2pCLFVBQThCLEVBQ3JELGVBQWdDO1FBSGhDLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBa0I7UUFDbEMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjtRQUNqQixlQUFVLEdBQVYsVUFBVSxDQUFvQjtRQUNyRCxvQkFBZSxHQUFmLGVBQWUsQ0FBaUI7UUE5RGpDLFlBQU8sR0FBWSxJQUFJLENBQUM7UUFFeEIsa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFDdEIsWUFBTyxHQUFHLEtBQUssQ0FBQztRQUNoQix3QkFBbUIsR0FBRyxLQUFLLENBQUM7UUFDNUIsbUJBQWMsR0FBRyxJQUFJLENBQUM7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QixFQUFFOzJGQUVELHNCQUFzQjtrQkFKbEMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsa0JBQWtCO29CQUM1QixRQUFRLEVBQUUsRUFBRTtpQkFDYjs7MEJBK0RJLE1BQU07MkJBQUMsWUFBWTswRUE3RGIsT0FBTztzQkFBZixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0csbUJBQW1CO3NCQUEzQixLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csdUJBQXVCO3NCQUEvQixLQUFLO2dCQUNHLGdCQUFnQjtzQkFBeEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE9uQ2hhbmdlcywgU2ltcGxlQ2hhbmdlcywgSW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCaWxsZWRQcm9kdWN0LCBQcmljaW5nVGllciB9IGZyb20gJ0B2ZW5kYXN0YS9iaWxsaW5nJztcbmltcG9ydCB7IE1hcmtldHBsYWNlQmlsbGluZ0ZyZXF1ZW5jeSwgRGlzcGxheVByaWNlU2VydmljZSB9IGZyb20gJ0B2ZW5kYXN0YS9jb3JlL3NoYXJlZCc7XG5pbXBvcnQgeyBQcmljaW5nLCBQcmljZSB9IGZyb20gJy4vcHJpY2luZyc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGNvbWJpbmVMYXRlc3QsIE9ic2VydmFibGUsIG9mLCBFTVBUWSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgbWFwLCBzd2l0Y2hNYXAsIGV4cGFuZCwgcmVkdWNlLCBjYXRjaEVycm9yLCBwdWJsaXNoUmVwbGF5LCByZWZDb3VudCwgZmlsdGVyIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgRGlzY291bnQsIExpc3REaXNjb3VudHNSZXF1ZXN0RmlsdGVyc0ludGVyZmFjZSwgRGlzY291bnRTZXJ2aWNlIH0gZnJvbSAnQHZlbmRhc3RhL2JpbGxpbmcnO1xuaW1wb3J0IHsgSHR0cEVycm9yUmVzcG9uc2UgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1iYXNlLXByaWNpbmcnLFxuICB0ZW1wbGF0ZTogJycsXG59KVxuZXhwb3J0IGNsYXNzIFZhQmFzZVByaWNpbmdDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICBASW5wdXQoKSBwcmljaW5nOiBQcmljaW5nID0gbnVsbDtcbiAgQElucHV0KCkgYmlsbGVkUHJvZHVjdDogQmlsbGVkUHJvZHVjdDtcbiAgQElucHV0KCkgd3JhcEZyZXF1ZW5jeSA9IGZhbHNlO1xuICBASW5wdXQoKSBpc0FkZG9uID0gZmFsc2U7XG4gIEBJbnB1dCgpIGhhc1ZlcmlmaWVkQ29udHJhY3QgPSBmYWxzZTtcbiAgQElucHV0KCkgaGlnaGxpZ2h0UHJpY2UgPSB0cnVlO1xuICBASW5wdXQoKSBsb2FkZWQgPSB0cnVlO1xuICBASW5wdXQoKSBzaG93QWxsUHJpY2VzID0gZmFsc2U7IC8vIFdoZW4gZmFsc2UgdGhpcyB3aWxsIG9ubHkgc2hvdyB0aGUgZmlyc3QgZWxlbWVudCBpbiB0aGUgcHJpY2luZy5wcmljZXMgbGlzdFxuICBASW5wdXQoKSB1c2VBYmJyZXZpYXRlZEZyZXF1ZW5jeSA9IGZhbHNlO1xuICBASW5wdXQoKSBzaG93SXNTdGFydGluZ0F0ID0gZmFsc2U7XG5cbiAgcHJpY2luZyQkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxQcmljaW5nPihudWxsKTtcbiAgYmlsbGVkUHJvZHVjdCQkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxCaWxsZWRQcm9kdWN0PihudWxsKTtcbiAgaGFzVmVyaWZpZWRDb250cmFjdCQkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG5cbiAgaXNGcmVlJDogT2JzZXJ2YWJsZTxib29sZWFuPjtcbiAgc2hvdWxkQ29udGFjdFNhbGVzJDogT2JzZXJ2YWJsZTxib29sZWFuPjtcbiAgaXNGbGF0UHJpY2UkOiBPYnNlcnZhYmxlPGJvb2xlYW4+O1xuXG4gIHByaWNpbmdUaWVyRGF0YSQ6IE9ic2VydmFibGU8XG4gICAge1xuICAgICAgaXNTdGFydGluZ1ByaWNlOiBib29sZWFuO1xuICAgICAgcHJpY2luZ1RpZXJTdHJpbmc6IHN0cmluZztcbiAgICAgIHByaWNpbmdUaWVyRm9yUHJvZHVjdDogc3RyaW5nO1xuICAgICAgcHJpY2luZ1RpZXJGb3JBZGRvbjogc3RyaW5nO1xuICAgICAgcHJpY2VTdHJpbmdGb3JUaWVyOiBzdHJpbmc7XG4gICAgICBwcmljZVN0cmluZ0ZvclRpZXJXaXRob3V0RnJlcTogc3RyaW5nO1xuICAgIH1bXVxuICA+O1xuXG4gIHByaWNlRGF0YSQ6IE9ic2VydmFibGU8XG4gICAge1xuICAgICAgaXNTdGFydGluZ1ByaWNlOiBib29sZWFuO1xuICAgICAgcHJpY2VTdHJpbmdGb3JQcmljaW5nV2l0aG91dEZyZXF1ZW5jeTogc3RyaW5nO1xuICAgICAgcHJpY2VTdHJpbmdGb3JQcmljaW5nV2l0aEZyZXF1ZW5jeTogc3RyaW5nO1xuICAgICAgZnJlcXVlbmN5U3RyaW5nOiBzdHJpbmc7XG4gICAgICBhYmJyZXZpYXRlZEZyZXF1ZW5jeVN0cmluZzogc3RyaW5nO1xuICAgIH1bXVxuICA+O1xuXG4gIGNvbW1pdG1lbnRNZXNzYWdlJDogT2JzZXJ2YWJsZTxzdHJpbmc+O1xuICBzZXR1cEZlZVN0cmluZyQ6IE9ic2VydmFibGU8c3RyaW5nPjtcbiAgaXNGaXJzdFRpZXJGcmVlJDogT2JzZXJ2YWJsZTxib29sZWFuPjtcbiAgc2hvd1ByaWNpbmdQb3BvdmVyOiBib29sZWFuID0gZmFsc2U7XG4gIGRpc2NvdW50cyQ6IE9ic2VydmFibGU8RGlzY291bnRbXT47XG5cbiAgZ2V0IHByaWNpbmckKCk6IE9ic2VydmFibGU8UHJpY2luZz4ge1xuICAgIHJldHVybiB0aGlzLnByaWNpbmckJC5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIGdldCBiaWxsZWRQcm9kdWN0JCgpOiBPYnNlcnZhYmxlPEJpbGxlZFByb2R1Y3Q+IHtcbiAgICByZXR1cm4gdGhpcy5iaWxsZWRQcm9kdWN0JCQuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICBnZXQgaGFzVmVyaWZpZWRDb250cmFjdCQoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMuaGFzVmVyaWZpZWRDb250cmFjdCQkLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSB0cmFuc2xhdGVTZXJ2aWNlOiBUcmFuc2xhdGVTZXJ2aWNlLFxuICAgIHByaXZhdGUgZGlzcGxheVByaWNlU2VydmljZTogRGlzcGxheVByaWNlU2VydmljZSxcbiAgICBASW5qZWN0KCdQQVJUTkVSX0lEJykgcmVhZG9ubHkgcGFydG5lcklkJDogT2JzZXJ2YWJsZTxzdHJpbmc+LFxuICAgIHByaXZhdGUgZGlzY291bnRTZXJ2aWNlOiBEaXNjb3VudFNlcnZpY2UsXG4gICkge1xuICAgIHRoaXMuaXNGcmVlJCA9IGNvbWJpbmVMYXRlc3QoW3RoaXMucHJpY2luZyQsIHRoaXMuYmlsbGVkUHJvZHVjdCQsIHRoaXMuaGFzVmVyaWZpZWRDb250cmFjdCRdKS5waXBlKFxuICAgICAgbWFwKChbcHJpY2luZywgYmlsbGVkUHJvZHVjdCwgaGFzVmVyaWZpZWRDb250cmFjdF0pID0+IHtcbiAgICAgICAgY29uc3QgaXNGcmVlSGVscGVyID0gKHByaWNlczogeyBwcmljZTogbnVtYmVyIH1bXSk6IGJvb2xlYW4gPT4ge1xuICAgICAgICAgIHJldHVybiBwcmljZXMgPyBwcmljZXMuZXZlcnkoKHApID0+IHAucHJpY2UgPT09IDAgfHwgcC5wcmljZSA9PT0gdW5kZWZpbmVkKSA6IGZhbHNlO1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChoYXNWZXJpZmllZENvbnRyYWN0ICYmIGJpbGxlZFByb2R1Y3QpIHtcbiAgICAgICAgICByZXR1cm4gYmlsbGVkUHJvZHVjdC5wcmljaW5nVGllcnMubGVuZ3RoID09PSAxID8gaXNGcmVlSGVscGVyKGJpbGxlZFByb2R1Y3QucHJpY2luZ1RpZXJzKSA6IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAhIXByaWNpbmcgJiYgaXNGcmVlSGVscGVyKHByaWNpbmcucHJpY2VzKTtcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICB0aGlzLnNob3VsZENvbnRhY3RTYWxlcyQgPSBjb21iaW5lTGF0ZXN0KFt0aGlzLnByaWNpbmckLCB0aGlzLmJpbGxlZFByb2R1Y3QkLCB0aGlzLmhhc1ZlcmlmaWVkQ29udHJhY3QkXSkucGlwZShcbiAgICAgIG1hcCgoW3ByaWNpbmcsIGJpbGxlZFByb2R1Y3QsIGhhc1ZlcmlmaWVkQ29udHJhY3RdKSA9PiB7XG4gICAgICAgIGNvbnN0IG5lc3RlZFByaWNlc0lzQ29udGFjdFNhbGVzID0gKHByaWNlczogeyBwcmljZTogbnVtYmVyIH1bXSkgPT4ge1xuICAgICAgICAgIHJldHVybiBwcmljZXMgJiYgcHJpY2VzLmxlbmd0aCA+IDAgPyBwcmljZXMuc29tZSgocCkgPT4gcC5wcmljZSA9PT0gbnVsbCB8fCBwLnByaWNlIDwgMCkgOiB0cnVlO1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChoYXNWZXJpZmllZENvbnRyYWN0ICYmIGJpbGxlZFByb2R1Y3QpIHtcbiAgICAgICAgICByZXR1cm4gbmVzdGVkUHJpY2VzSXNDb250YWN0U2FsZXMoYmlsbGVkUHJvZHVjdC5wcmljaW5nVGllcnMpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghcHJpY2luZykge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXN0ZWRQcmljZXNJc0NvbnRhY3RTYWxlcyhwcmljaW5nLnByaWNlcyk7XG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgdGhpcy5pc0ZsYXRQcmljZSQgPSB0aGlzLmJpbGxlZFByb2R1Y3QkLnBpcGUobWFwKChiaWxsZWRQcm9kdWN0KSA9PiBiaWxsZWRQcm9kdWN0LnByaWNpbmdUaWVycy5sZW5ndGggPT09IDEpKTtcbiAgICB0aGlzLnByaWNpbmdUaWVyRGF0YSQgPSB0aGlzLmJpbGxlZFByb2R1Y3QkLnBpcGUoXG4gICAgICBzd2l0Y2hNYXAoKGJpbGxlZFByb2R1Y3QpID0+IHtcbiAgICAgICAgY29uc3QgcHJpY2luZ1RpZXJPYnNlcnZhYmxlcyA9IGJpbGxlZFByb2R1Y3QucHJpY2luZ1RpZXJzLm1hcCgocHJpY2luZ1RpZXIpID0+IHtcbiAgICAgICAgICByZXR1cm4gY29tYmluZUxhdGVzdChbXG4gICAgICAgICAgICBvZihwcmljaW5nVGllci5pc1N0YXJ0aW5nUHJpY2UpLFxuICAgICAgICAgICAgdGhpcy5idWlsZFByaWNpbmdUaWVyU3RyaW5nKHByaWNpbmdUaWVyKSxcbiAgICAgICAgICAgIHRoaXMuYnVpbGRQcmljaW5nVGllckZvclByb2R1Y3QocHJpY2luZ1RpZXIsIGJpbGxlZFByb2R1Y3QuYmlsbGluZ0ZyZXF1ZW5jeSksXG4gICAgICAgICAgICB0aGlzLmJ1aWxkUHJpY2luZ1RpZXJGb3JBZGRvbihwcmljaW5nVGllciksXG4gICAgICAgICAgICB0aGlzLmJ1aWxkUHJpY2VTdHJpbmdGb3JUaWVyKHByaWNpbmdUaWVyLCBiaWxsZWRQcm9kdWN0LmJpbGxpbmdGcmVxdWVuY3ksIHByaWNpbmdUaWVyLmlzU3RhcnRpbmdQcmljZSksXG4gICAgICAgICAgICB0aGlzLmJ1aWxkUHJpY2VTdHJpbmdGb3JUaWVyKHByaWNpbmdUaWVyKSxcbiAgICAgICAgICBdKS5waXBlKFxuICAgICAgICAgICAgbWFwKFxuICAgICAgICAgICAgICAoW1xuICAgICAgICAgICAgICAgIGlzU3RhcnRpbmdQcmljZSxcbiAgICAgICAgICAgICAgICBwcmljaW5nVGllclN0cmluZyxcbiAgICAgICAgICAgICAgICBwcmljaW5nVGllckZvclByb2R1Y3QsXG4gICAgICAgICAgICAgICAgcHJpY2luZ1RpZXJGb3JBZGRvbixcbiAgICAgICAgICAgICAgICBwcmljZVN0cmluZ0ZvclRpZXIsXG4gICAgICAgICAgICAgICAgcHJpY2VTdHJpbmdGb3JUaWVyV2l0aG91dEZyZXEsXG4gICAgICAgICAgICAgIF0pID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgaXNTdGFydGluZ1ByaWNlOiBpc1N0YXJ0aW5nUHJpY2UsXG4gICAgICAgICAgICAgICAgICBwcmljaW5nVGllclN0cmluZzogcHJpY2luZ1RpZXJTdHJpbmcsXG4gICAgICAgICAgICAgICAgICBwcmljaW5nVGllckZvclByb2R1Y3Q6IHByaWNpbmdUaWVyRm9yUHJvZHVjdCxcbiAgICAgICAgICAgICAgICAgIHByaWNpbmdUaWVyRm9yQWRkb246IHByaWNpbmdUaWVyRm9yQWRkb24sXG4gICAgICAgICAgICAgICAgICBwcmljZVN0cmluZ0ZvclRpZXI6IHByaWNlU3RyaW5nRm9yVGllcixcbiAgICAgICAgICAgICAgICAgIHByaWNlU3RyaW5nRm9yVGllcldpdGhvdXRGcmVxOiBwcmljZVN0cmluZ0ZvclRpZXJXaXRob3V0RnJlcSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGNvbWJpbmVMYXRlc3QoWy4uLnByaWNpbmdUaWVyT2JzZXJ2YWJsZXNdKTtcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICB0aGlzLnByaWNlRGF0YSQgPSB0aGlzLnByaWNpbmckLnBpcGUoXG4gICAgICBzd2l0Y2hNYXAoKHByaWNpbmcpID0+IHtcbiAgICAgICAgbGV0IGZpbHRlcmVkUHJpY2VzID0gcHJpY2luZy5wcmljZXM7XG4gICAgICAgIGlmIChwcmljaW5nLnByaWNlcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgZmlsdGVyZWRQcmljZXMgPSBwcmljaW5nLnByaWNlcy5maWx0ZXIoKHByaWNlKSA9PiBwcmljZS5wcmljZSA+IDApLnNvcnQodGhpcy5zb3J0UHJpY2VzQnlGcmVxdWVuY3kpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHByaWNlT2JzZXJ2YWJsZXMgPSBmaWx0ZXJlZFByaWNlcy5tYXAoKHByaWNlKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGNvbWJpbmVMYXRlc3QoW1xuICAgICAgICAgICAgb2YocHJpY2UuaXNTdGFydGluZ1ByaWNlKSxcbiAgICAgICAgICAgIHRoaXMuYnVpbGRQcmljZVN0cmluZ0ZvclByaWNpbmcocHJpY2UsIHByaWNpbmcuY3VycmVuY3ksIHRydWUsIGZhbHNlKSxcbiAgICAgICAgICAgIHRoaXMuYnVpbGRQcmljZVN0cmluZ0ZvclByaWNpbmcocHJpY2UsIHByaWNpbmcuY3VycmVuY3ksIGZhbHNlLCB0cnVlKSxcbiAgICAgICAgICAgIHRoaXMuYnVpbGRGcmVxdWVuY3lTdHJpbmcocHJpY2UuZnJlcXVlbmN5KSxcbiAgICAgICAgICAgIG9mKHRoaXMuYnVpbGRBYmJyZXZpYXRlZEZyZXF1ZW5jeVN0cmluZyhwcmljZS5mcmVxdWVuY3kpKSxcbiAgICAgICAgICBdKS5waXBlKFxuICAgICAgICAgICAgbWFwKFxuICAgICAgICAgICAgICAoW1xuICAgICAgICAgICAgICAgIGlzU3RhcnRpbmdQcmljZSxcbiAgICAgICAgICAgICAgICBwcmljZVN0cmluZ0ZvclByaWNpbmdXaXRob3V0RnJlcXVlbmN5LFxuICAgICAgICAgICAgICAgIHByaWNlU3RyaW5nRm9yUHJpY2luZ1dpdGhGcmVxdWVuY3ksXG4gICAgICAgICAgICAgICAgZnJlcXVlbmN5U3RyaW5nLFxuICAgICAgICAgICAgICAgIGFiYnJldkZyZXEsXG4gICAgICAgICAgICAgIF0pID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgaXNTdGFydGluZ1ByaWNlOiBpc1N0YXJ0aW5nUHJpY2UsXG4gICAgICAgICAgICAgICAgICBwcmljZVN0cmluZ0ZvclByaWNpbmdXaXRob3V0RnJlcXVlbmN5OiBwcmljZVN0cmluZ0ZvclByaWNpbmdXaXRob3V0RnJlcXVlbmN5LFxuICAgICAgICAgICAgICAgICAgcHJpY2VTdHJpbmdGb3JQcmljaW5nV2l0aEZyZXF1ZW5jeTogcHJpY2VTdHJpbmdGb3JQcmljaW5nV2l0aEZyZXF1ZW5jeSxcbiAgICAgICAgICAgICAgICAgIGZyZXF1ZW5jeVN0cmluZzogZnJlcXVlbmN5U3RyaW5nLFxuICAgICAgICAgICAgICAgICAgYWJicmV2aWF0ZWRGcmVxdWVuY3lTdHJpbmc6IGFiYnJldkZyZXEsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBjb21iaW5lTGF0ZXN0KFsuLi5wcmljZU9ic2VydmFibGVzXSk7XG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgdGhpcy5jb21taXRtZW50TWVzc2FnZSQgPSB0aGlzLmJ1aWxkQ29tbWl0bWVudE1lc3NhZ2UoKTtcbiAgICB0aGlzLnNldHVwRmVlU3RyaW5nJCA9IHRoaXMuZGlzcGxheVByaWNlU2VydmljZS5nZXRTZXR1cEZlZVN0cmluZygpO1xuICAgIHRoaXMuaXNGaXJzdFRpZXJGcmVlJCA9IHRoaXMuYmlsbGVkUHJvZHVjdCQucGlwZShcbiAgICAgIG1hcCgoYmlsbGVkUHJvZHVjdCkgPT4ge1xuICAgICAgICByZXR1cm4gYmlsbGVkUHJvZHVjdC5wcmljaW5nVGllcnMubGVuZ3RoID4gMSAmJiBiaWxsZWRQcm9kdWN0LnByaWNpbmdUaWVycy5zb21lKChpdGVtKSA9PiBpdGVtLnByaWNlID09PSAwKTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXMuaGFzT3duUHJvcGVydHkoJ3ByaWNpbmcnKSkge1xuICAgICAgdGhpcy5wcmljaW5nJCQubmV4dChjaGFuZ2VzLnByaWNpbmcuY3VycmVudFZhbHVlKTtcbiAgICB9XG4gICAgaWYgKGNoYW5nZXMuaGFzT3duUHJvcGVydHkoJ2JpbGxlZFByb2R1Y3QnKSkge1xuICAgICAgdGhpcy5iaWxsZWRQcm9kdWN0JCQubmV4dChjaGFuZ2VzLmJpbGxlZFByb2R1Y3QuY3VycmVudFZhbHVlKTtcbiAgICB9XG4gICAgaWYgKGNoYW5nZXMuaGFzT3duUHJvcGVydHkoJ2hhc1ZlcmlmaWVkQ29udHJhY3QnKSkge1xuICAgICAgdGhpcy5oYXNWZXJpZmllZENvbnRyYWN0JCQubmV4dChjaGFuZ2VzLmhhc1ZlcmlmaWVkQ29udHJhY3QuY3VycmVudFZhbHVlKTtcbiAgICB9XG4gIH1cblxuICBidWlsZFByaWNpbmdUaWVyU3RyaW5nKHRpZXI6IFByaWNpbmdUaWVyKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcbiAgICBsZXQgbWF4ID0gU3RyaW5nKHRpZXIucmFuZ2VNYXgpO1xuICAgIGlmICh0aWVyLnJhbmdlTWF4ID09PSAtMSkge1xuICAgICAgbWF4ID0gJ+KInic7XG4gICAgICBpZiAodGllci5yYW5nZU1pbiA9PT0gMCB8fCB0aWVyLnJhbmdlTWluID09PSAxKSB7XG4gICAgICAgIHJldHVybiBvZignJyk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnRyYW5zbGF0ZVNlcnZpY2Uuc3RyZWFtKCdGUk9OVEVORC5TVE9SRS5NSU5fVE9fTUFYJywge1xuICAgICAgbWluUmFuZ2U6IFN0cmluZyh0aWVyLnJhbmdlTWluKSxcbiAgICAgIG1heFJhbmdlOiBtYXgsXG4gICAgfSk7XG4gIH1cblxuICBidWlsZFByaWNpbmdUaWVyRm9yUHJvZHVjdCh0aWVyOiBQcmljaW5nVGllciwgZnJlcXVlbmN5Pzogc3RyaW5nKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gY29tYmluZUxhdGVzdChbdGhpcy5idWlsZFByaWNpbmdUaWVyU3RyaW5nKHRpZXIpLCB0aGlzLmJ1aWxkRnJlcXVlbmN5U3RyaW5nKGZyZXF1ZW5jeSldKS5waXBlKFxuICAgICAgc3dpdGNoTWFwKChbcHJpY2luZ1RpZXIsIGZvcm1hdHRlZEZyZXF1ZW5jeV0pID0+IHtcbiAgICAgICAgaWYgKHByaWNpbmdUaWVyKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMudHJhbnNsYXRlU2VydmljZS5zdHJlYW0oJ0ZST05URU5ELlNUT1JFLlBST0RVQ1RfUFJJQ0lOR19XSVRIX0ZSRVFVRU5DWScsIHtcbiAgICAgICAgICAgIHByaWNpbmdUaWVyOiBwcmljaW5nVGllcixcbiAgICAgICAgICAgIGZyZXF1ZW5jeTogZm9ybWF0dGVkRnJlcXVlbmN5LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvZihmb3JtYXR0ZWRGcmVxdWVuY3kpO1xuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIGJ1aWxkUHJpY2luZ1RpZXJGb3JBZGRvbih0aWVyOiBQcmljaW5nVGllcik6IE9ic2VydmFibGU8c3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMuYnVpbGRQcmljaW5nVGllclN0cmluZyh0aWVyKS5waXBlKG1hcCgocHJpY2luZ1JhbmdlKSA9PiAocHJpY2luZ1JhbmdlID8gcHJpY2luZ1JhbmdlIDogJycpKSk7XG4gIH1cblxuICBzb3J0UHJpY2VzQnlGcmVxdWVuY3kocHJpY2VBOiBQcmljZSwgcHJpY2VCOiBQcmljZSk6IG51bWJlciB7XG4gICAgLy8gdGhpcyBtYXAgaXMgY29kZWQgYmFzZWQgb24gZnJlcXVlbmN5IHZhbHVlcyBkZXNjcmliZWQgYnkgdGhlIGVudW1zIGRlc2NyaWJlZCBpbiB0aGUgbWFya2V0cGxhY2UgcGFja2FnZXMgdmVuZGFzdGFcbiAgICAvLyBhcGlzIGFuZCB0aGUgY29ycmVzcG9uZGluZyB0cmFuc2xhdGlvbnMgdG8gc3RyaW5ncyBsYWNlZCB0aHJvdWdob3V0IGdhbGF4eVxuICAgIGNvbnN0IHByaWNlRnJlcXVlbmN5Q29tcGFyaXNvbk1hcDogTWFwPHN0cmluZywgTWFwPHN0cmluZywgbnVtYmVyPj4gPSBuZXcgTWFwPHN0cmluZywgTWFwPHN0cmluZywgbnVtYmVyPj4oW1xuICAgICAgW1xuICAgICAgICAnTU9OVEhMWScsXG4gICAgICAgIG5ldyBNYXAoW1xuICAgICAgICAgIFsnTU9OVEhMWScsIDBdLFxuICAgICAgICAgIFsnWUVBUkxZJywgLTFdLFxuICAgICAgICAgIFsnT05DRScsIC0xXSxcbiAgICAgICAgICBbJ09ORSBUSU1FJywgLTFdLFxuICAgICAgICAgIFsnT05FX1RJTUUnLCAtMV0sXG4gICAgICAgIF0pLFxuICAgICAgXSxcbiAgICAgIFtcbiAgICAgICAgJ1lFQVJMWScsXG4gICAgICAgIG5ldyBNYXAoW1xuICAgICAgICAgIFsnTU9OVEhMWScsIDFdLFxuICAgICAgICAgIFsnWUVBUkxZJywgMF0sXG4gICAgICAgICAgWydPTkNFJywgLTFdLFxuICAgICAgICAgIFsnT05FIFRJTUUnLCAtMV0sXG4gICAgICAgICAgWydPTkVfVElNRScsIC0xXSxcbiAgICAgICAgXSksXG4gICAgICBdLFxuICAgICAgW1xuICAgICAgICAnT05DRScsXG4gICAgICAgIG5ldyBNYXAoW1xuICAgICAgICAgIFsnTU9OVEhMWScsIDFdLFxuICAgICAgICAgIFsnWUVBUkxZJywgMV0sXG4gICAgICAgICAgWydPTkNFJywgMF0sXG4gICAgICAgICAgWydPTkUgVElNRScsIDBdLFxuICAgICAgICAgIFsnT05FX1RJTUUnLCAwXSxcbiAgICAgICAgXSksXG4gICAgICBdLFxuICAgICAgW1xuICAgICAgICAnT05FIFRJTUUnLFxuICAgICAgICBuZXcgTWFwKFtcbiAgICAgICAgICBbJ01PTlRITFknLCAxXSxcbiAgICAgICAgICBbJ1lFQVJMWScsIDFdLFxuICAgICAgICAgIFsnT05DRScsIDBdLFxuICAgICAgICAgIFsnT05FIFRJTUUnLCAwXSxcbiAgICAgICAgICBbJ09ORV9USU1FJywgMF0sXG4gICAgICAgIF0pLFxuICAgICAgXSxcbiAgICAgIFtcbiAgICAgICAgJ09ORV9USU1FJyxcbiAgICAgICAgbmV3IE1hcChbXG4gICAgICAgICAgWydNT05USExZJywgMV0sXG4gICAgICAgICAgWydZRUFSTFknLCAxXSxcbiAgICAgICAgICBbJ09OQ0UnLCAwXSxcbiAgICAgICAgICBbJ09ORSBUSU1FJywgMF0sXG4gICAgICAgICAgWydPTkVfVElNRScsIDBdLFxuICAgICAgICBdKSxcbiAgICAgIF0sXG4gICAgXSk7XG5cbiAgICBpZiAocHJpY2VGcmVxdWVuY3lDb21wYXJpc29uTWFwLmdldChwcmljZUEuZnJlcXVlbmN5LnRvVXBwZXJDYXNlKCkpID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbXBhcmVWYWwgPSBwcmljZUZyZXF1ZW5jeUNvbXBhcmlzb25NYXBcbiAgICAgIC5nZXQocHJpY2VBLmZyZXF1ZW5jeS50b1VwcGVyQ2FzZSgpKVxuICAgICAgLmdldChwcmljZUIuZnJlcXVlbmN5LnRvVXBwZXJDYXNlKCkpO1xuICAgIHJldHVybiBjb21wYXJlVmFsID8gY29tcGFyZVZhbCA6IDA7XG4gIH1cblxuICBidWlsZFByaWNlU3RyaW5nRm9yUHJpY2luZyhcbiAgICBwcmljZTogUHJpY2UsXG4gICAgY3VycmVuY3k6IHN0cmluZyxcbiAgICBleGNsdWRlRnJlcXVlbmN5OiBib29sZWFuLFxuICAgIGNhbkluY2x1ZGVTdGFydGluZ0F0UHJlZml4OiBib29sZWFuLFxuICApOiBPYnNlcnZhYmxlPHN0cmluZz4ge1xuICAgIHJldHVybiB0aGlzLmRpc3BsYXlQcmljZVNlcnZpY2UuZm9ybWF0RGlzcGxheVByaWNlKFxuICAgICAgcHJpY2UucHJpY2UsXG4gICAgICBjdXJyZW5jeSxcbiAgICAgIChleGNsdWRlRnJlcXVlbmN5ID8gJycgOiBwcmljZS5mcmVxdWVuY3kpIGFzIGFueSxcbiAgICAgIHRydWUsXG4gICAgICB0cnVlLFxuICAgICAgdHJ1ZSxcbiAgICAgIHByaWNlLmlzU3RhcnRpbmdQcmljZSAmJiBjYW5JbmNsdWRlU3RhcnRpbmdBdFByZWZpeCxcbiAgICApO1xuICB9XG5cbiAgYnVpbGRQcmljZVN0cmluZ0ZvclRpZXIoXG4gICAgdGllcjogUHJpY2luZ1RpZXIsXG4gICAgZnJlcXVlbmN5PzogTWFya2V0cGxhY2VCaWxsaW5nRnJlcXVlbmN5LFxuICAgIGlzU3RhcnRpbmdQcmljZT86IGJvb2xlYW4sXG4gICk6IE9ic2VydmFibGU8c3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMuZGlzcGxheVByaWNlU2VydmljZS5mb3JtYXREaXNwbGF5UHJpY2UoXG4gICAgICB0aWVyLnByaWNlLFxuICAgICAgdGhpcy5iaWxsZWRQcm9kdWN0LmN1cnJlbmN5LFxuICAgICAgZnJlcXVlbmN5IGFzIGFueSxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIHVuZGVmaW5lZCxcbiAgICAgIGlzU3RhcnRpbmdQcmljZSxcbiAgICApO1xuICB9XG5cbiAgYnVpbGRGcmVxdWVuY3lTdHJpbmcoZnJlcXVlbmN5Pzogc3RyaW5nKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5kaXNwbGF5UHJpY2VTZXJ2aWNlLmZvcm1hdEJpbGxpbmdGcmVxdWVuY3koZnJlcXVlbmN5KTtcbiAgfVxuXG4gIGJ1aWxkQWJicmV2aWF0ZWRGcmVxdWVuY3lTdHJpbmcoZnJlcXVlbmN5Pzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBzd2l0Y2ggKChmcmVxdWVuY3kgfHwgJycpLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgIGNhc2UgJ2RhaWx5JzpcbiAgICAgICAgcmV0dXJuICdkeSc7XG4gICAgICBjYXNlICd3ZWVrbHknOlxuICAgICAgICByZXR1cm4gJ3drJztcbiAgICAgIGNhc2UgJ21vbnRobHknOlxuICAgICAgICByZXR1cm4gJ21vJztcbiAgICAgIGNhc2UgJ3llYXJseSc6XG4gICAgICAgIHJldHVybiAneXInO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGJ1aWxkQ29tbWl0bWVudE1lc3NhZ2UoKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gY29tYmluZUxhdGVzdChbXG4gICAgICB0aGlzLnRyYW5zbGF0ZVNlcnZpY2Uuc3RyZWFtKCdGUk9OVEVORC5TVE9SRS5QUklDSU5HX0ZSRVFVRU5DSUVTJyksXG4gICAgICB0aGlzLmJpbGxlZFByb2R1Y3QkLFxuICAgICAgdGhpcy5wcmljaW5nJCxcbiAgICAgIHRoaXMuaXNGcmVlJCxcbiAgICAgIHRoaXMuc2hvdWxkQ29udGFjdFNhbGVzJCxcbiAgICBdKS5waXBlKFxuICAgICAgc3dpdGNoTWFwKChbZnJlcXVlbmN5VHJhbnNsYXRpb25zLCBiaWxsZWRQcm9kdWN0LCBwcmljaW5nLCBpc0ZyZWUsIHNob3VsZENvbnRhY3RTYWxlc10pID0+IHtcbiAgICAgICAgY29uc3QgZnJlcXVlbmN5ID0gYmlsbGVkUHJvZHVjdFxuICAgICAgICAgID8gYmlsbGVkUHJvZHVjdC5iaWxsaW5nRnJlcXVlbmN5LnRvU3RyaW5nKCkudG9Mb3dlckNhc2UoKVxuICAgICAgICAgIDogcHJpY2luZyAmJiBwcmljaW5nLnByaWNlcy5sZW5ndGggPiAwXG4gICAgICAgICAgPyBwcmljaW5nLnByaWNlc1swXS5mcmVxdWVuY3kudG9Mb3dlckNhc2UoKVxuICAgICAgICAgIDogJyc7XG4gICAgICAgIGxldCBmcmVxdWVuY3lTdHJpbmcgPSAnJztcbiAgICAgICAgaWYgKGZyZXF1ZW5jeSA9PT0gJ3llYXJseScpIHtcbiAgICAgICAgICBmcmVxdWVuY3lTdHJpbmcgPSBmcmVxdWVuY3lUcmFuc2xhdGlvbnMuWUVBUjtcbiAgICAgICAgfSBlbHNlIGlmIChmcmVxdWVuY3kgPT09ICdtb250aGx5Jykge1xuICAgICAgICAgIGZyZXF1ZW5jeVN0cmluZyA9IGZyZXF1ZW5jeVRyYW5zbGF0aW9ucy5NT05USDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWZyZXF1ZW5jeVN0cmluZyB8fCBpc0ZyZWUgfHwgc2hvdWxkQ29udGFjdFNhbGVzKSB7XG4gICAgICAgICAgcmV0dXJuIG9mKCcnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYmlsbGVkUHJvZHVjdCAmJiBiaWxsZWRQcm9kdWN0LmNvbW1pdG1lbnQpIHtcbiAgICAgICAgICBjb25zdCBpbml0aWFsID0gYmlsbGVkUHJvZHVjdC5jb21taXRtZW50LmluaXRpYWw7XG4gICAgICAgICAgY29uc3QgcmV