UNPKG

@spartacus/core

Version:

Spartacus - the core framework

152 lines 22.3 kB
import { Injectable } from '@angular/core'; import { combineLatest, of } from 'rxjs'; import { filter, map, switchMap } from 'rxjs/operators'; import { PageMetaResolver } from '../../cms/page/page-meta.resolver'; import { PageType } from '../../model/cms.model'; import * as i0 from "@angular/core"; import * as i1 from "../../routing/facade/routing.service"; import * as i2 from "../facade/product.service"; import * as i3 from "../../i18n/translation.service"; import * as i4 from "../../cms/page/base-page-meta.resolver"; import * as i5 from "../../cms/page/routing/page-link.service"; /** * Resolves the page data for the Product Detail Page * based on the `PageType.PRODUCT_PAGE`. * * The page title, heading, description, breadcrumbs and * first GALLERY image are resolved if available in the data. */ export class ProductPageMetaResolver extends PageMetaResolver { constructor(routingService, productService, translation, basePageMetaResolver, pageLinkService) { super(); this.routingService = routingService; this.productService = productService; this.translation = translation; this.basePageMetaResolver = basePageMetaResolver; this.pageLinkService = pageLinkService; // reusable observable for product data based on the current page this.product$ = this.routingService .getRouterState() .pipe(map((state) => state.state.params['productCode']), filter((code) => !!code), switchMap((code) => this.productService.get(code, "details" /* DETAILS */)), filter((p) => Boolean(p))); this.pageType = PageType.PRODUCT_PAGE; } /** * Resolves the page heading for the Product Detail Page. * The page heading is used in the UI (`<h1>`), where as the page * title is used by the browser and crawlers. */ resolveHeading() { return this.product$.pipe(switchMap((p) => this.translation.translate('pageMetaResolver.product.heading', { heading: p.name, }))); } /** * Resolves the page title for the Product Detail Page. The page title * is resolved with the product name, the first category and the manufacturer. * The page title used by the browser (history, tabs) and crawlers. */ resolveTitle() { return this.product$.pipe(switchMap((product) => { let title = product.name; title += this.resolveFirstCategory(product); title += this.resolveManufacturer(product); return this.translation.translate('pageMetaResolver.product.title', { title: title, }); })); } /** * Resolves the page description for the Product Detail Page. The description * is based on the `product.summary`. */ resolveDescription() { return this.product$.pipe(switchMap((product) => this.translation.translate('pageMetaResolver.product.description', { description: product.summary, }))); } /** * Resolves breadcrumbs for the Product Detail Page. The breadcrumbs are driven by * a static home page crumb and a crumb for each category. */ resolveBreadcrumbs() { return combineLatest([ this.product$.pipe(), this.translation.translate('common.home'), ]).pipe(map(([product, label]) => { const breadcrumbs = []; breadcrumbs.push({ label, link: '/' }); for (const { name, code, url } of product.categories || []) { breadcrumbs.push({ label: name || code, link: url, }); } return breadcrumbs; })); } /** * Resolves the main page image for the Product Detail Page. The product image * is based on the PRIMARY product image. The zoom format is used by default. */ resolveImage() { return this.product$.pipe(map((product) => { var _a, _b, _c, _d; return (_d = (_c = (_b = (_a = product.images) === null || _a === void 0 ? void 0 : _a.PRIMARY) === null || _b === void 0 ? void 0 : _b.zoom) === null || _c === void 0 ? void 0 : _c.url) !== null && _d !== void 0 ? _d : null; })); } resolveFirstCategory(product) { var _a; const firstCategory = (_a = product === null || product === void 0 ? void 0 : product.categories) === null || _a === void 0 ? void 0 : _a[0]; return firstCategory ? ` | ${firstCategory.name || firstCategory.code}` : ''; } resolveManufacturer(product) { return product.manufacturer ? ` | ${product.manufacturer}` : ''; } resolveRobots() { return this.basePageMetaResolver.resolveRobots(); } /** * Resolves the canonical url for the product page using the default canonical url * configuration. * * In case of a variant product, the baseProduct code is used to resolve the url. It's important * to know that this has a few limitations: * - We're not always able to get the super baseProduct, in case of multi-level variants. * OCC only exposes the direct baseProduct, which might still not resolve in the correct * canonical URL. This is business driven and subject to change in a customization. * - The url resolved for the variant doesn't contain any content other then the product code. * This means that we do not provide any product data to resolve pretty URLs (for example * the product title). */ resolveCanonicalUrl() { return this.product$.pipe(switchMap((product) => this.findBaseProduct(product)), map((product) => { const url = this.routingService.getFullUrl({ cxRoute: 'product', params: product, }); return this.pageLinkService.getCanonicalUrl({}, url); })); } /** * Resolves the base product whenever the given product is a variant product. * * Since product variants can be multi-layered, we recursively try to find the base product * this might be too opinionated for your business though. */ findBaseProduct(product) { if (product === null || product === void 0 ? void 0 : product.baseProduct) { return this.productService .get(product.baseProduct, "list" /* LIST */) .pipe(filter((product) => Boolean(product)), switchMap((baseProduct) => this.findBaseProduct(baseProduct))); } return of(product); } } ProductPageMetaResolver.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: ProductPageMetaResolver, deps: [{ token: i1.RoutingService }, { token: i2.ProductService }, { token: i3.TranslationService }, { token: i4.BasePageMetaResolver }, { token: i5.PageLinkService }], target: i0.ɵɵFactoryTarget.Injectable }); ProductPageMetaResolver.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: ProductPageMetaResolver, providedIn: 'root' }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: ProductPageMetaResolver, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: function () { return [{ type: i1.RoutingService }, { type: i2.ProductService }, { type: i3.TranslationService }, { type: i4.BasePageMetaResolver }, { type: i5.PageLinkService }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZHVjdC1wYWdlLW1ldGEucmVzb2x2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jb3JlL3NyYy9wcm9kdWN0L3NlcnZpY2VzL3Byb2R1Y3QtcGFnZS1tZXRhLnJlc29sdmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLGFBQWEsRUFBYyxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDckQsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHeEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFXckUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHVCQUF1QixDQUFDOzs7Ozs7O0FBTWpEOzs7Ozs7R0FNRztBQUlILE1BQU0sT0FBTyx1QkFDWCxTQUFRLGdCQUFnQjtJQVN4QixZQUNZLGNBQThCLEVBQzlCLGNBQThCLEVBQzlCLFdBQStCLEVBQy9CLG9CQUEwQyxFQUMxQyxlQUFnQztRQUUxQyxLQUFLLEVBQUUsQ0FBQztRQU5FLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUM5QixtQkFBYyxHQUFkLGNBQWMsQ0FBZ0I7UUFDOUIsZ0JBQVcsR0FBWCxXQUFXLENBQW9CO1FBQy9CLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBc0I7UUFDMUMsb0JBQWUsR0FBZixlQUFlLENBQWlCO1FBTTVDLGlFQUFpRTtRQUN2RCxhQUFRLEdBQXdCLElBQUksQ0FBQyxjQUFjO2FBQzFELGNBQWMsRUFBRTthQUNoQixJQUFJLENBQ0gsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxFQUNqRCxNQUFNLENBQUMsQ0FBQyxJQUFJLEVB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O1lBQ3hCLE9BQU8sSUFBSSxDQUFDLGNBQWM7aUJBQ3ZCLEdBQUcsQ0FBQyxPQUFPLENBQUMsV0FBVyxvQkFBb0I7aUJBQzNDLElBQUksQ0FDSCxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUNyQyxTQUFTLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FDOUQsQ0FBQztTQUNMO1FBQ0QsT0FBTyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDckIsQ0FBQzs7b0hBektVLHVCQUF1Qjt3SEFBdkIsdUJBQXVCLGNBRnRCLE1BQU07MkZBRVAsdUJBQXVCO2tCQUhuQyxVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGNvbWJpbmVMYXRlc3QsIE9ic2VydmFibGUsIG9mIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBmaWx0ZXIsIG1hcCwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQnJlYWRjcnVtYk1ldGEsIFBhZ2VSb2JvdHNNZXRhIH0gZnJvbSAnLi4vLi4vY21zL21vZGVsL3BhZ2UubW9kZWwnO1xuaW1wb3J0IHsgQmFzZVBhZ2VNZXRhUmVzb2x2ZXIgfSBmcm9tICcuLi8uLi9jbXMvcGFnZS9iYXNlLXBhZ2UtbWV0YS5yZXNvbHZlcic7XG5pbXBvcnQgeyBQYWdlTWV0YVJlc29sdmVyIH0gZnJvbSAnLi4vLi4vY21zL3BhZ2UvcGFnZS1tZXRhLnJlc29sdmVyJztcbmltcG9ydCB7XG4gIFBhZ2VCcmVhZGNydW1iUmVzb2x2ZXIsXG4gIFBhZ2VEZXNjcmlwdGlvblJlc29sdmVyLFxuICBQYWdlSGVhZGluZ1Jlc29sdmVyLFxuICBQYWdlSW1hZ2VSZXNvbHZlcixcbiAgUGFnZVJvYm90c1Jlc29sdmVyLFxuICBQYWdlVGl0bGVSZXNvbHZlcixcbn0gZnJvbSAnLi4vLi4vY21zL3BhZ2UvcGFnZS5yZXNvbHZlcnMnO1xuaW1wb3J0IHsgUGFnZUxpbmtTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY21zL3BhZ2Uvcm91dGluZy9wYWdlLWxpbmsuc2VydmljZSc7XG5pbXBvcnQgeyBUcmFuc2xhdGlvblNlcnZpY2UgfSBmcm9tICcuLi8uLi9pMThuL3RyYW5zbGF0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgUGFnZVR5cGUgfSBmcm9tICcuLi8uLi9tb2RlbC9jbXMubW9kZWwnO1xuaW1wb3J0IHsgQ2F0ZWdvcnksIFByb2R1Y3QgfSBmcm9tICcuLi8uLi9tb2RlbC9wcm9kdWN0Lm1vZGVsJztcbmltcG9ydCB7IFJvdXRpbmdTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vcm91dGluZy9mYWNhZGUvcm91dGluZy5zZXJ2aWNlJztcbmltcG9ydCB7IFByb2R1Y3RTZXJ2aWNlIH0gZnJvbSAnLi4vZmFjYWRlL3Byb2R1Y3Quc2VydmljZSc7XG5pbXBvcnQgeyBQcm9kdWN0U2NvcGUgfSBmcm9tICcuLi9tb2RlbC9wcm9kdWN0LXNjb3BlJztcblxuLyoqXG4gKiBSZXNvbHZlcyB0aGUgcGFnZSBkYXRhIGZvciB0aGUgUHJvZHVjdCBEZXRhaWwgUGFnZVxuICogYmFzZWQgb24gdGhlIGBQYWdlVHlwZS5QUk9EVUNUX1BBR0VgLlxuICpcbiAqIFRoZSBwYWdlIHRpdGxlLCBoZWFkaW5nLCBkZXNjcmlwdGlvbiwgYnJlYWRjcnVtYnMgYW5kXG4gKiBmaXJzdCBHQUxMRVJZIGltYWdlIGFyZSByZXNvbHZlZCBpZiBhdmFpbGFibGUgaW4gdGhlIGRhdGEuXG4gKi9cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxufSlcbmV4cG9ydCBjbGFzcyBQcm9kdWN0UGFnZU1ldGFSZXNvbHZlclxuICBleHRlbmRzIFBhZ2VNZXRhUmVzb2x2ZXJcbiAgaW1wbGVtZW50c1xuICAgIFBhZ2VIZWFkaW5nUmVzb2x2ZXIsXG4gICAgUGFnZVRpdGxlUmVzb2x2ZXIsXG4gICAgUGFnZURlc2NyaXB0aW9uUmVzb2x2ZXIsXG4gICAgUGFnZUJyZWFkY3J1bWJSZXNvbHZlcixcbiAgICBQYWdlSW1hZ2VSZXNvbHZlcixcbiAgICBQYWdlUm9ib3RzUmVzb2x2ZXJcbntcbiAgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIHJvdXRpbmdTZXJ2aWNlOiBSb3V0aW5nU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgcHJvZHVjdFNlcnZpY2U6IFByb2R1Y3RTZXJ2aWNlLFxuICAgIHByb3RlY3RlZCB0cmFuc2xhdGlvbjogVHJhbnNsYXRpb25TZXJ2aWNlLFxuICAgIHByb3RlY3RlZCBiYXNlUGFnZU1ldGFSZXNvbHZlcjogQmFzZVBhZ2VNZXRhUmVzb2x2ZXIsXG4gICAgcHJvdGVjdGVkIHBhZ2VMaW5rU2VydmljZTogUGFnZUxpbmtTZXJ2aWNlXG4gICkge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5wYWdlVHlwZSA9IFBhZ2VUeXBlLlBST0RVQ1RfUEFHRTtcbiAgfVxuXG4gIC8vIHJldXNhYmxlIG9ic2VydmFibGUgZm9yIHByb2R1Y3QgZGF0YSBiYXNlZCBvbiB0aGUgY3VycmVudCBwYWdlXG4gIHByb3RlY3RlZCBwcm9kdWN0JDogT2JzZXJ2YWJsZTxQcm9kdWN0PiA9IHRoaXMucm91dGluZ1NlcnZpY2VcbiAgICAuZ2V0Um91dGVyU3RhdGUoKVxuICAgIC5waXBlKFxuICAgICAgbWFwKChzdGF0ZSkgPT4gc3RhdGUuc3RhdGUucGFyYW1zWydwcm9kdWN0Q29kZSddKSxcbiAgICAgIGZpbHRlcigoY29kZSkgPT4gISFjb2RlKSxcbiAgICAgIHN3aXRjaE1hcCgoY29kZSkgPT4gdGhpcy5wcm9kdWN0U2VydmljZS5nZXQoY29kZSwgUHJvZHVjdFNjb3BlLkRFVEFJTFMpKSxcbiAgICAgIGZpbHRlcigocCkgPT4gQm9vbGVhbihwKSlcbiAgICApO1xuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyB0aGUgcGFnZSBoZWFkaW5nIGZvciB0aGUgUHJvZHVjdCBEZXRhaWwgUGFnZS5cbiAgICogVGhlIHBhZ2UgaGVhZGluZyBpcyB1c2VkIGluIHRoZSBVSSAoYDxoMT5gKSwgd2hlcmUgYXMgdGhlIHBhZ2VcbiAgICogdGl0bGUgaXMgdXNlZCBieSB0aGUgYnJvd3NlciBhbmQgY3Jhd2xlcnMuXG4gICAqL1xuICByZXNvbHZlSGVhZGluZygpOiBPYnNlcnZhYmxlPHN0cmluZz4ge1xuICAgIHJldHVybiB0aGlzLnByb2R1Y3QkLnBpcGUoXG4gICAgICBzd2l0Y2hNYXAoKHA6IFByb2R1Y3QpID0+XG4gICAgICAgIHRoaXMudHJhbnNsYXRpb24udHJhbnNsYXRlKCdwYWdlTWV0YVJlc29sdmVyLnByb2R1Y3QuaGVhZGluZycsIHtcbiAgICAgICAgICBoZWFkaW5nOiBwLm5hbWUsXG4gICAgICAgIH0pXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyB0aGUgcGFnZSB0aXRsZSBmb3IgdGhlIFByb2R1Y3QgRGV0YWlsIFBhZ2UuIFRoZSBwYWdlIHRpdGxlXG4gICAqIGlzIHJlc29sdmVkIHdpdGggdGhlIHByb2R1Y3QgbmFtZSwgdGhlIGZpcnN0IGNhdGVnb3J5IGFuZCB0aGUgbWFudWZhY3R1cmVyLlxuICAgKiBUaGUgcGFnZSB0aXRsZSB1c2VkIGJ5IHRoZSBicm93c2VyIChoaXN0b3J5LCB0YWJzKSBhbmQgY3Jhd2xlcnMuXG4gICAqL1xuICByZXNvbHZlVGl0bGUoKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5wcm9kdWN0JC5waXBlKFxuICAgICAgc3dpdGNoTWFwKChwcm9kdWN0KSA9PiB7XG4gICAgICAgIGxldCB0aXRsZSA9IHByb2R1Y3QubmFtZTtcbiAgICAgICAgdGl0bGUgKz0gdGhpcy5yZXNvbHZlRmlyc3RDYXRlZ29yeShwcm9kdWN0KTtcbiAgICAgICAgdGl0bGUgKz0gdGhpcy5yZXNvbHZlTWFudWZhY3R1cmVyKHByb2R1Y3QpO1xuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2xhdGlvbi50cmFuc2xhdGUoJ3BhZ2VNZXRhUmVzb2x2ZXIucHJvZHVjdC50aXRsZScsIHtcbiAgICAgICAgICB0aXRsZTogdGl0bGUsXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIHRoZSBwYWdlIGRlc2NyaXB0aW9uIGZvciB0aGUgUHJvZHVjdCBEZXRhaWwgUGFnZS4gVGhlIGRlc2NyaXB0aW9uXG4gICAqIGlzIGJhc2VkIG9uIHRoZSBgcHJvZHVjdC5zdW1tYXJ5YC5cbiAgICovXG4gIHJlc29sdmVEZXNjcmlwdGlvbigpOiBPYnNlcnZhYmxlPHN0cmluZz4ge1xuICAgIHJldHVybiB0aGlzLnByb2R1Y3QkLnBpcGUoXG4gICAgICBzd2l0Y2hNYXAoKHByb2R1Y3QpID0+XG4gICAgICAgIHRoaXMudHJhbnNsYXRpb24udHJhbnNsYXRlKCdwYWdlTWV0YVJlc29sdmVyLnByb2R1Y3QuZGVzY3JpcHRpb24nLCB7XG4gICAgICAgICAgZGVzY3JpcHRpb246IHByb2R1Y3Quc3VtbWFyeSxcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIGJyZWFkY3J1bWJzIGZvciB0aGUgUHJvZHVjdCBEZXRhaWwgUGFnZS4gVGhlIGJyZWFkY3J1bWJzIGFyZSBkcml2ZW4gYnlcbiAgICogYSBzdGF0aWMgaG9tZSBwYWdlIGNydW1iIGFuZCBhIGNydW1iIGZvciBlYWNoIGNhdGVnb3J5LlxuICAgKi9cbiAgcmVzb2x2ZUJyZWFkY3J1bWJzKCk6IE9ic2VydmFibGU8QnJlYWRjcnVtYk1ldGFbXT4ge1xuICAgIHJldHVybiBjb21iaW5lTGF0ZXN0KFtcbiAgICAgIHRoaXMucHJvZHVjdCQucGlwZSgpLFxuICAgICAgdGhpcy50cmFuc2xhdGlvbi50cmFuc2xhdGUoJ2NvbW1vbi5ob21lJyksXG4gICAgXSkucGlwZShcbiAgICAgIG1hcCgoW3Byb2R1Y3QsIGxhYmVsXSkgPT4ge1xuICAgICAgICBjb25zdCBicmVhZGNydW1icyA9IFtdO1xuICAgICAgICBicmVhZGNydW1icy5wdXNoKHsgbGFiZWwsIGxpbms6ICcvJyB9KTtcbiAgICAgICAgZm9yIChjb25zdCB7IG5hbWUsIGNvZGUsIHVybCB9IG9mIHByb2R1Y3QuY2F0ZWdvcmllcyB8fCBbXSkge1xuICAgICAgICAgIGJyZWFkY3J1bWJzLnB1c2goe1xuICAgICAgICAgICAgbGFiZWw6IG5hbWUgfHwgY29kZSxcbiAgICAgICAgICAgIGxpbms6IHVybCxcbiAgICAgICAgICB9IGFzIEJyZWFkY3J1bWJNZXRhKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYnJlYWRjcnVtYnM7XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgdGhlIG1haW4gcGFnZSBpbWFnZSBmb3IgdGhlIFByb2R1Y3QgRGV0YWlsIFBhZ2UuIFRoZSBwcm9kdWN0IGltYWdlXG4gICAqIGlzIGJhc2VkIG9uIHRoZSBQUklNQVJZIHByb2R1Y3QgaW1hZ2UuIFRoZSB6b29tIGZvcm1hdCBpcyB1c2VkIGJ5IGRlZmF1bHQuXG4gICAqL1xuICByZXNvbHZlSW1hZ2UoKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5wcm9kdWN0JC5waXBlKFxuICAgICAgbWFwKChwcm9kdWN0KSA9PiAoPGFueT5wcm9kdWN0LmltYWdlcz8uUFJJTUFSWSk/Lnpvb20/LnVybCA/PyBudWxsKVxuICAgICk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcmVzb2x2ZUZpcnN0Q2F0ZWdvcnkocHJvZHVjdDogUHJvZHVjdCk6IHN0cmluZyB7XG4gICAgY29uc3QgZmlyc3RDYXRlZ29yeTogQ2F0ZWdvcnkgfCB1bmRlZmluZWQgPSBwcm9kdWN0Py5jYXRlZ29yaWVzPy5bMF07XG5cbiAgICByZXR1cm4gZmlyc3RDYXRlZ29yeVxuICAgICAgPyBgIHwgJHtmaXJzdENhdGVnb3J5Lm5hbWUgfHwgZmlyc3RDYXRlZ29yeS5jb2RlfWBcbiAgICAgIDogJyc7XG4gIH1cblxuICBwcm90ZWN0ZWQgcmVzb2x2ZU1hbnVmYWN0dXJlcihwcm9kdWN0OiBQcm9kdWN0KTogc3RyaW5nIHtcbiAgICByZXR1cm4gcHJvZHVjdC5tYW51ZmFjdHVyZXIgPyBgIHwgJHtwcm9kdWN0Lm1hbnVmYWN0dXJlcn1gIDogJyc7XG4gIH1cblxuICByZXNvbHZlUm9ib3RzKCk6IE9ic2VydmFibGU8UGFnZVJvYm90c01ldGFbXT4ge1xuICAgIHJldHVybiB0aGlzLmJhc2VQYWdlTWV0YVJlc29sdmVyLnJlc29sdmVSb2JvdHMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyB0aGUgY2Fub25pY2FsIHVybCBmb3IgdGhlIHByb2R1Y3QgcGFnZSB1c2luZyB0aGUgZGVmYXVsdCBjYW5vbmljYWwgdXJsXG4gICAqIGNvbmZpZ3VyYXRpb24uXG4gICAqXG4gICAqIEluIGNhc2Ugb2YgYSB2YXJpYW50IHByb2R1Y3QsIHRoZSBiYXNlUHJvZHVjdCBjb2RlIGlzIHVzZWQgdG8gcmVzb2x2ZSB0aGUgdXJsLiBJdCdzIGltcG9ydGFudFxuICAgKiB0byBrbm93IHRoYXQgdGhpcyBoYXMgYSBmZXcgbGltaXRhdGlvbnM6XG4gICAqIC0gV2UncmUgbm90IGFsd2F5cyBhYmxlIHRvIGdldCB0aGUgc3VwZXIgYmFzZVByb2R1Y3QsIGluIGNhc2Ugb2YgbXVsdGktbGV2ZWwgdmFyaWFudHMuXG4gICAqICAgT0NDIG9ubHkgZXhwb3NlcyB0aGUgZGlyZWN0IGJhc2VQcm9kdWN0LCB3aGljaCBtaWdodCBzdGlsbCBub3QgcmVzb2x2ZSBpbiB0aGUgY29ycmVjdFxuICAgKiAgIGNhbm9uaWNhbCBVUkwuIFRoaXMgaXMgYnVzaW5lc3MgZHJpdmVuIGFuZCBzdWJqZWN0IHRvIGNoYW5nZSBpbiBhIGN1c3RvbWl6YXRpb24uXG4gICAqIC0gVGhlIHVybCByZXNvbHZlZCBmb3IgdGhlIHZhcmlhbnQgZG9lc24ndCBjb250YWluIGFueSBjb250ZW50IG90aGVyIHRoZW4gdGhlIHByb2R1Y3QgY29kZS5cbiAgICogICBUaGlzIG1lYW5zIHRoYXQgd2UgZG8gbm90IHByb3ZpZGUgYW55IHByb2R1Y3QgZGF0YSB0byByZXNvbHZlIHByZXR0eSBVUkxzIChmb3IgZXhhbXBsZVxuICAgKiAgIHRoZSBwcm9kdWN0IHRpdGxlKS5cbiAgICovXG4gIHJlc29sdmVDYW5vbmljYWxVcmwoKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5wcm9kdWN0JC5waXBlKFxuICAgICAgc3dpdGNoTWFwKChwcm9kdWN0KSA9PiB0aGlzLmZpbmRCYXNlUHJvZHVjdChwcm9kdWN0KSksXG4gICAgICBtYXAoKHByb2R1Y3QpID0+IHtcbiAgICAgICAgY29uc3QgdXJsID0gdGhpcy5yb3V0aW5nU2VydmljZS5nZXRGdWxsVXJsKHtcbiAgICAgICAgICBjeFJvdXRlOiAncHJvZHVjdCcsXG4gICAgICAgICAgcGFyYW1zOiBwcm9kdWN0LFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFnZUxpbmtTZXJ2aWNlLmdldENhbm9uaWNhbFVybCh7fSwgdXJsKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcyB0aGUgYmFzZSBwcm9kdWN0IHdoZW5ldmVyIHRoZSBnaXZlbiBwcm9kdWN0IGlzIGEgdmFyaWFudCBwcm9kdWN0LlxuICAgKlxuICAgKiBTaW5jZSBwcm9kdWN0IHZhcmlhbnRzIGNhbiBiZSBtdWx0aS1sYXllcmVkLCB3ZSByZWN1cnNpdmVseSB0cnkgdG8gZmluZCB0aGUgYmFzZSBwcm9kdWN0XG4gICAqIHRoaXMgbWlnaHQgYmUgdG9vIG9waW5pb25hdGVkIGZvciB5b3VyIGJ1c2luZXNzIHRob3VnaC5cbiAgICovXG4gIHByb3RlY3RlZCBmaW5kQmFzZVByb2R1Y3QocHJvZHVjdDogUHJvZHVjdCk6IE9ic2VydmFibGU8UHJvZHVjdD4ge1xuICAgIGlmIChwcm9kdWN0Py5iYXNlUHJvZHVjdCkge1xuICAgICAgcmV0dXJuIHRoaXMucHJvZHVjdFNlcnZpY2VcbiAgICAgICAgLmdldChwcm9kdWN0LmJhc2VQcm9kdWN0LCBQcm9kdWN0U2NvcGUuTElTVClcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgZmlsdGVyKChwcm9kdWN0KSA9PiBCb29sZWFuKHByb2R1Y3QpKSxcbiAgICAgICAgICBzd2l0Y2hNYXAoKGJhc2VQcm9kdWN0KSA9PiB0aGlzLmZpbmRCYXNlUHJvZHVjdChiYXNlUHJvZHVjdCkpXG4gICAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBvZihwcm9kdWN0KTtcbiAgfVxufVxuIl19