@spartacus/core
Version:
Spartacus - the core framework
152 lines • 22.3 kB
JavaScript
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