@spartacus/core
Version:
Spartacus - the core framework
137 lines • 21.4 kB
JavaScript
import { Injectable } from '@angular/core';
import { combineLatest, of } from 'rxjs';
import { map, shareReplay, switchMap } from 'rxjs/operators';
import { DefaultRoutePageMetaResolver } from './default-route-page-meta.resolver';
import * as i0 from "@angular/core";
import * as i1 from "../../../routing/services/activated-routes.service";
/**
* Resolves the page meta based on the Angular Activated Routes
*/
export class RoutingPageMetaResolver {
constructor(activatedRoutesService, injector) {
this.activatedRoutesService = activatedRoutesService;
this.injector = injector;
/**
* Array of activated routes, excluding the special Angular `root` route.
*/
this.routes$ = this.activatedRoutesService.routes$.pipe(
// drop the first route - the special `root` route:
map((routes) => (routes = routes.slice(1, routes.length))));
/**
* Array of activated routes together with precalculated extras:
*
* - route's page meta resolver
* - route's absolute string URL
*
* In case when there is no page meta resolver configured for a specific route,
* it inherits its parent's resolver.
*
* When there is no page meta resolver configured for the highest parent in the hierarchy,
* it uses the `DefaultRoutePageMetaResolver`.
*/
this.routesWithExtras$ = this.routes$.pipe(map((routes) => routes.reduce((results, route) => {
var _a;
const parent = results.length
? results[results.length - 1]
: {
route: null,
resolver: this.injector.get(DefaultRoutePageMetaResolver),
url: '',
};
const resolver = (_a = this.getResolver(route)) !== null && _a !== void 0 ? _a : parent.resolver; // fallback to parent's resolver
const urlPart = this.getUrlPart(route);
const url = parent.url + (urlPart ? `/${urlPart}` : ''); // don't add slash for a route with path '', to avoid double slash ...//...
return results.concat({ route, resolver, url });
}, [])), shareReplay({ bufferSize: 1, refCount: true }));
}
/**
* Array of breadcrumbs defined for all the activated routes (from the root route to the leaf route).
* It emits on every completed routing navigation.
*/
resolveBreadcrumbs(options) {
return this.routesWithExtras$.pipe(map((routesWithExtras) => (options === null || options === void 0 ? void 0 : options.includeCurrentRoute)
? routesWithExtras
: this.trimCurrentRoute(routesWithExtras)), switchMap((routesWithExtras) => routesWithExtras.length
? combineLatest(routesWithExtras.map((routeWithExtras) => this.resolveRouteBreadcrumb(routeWithExtras)))
: of([])), map((breadcrumbArrays) => breadcrumbArrays.flat()));
}
/**
* Returns the instance of the RoutePageMetaResolver configured for the given activated route.
* Returns null in case there the resolver can't be injected or is undefined.
*
* @param route route to resolve
*/
getResolver(route) {
const pageMetaConfig = this.getPageMetaConfig(route);
if (typeof pageMetaConfig !== 'string' && (pageMetaConfig === null || pageMetaConfig === void 0 ? void 0 : pageMetaConfig.resolver)) {
return this.injector.get(pageMetaConfig.resolver, null);
}
return null;
}
/**
* Resolvers breadcrumb for a specific route
*/
resolveRouteBreadcrumb({ route, resolver, url, }) {
const breadcrumbResolver = resolver;
if (typeof breadcrumbResolver.resolveBreadcrumbs === 'function') {
return breadcrumbResolver.resolveBreadcrumbs({
route,
url,
pageMetaConfig: this.getPageMetaConfig(route),
});
}
return of([]);
}
/**
* By default in breadcrumbs list we don't want to show a link to the current page, so this function
* trims the last breadcrumb (the breadcrumb of the current route).
*
* This function also handles special case when the current route has a configured empty path ('' route).
* The '' routes are often a _technical_ routes to organize other routes, assign common guards for its children, etc.
* It shouldn't happen that '' route has a defined breadcrumb config.
*
* In that case, we trim not only the last route ('' route), but also its parent route with non-empty path
* (which likely defines the breadcrumb config).
*/
trimCurrentRoute(routesWithExtras) {
// If the last route is '', we trim:
// - the '' route
// - all parent '' routes (until we meet route with non-empty path)
var _a, _b;
let i = routesWithExtras.length - 1;
while (((_b = (_a = routesWithExtras[i]) === null || _a === void 0 ? void 0 : _a.route) === null || _b === void 0 ? void 0 : _b.url.length) === 0 && i >= 0) {
i--;
}
// Finally we trim the last route (the one with non-empty path)
return routesWithExtras.slice(0, i);
}
/**
* Returns the URL path for the given activated route in a string format.
* (ActivatedRouteSnapshot#url contains an array of `UrlSegment`s, not a string)
*/
getUrlPart(route) {
return route.url.map((urlSegment) => urlSegment.path).join('/');
}
/**
* Returns the breadcrumb config placed in the route's `data` configuration.
*/
getPageMetaConfig(route) {
var _a, _b;
// Note: we use `route.routeConfig.data` (not `route.data`) to save us from
// an edge case bug. In Angular, by design the `data` of ActivatedRoute is inherited
// from the parent route, if only the child has an empty path ''.
// But in any case we don't want the page meta configs to be inherited, so we
// read data from the original `routeConfig` which is static.
//
// Note: we may inherit the parent's page meta resolver in case we don't define it,
// but we don't want to inherit parent's page meta config!
return (_b = (_a = route === null || route === void 0 ? void 0 : route.routeConfig) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.cxPageMeta;
}
}
RoutingPageMetaResolver.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: RoutingPageMetaResolver, deps: [{ token: i1.ActivatedRoutesService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
RoutingPageMetaResolver.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: RoutingPageMetaResolver, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: RoutingPageMetaResolver, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: function () { return [{ type: i1.ActivatedRoutesService }, { type: i0.Injector }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGluZy1wYWdlLW1ldGEucmVzb2x2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jb3JlL3NyYy9jbXMvcGFnZS9yb3V0aW5nL3JvdXRpbmctcGFnZS1tZXRhLnJlc29sdmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQVksTUFBTSxlQUFlLENBQUM7QUFFckQsT0FBTyxFQUFFLGFBQWEsRUFBYyxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDckQsT0FBTyxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHN0QsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sb0NBQW9DLENBQUM7OztBQXFCbEY7O0dBRUc7QUFFSCxNQUFNLE9BQU8sdUJBQXVCO0lBQ2xDLFlBQ1ksc0JBQThDLEVBQzlDLFFBQWtCO1FBRGxCLDJCQUFzQixHQUF0QixzQkFBc0IsQ0FBd0I7UUFDOUMsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUc5Qjs7V0FFRztRQUNnQixZQUFPLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxJQUFJO1FBQ25FLG1EQUFtRDtRQUNuRCxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQzNELENBQUM7UUFFRjs7Ozs7Ozs7Ozs7V0FXRztRQUNnQixzQkFBaUIsR0FDbEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQ2YsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FDYixNQUFNLENBQUMsTUFBTSxDQUFvQixDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRTs7WUFDbEQsTUFBTSxNQUFNLEdBQUcsT0FB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Y3RhYmxlLCBJbmplY3RvciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBjb21iaW5lTGF0ZXN0LCBPYnNlcnZhYmxlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCBzaGFyZVJlcGxheSwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGVzU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3JvdXRpbmcvc2VydmljZXMvYWN0aXZhdGVkLXJvdXRlcy5zZXJ2aWNlJztcbmltcG9ydCB7IEJyZWFkY3J1bWJNZXRhIH0gZnJvbSAnLi4vLi4vbW9kZWwvcGFnZS5tb2RlbCc7XG5pbXBvcnQgeyBEZWZhdWx0Um91dGVQYWdlTWV0YVJlc29sdmVyIH0gZnJvbSAnLi9kZWZhdWx0LXJvdXRlLXBhZ2UtbWV0YS5yZXNvbHZlcic7XG5pbXBvcnQge1xuICBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90V2l0aFBhZ2VNZXRhLFxuICBSb3V0ZUJyZWFkY3J1bWJSZXNvbHZlcixcbiAgUm91dGVQYWdlTWV0YUNvbmZpZyxcbn0gZnJvbSAnLi9yb3V0ZS1wYWdlLW1ldGEubW9kZWwnO1xuXG4vLyBQUklWQVRFXG5leHBvcnQgaW50ZXJmYWNlIFJvdXRlV2l0aEV4dHJhcyB7XG4gIHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90V2l0aFBhZ2VNZXRhO1xuICByZXNvbHZlcjogYW55O1xuICB1cmw6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSb3V0aW5nUmVzb2x2ZUJyZWFkY3J1bWJzT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBJbmNsdWRlcyB0aGUgY3VycmVudCByb3V0ZSBpbiB0aGUgYnJlYWRjcnVtYnMuXG4gICAqL1xuICBpbmNsdWRlQ3VycmVudFJvdXRlPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBSZXNvbHZlcyB0aGUgcGFnZSBtZXRhIGJhc2VkIG9uIHRoZSBBbmd1bGFyIEFjdGl2YXRlZCBSb3V0ZXNcbiAqL1xuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBSb3V0aW5nUGFnZU1ldGFSZXNvbHZlciB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBhY3RpdmF0ZWRSb3V0ZXNTZXJ2aWNlOiBBY3RpdmF0ZWRSb3V0ZXNTZXJ2aWNlLFxuICAgIHByb3RlY3RlZCBpbmplY3RvcjogSW5qZWN0b3JcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBBcnJheSBvZiBhY3RpdmF0ZWQgcm91dGVzLCBleGNsdWRpbmcgdGhlIHNwZWNpYWwgQW5ndWxhciBgcm9vdGAgcm91dGUuXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcm91dGVzJCA9IHRoaXMuYWN0aXZhdGVkUm91dGVzU2VydmljZS5yb3V0ZXMkLnBpcGUoXG4gICAgLy8gZHJvcCB0aGUgZmlyc3Qgcm91dGUgLSB0aGUgc3BlY2lhbCBgcm9vdGAgcm91dGU6XG4gICAgbWFwKChyb3V0ZXMpID0+IChyb3V0ZXMgPSByb3V0ZXMuc2xpY2UoMSwgcm91dGVzLmxlbmd0aCkpKVxuICApO1xuXG4gIC8qKlxuICAgKiBBcnJheSBvZiBhY3RpdmF0ZWQgcm91dGVzIHRvZ2V0aGVyIHdpdGggcHJlY2FsY3VsYXRlZCBleHRyYXM6XG4gICAqXG4gICAqIC0gcm91dGUncyBwYWdlIG1ldGEgcmVzb2x2ZXJcbiAgICogLSByb3V0ZSdzIGFic29sdXRlIHN0cmluZyBVUkxcbiAgICpcbiAgICogSW4gY2FzZSB3aGVuIHRoZXJlIGlzIG5vIHBhZ2UgbWV0YSByZXNvbHZlciBjb25maWd1cmVkIGZvciBhIHNwZWNpZmljIHJvdXRlLFxuICAgKiBpdCBpbmhlcml0cyBpdHMgcGFyZW50J3MgcmVzb2x2ZXIuXG4gICAqXG4gICAqIFdoZW4gdGhlcmUgaXMgbm8gcGFnZSBtZXRhIHJlc29sdmVyIGNvbmZpZ3VyZWQgZm9yIHRoZSBoaWdoZXN0IHBhcmVudCBpbiB0aGUgaGllcmFyY2h5LFxuICAgKiBpdCB1c2VzIHRoZSBgRGVmYXVsdFJvdXRlUGFnZU1ldGFSZXNvbHZlcmAuXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcm91dGVzV2l0aEV4dHJhcyQ6IE9ic2VydmFibGU8Um91dGVXaXRoRXh0cmFzW10+ID1cbiAgICB0aGlzLnJvdXRlcyQucGlwZShcbiAgICAgIG1hcCgocm91dGVzKSA9PlxuICAgICAgICByb3V0ZXMucmVkdWNlPFJvdXRlV2l0aEV4dHJhc1tdPigocmVzdWx0cywgcm91dGUpID0+IHtcbiAgICAgICAgICBjb25zdCBwYXJlbnQgPSByZXN1bHRzLmxlbmd0aFxuICAgICAgICAgICAgPyByZXN1bHRzW3Jlc3VsdHMubGVuZ3RoIC0gMV1cbiAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgIHJvdXRlOiBudWxsLFxuICAgICAgICAgICAgICAgIHJlc29sdmVyOiB0aGlzLmluamVjdG9yLmdldChEZWZhdWx0Um91dGVQYWdlTWV0YVJlc29sdmVyKSxcbiAgICAgICAgICAgICAgICB1cmw6ICcnLFxuICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgY29uc3QgcmVzb2x2ZXIgPSB0aGlzLmdldFJlc29sdmVyKHJvdXRlKSA/PyBwYXJlbnQucmVzb2x2ZXI7IC8vIGZhbGxiYWNrIHRvIHBhcmVudCdzIHJlc29sdmVyXG5cbiAgICAgICAgICBjb25zdCB1cmxQYXJ0ID0gdGhpcy5nZXRVcmxQYXJ0KHJvdXRlKTtcbiAgICAgICAgICBjb25zdCB1cmwgPSBwYXJlbnQudXJsICsgKHVybFBhcnQgPyBgLyR7dXJsUGFydH1gIDogJycpOyAvLyBkb24ndCBhZGQgc2xhc2ggZm9yIGEgcm91dGUgd2l0aCBwYXRoICcnLCB0byBhdm9pZCBkb3VibGUgc2xhc2ggLi4uLy8uLi5cblxuICAgICAgICAgIHJldHVybiByZXN1bHRzLmNvbmNhdCh7IHJvdXRlLCByZXNvbHZlciwgdXJsIH0pO1xuICAgICAgICB9LCBbXSlcbiAgICAgICksXG4gICAgICBzaGFyZVJlcGxheSh7IGJ1ZmZlclNpemU6IDEsIHJlZkNvdW50OiB0cnVlIH0pXG4gICAgKTtcblxuICAvKipcbiAgICogQXJyYXkgb2YgYnJlYWRjcnVtYnMgZGVmaW5lZCBmb3IgYWxsIHRoZSBhY3RpdmF0ZWQgcm91dGVzIChmcm9tIHRoZSByb290IHJvdXRlIHRvIHRoZSBsZWFmIHJvdXRlKS5cbiAgICogSXQgZW1pdHMgb24gZXZlcnkgY29tcGxldGVkIHJvdXRpbmcgbmF2aWdhdGlvbi5cbiAgICovXG4gIHJlc29sdmVCcmVhZGNydW1icyhcbiAgICBvcHRpb25zPzogUm91dGluZ1Jlc29sdmVCcmVhZGNydW1ic09wdGlvbnNcbiAgKTogT2JzZXJ2YWJsZTxCcmVhZGNydW1iTWV0YVtdPiB7XG4gICAgcmV0dXJuIHRoaXMucm91dGVzV2l0aEV4dHJhcyQucGlwZShcbiAgICAgIG1hcCgocm91dGVzV2l0aEV4dHJhcykgPT5cbiAgICAgICAgb3B0aW9ucz8uaW5jbHVkZUN1cnJlbnRSb3V0ZVxuICAgICAgICAgID8gcm91dGVzV2l0aEV4dHJhc1xuICAgICAgICAgIDogdGhpcy50cmltQ3VycmVudFJvdXRlKHJvdXRlc1dpdGhFeHRyYXMpXG4gICAgICApLFxuICAgICAgc3dpdGNoTWFwKChyb3V0ZXNXaXRoRXh0cmFzKSA9PlxuICAgICAgICByb3V0ZXNXaXRoRXh0cmFzLmxlbmd0aFxuICAgICAgICAgID8gY29tYmluZUxhdGVzdChcbiAgICAgICAgICAgICAgcm91dGVzV2l0aEV4dHJhcy5tYXAoKHJvdXRlV2l0aEV4dHJhcykgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnJlc29sdmVSb3V0ZUJyZWFkY3J1bWIocm91dGVXaXRoRXh0cmFzKVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgICAgOiBvZihbXSlcbiAgICAgICksXG4gICAgICBtYXAoKGJyZWFkY3J1bWJBcnJheXMpID0+IGJyZWFkY3J1bWJBcnJheXMuZmxhdCgpKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgaW5zdGFuY2Ugb2YgdGhlIFJvdXRlUGFnZU1ldGFSZXNvbHZlciBjb25maWd1cmVkIGZvciB0aGUgZ2l2ZW4gYWN0aXZhdGVkIHJvdXRlLlxuICAgKiBSZXR1cm5zIG51bGwgaW4gY2FzZSB0aGVyZSB0aGUgcmVzb2x2ZXIgY2FuJ3QgYmUgaW5qZWN0ZWQgb3IgaXMgdW5kZWZpbmVkLlxuICAgKlxuICAgKiBAcGFyYW0gcm91dGUgcm91dGUgdG8gcmVzb2x2ZVxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFJlc29sdmVyKHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90V2l0aFBhZ2VNZXRhKTogYW55IHtcbiAgICBjb25zdCBwYWdlTWV0YUNvbmZpZyA9IHRoaXMuZ2V0UGFnZU1ldGFDb25maWcocm91dGUpO1xuXG4gICAgaWYgKHR5cGVvZiBwYWdlTWV0YUNvbmZpZyAhPT0gJ3N0cmluZycgJiYgcGFnZU1ldGFDb25maWc/LnJlc29sdmVyKSB7XG4gICAgICByZXR1cm4gdGhpcy5pbmplY3Rvci5nZXQocGFnZU1ldGFDb25maWcucmVzb2x2ZXIsIG51bGwpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlcnMgYnJlYWRjcnVtYiBmb3IgYSBzcGVjaWZpYyByb3V0ZVxuICAgKi9cbiAgcHJvdGVjdGVkIHJlc29sdmVSb3V0ZUJyZWFkY3J1bWIoe1xuICAgIHJvdXRlLFxuICAgIHJlc29sdmVyLFxuICAgIHVybCxcbiAgfTogUm91dGVXaXRoRXh0cmFzKTogT2JzZXJ2YWJsZTxCcmVhZGNydW1iTWV0YVtdPiB7XG4gICAgY29uc3QgYnJlYWRjcnVtYlJlc29sdmVyID0gcmVzb2x2ZXIgYXMgUm91dGVCcmVhZGNydW1iUmVzb2x2ZXI7XG5cbiAgICBpZiAodHlwZW9mIGJyZWFkY3J1bWJSZXNvbHZlci5yZXNvbHZlQnJlYWRjcnVtYnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHJldHVybiBicmVhZGNydW1iUmVzb2x2ZXIucmVzb2x2ZUJyZWFkY3J1bWJzKHtcbiAgICAgICAgcm91dGUsXG4gICAgICAgIHVybCxcbiAgICAgICAgcGFnZU1ldGFDb25maWc6IHRoaXMuZ2V0UGFnZU1ldGFDb25maWcocm91dGUpLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBvZihbXSk7XG4gIH1cblxuICAvKipcbiAgICogQnkgZGVmYXVsdCBpbiBicmVhZGNydW1icyBsaXN0IHdlIGRvbid0IHdhbnQgdG8gc2hvdyBhIGxpbmsgdG8gdGhlIGN1cnJlbnQgcGFnZSwgc28gdGhpcyBmdW5jdGlvblxuICAgKiB0cmltcyB0aGUgbGFzdCBicmVhZGNydW1iICh0aGUgYnJlYWRjcnVtYiBvZiB0aGUgY3VycmVudCByb3V0ZSkuXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gYWxzbyBoYW5kbGVzIHNwZWNpYWwgY2FzZSB3aGVuIHRoZSBjdXJyZW50IHJvdXRlIGhhcyBhIGNvbmZpZ3VyZWQgZW1wdHkgcGF0aCAoJycgcm91dGUpLlxuICAgKiBUaGUgJycgcm91dGVzIGFyZSBvZnRlbiBhIF90ZWNobmljYWxfIHJvdXRlcyB0byBvcmdhbml6ZSBvdGhlciByb3V0ZXMsIGFzc2lnbiBjb21tb24gZ3VhcmRzIGZvciBpdHMgY2hpbGRyZW4sIGV0Yy5cbiAgICogSXQgc2hvdWxkbid0IGhhcHBlbiB0aGF0ICcnIHJvdXRlIGhhcyBhIGRlZmluZWQgYnJlYWRjcnVtYiBjb25maWcuXG4gICAqXG4gICAqIEluIHRoYXQgY2FzZSwgd2UgdHJpbSBub3Qgb25seSB0aGUgbGFzdCByb3V0ZSAoJycgcm91dGUpLCBidXQgYWxzbyBpdHMgcGFyZW50IHJvdXRlIHdpdGggbm9uLWVtcHR5IHBhdGhcbiAgICogKHdoaWNoIGxpa2VseSBkZWZpbmVzIHRoZSBicmVhZGNydW1iIGNvbmZpZykuXG4gICAqL1xuICBwcml2YXRlIHRyaW1DdXJyZW50Um91dGUoXG4gICAgcm91dGVzV2l0aEV4dHJhczogUm91dGVXaXRoRXh0cmFzW11cbiAgKTogUm91dGVXaXRoRXh0cmFzW10ge1xuICAgIC8vIElmIHRoZSBsYXN0IHJvdXRlIGlzICcnLCB3ZSB0cmltOlxuICAgIC8vIC0gdGhlICcnIHJvdXRlXG4gICAgLy8gLSBhbGwgcGFyZW50ICcnIHJvdXRlcyAodW50aWwgd2UgbWVldCByb3V0ZSB3aXRoIG5vbi1lbXB0eSBwYXRoKVxuXG4gICAgbGV0IGkgPSByb3V0ZXNXaXRoRXh0cmFzLmxlbmd0aCAtIDE7XG4gICAgd2hpbGUgKHJvdXRlc1dpdGhFeHRyYXNbaV0/LnJvdXRlPy51cmwubGVuZ3RoID09PSAwICYmIGkgPj0gMCkge1xuICAgICAgaS0tO1xuICAgIH1cblxuICAgIC8vIEZpbmFsbHkgd2UgdHJpbSB0aGUgbGFzdCByb3V0ZSAodGhlIG9uZSB3aXRoIG5vbi1lbXB0eSBwYXRoKVxuICAgIHJldHVybiByb3V0ZXNXaXRoRXh0cmFzLnNsaWNlKDAsIGkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIFVSTCBwYXRoIGZvciB0aGUgZ2l2ZW4gYWN0aXZhdGVkIHJvdXRlIGluIGEgc3RyaW5nIGZvcm1hdC5cbiAgICogKEFjdGl2YXRlZFJvdXRlU25hcHNob3QjdXJsIGNvbnRhaW5zIGFuIGFycmF5IG9mIGBVcmxTZWdtZW50YHMsIG5vdCBhIHN0cmluZylcbiAgICovXG4gIHByaXZhdGUgZ2V0VXJsUGFydChyb3V0ZTogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHJvdXRlLnVybC5tYXAoKHVybFNlZ21lbnQpID0+IHVybFNlZ21lbnQucGF0aCkuam9pbignLycpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGJyZWFkY3J1bWIgY29uZmlnIHBsYWNlZCBpbiB0aGUgcm91dGUncyBgZGF0YWAgY29uZmlndXJhdGlvbi5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRQYWdlTWV0YUNvbmZpZyhcbiAgICByb3V0ZTogQWN0aXZhdGVkUm91dGVTbmFwc2hvdFdpdGhQYWdlTWV0YVxuICApOiBSb3V0ZVBhZ2VNZXRhQ29uZmlnIHtcbiAgICAvLyBOb3RlOiB3ZSB1c2UgYHJvdXRlLnJvdXRlQ29uZmlnLmRhdGFgIChub3QgYHJvdXRlLmRhdGFgKSB0byBzYXZlIHVzIGZyb21cbiAgICAvLyBhbiBlZGdlIGNhc2UgYnVnLiBJbiBBbmd1bGFyLCBieSBkZXNpZ24gdGhlIGBkYXRhYCBvZiBBY3RpdmF0ZWRSb3V0ZSBpcyBpbmhlcml0ZWRcbiAgICAvLyBmcm9tIHRoZSBwYXJlbnQgcm91dGUsIGlmIG9ubHkgdGhlIGNoaWxkIGhhcyBhbiBlbXB0eSBwYXRoICcnLlxuICAgIC8vIEJ1dCBpbiBhbnkgY2FzZSB3ZSBkb24ndCB3YW50IHRoZSBwYWdlIG1ldGEgY29uZmlncyB0byBiZSBpbmhlcml0ZWQsIHNvIHdlXG4gICAgLy8gcmVhZCBkYXRhIGZyb20gdGhlIG9yaWdpbmFsIGByb3V0ZUNvbmZpZ2Agd2hpY2ggaXMgc3RhdGljLlxuICAgIC8vXG4gICAgLy8gTm90ZTogd2UgbWF5IGluaGVyaXQgdGhlIHBhcmVudCdzIHBhZ2UgbWV0YSByZXNvbHZlciBpbiBjYXNlIHdlIGRvbid0IGRlZmluZSBpdCxcbiAgICAvLyBidXQgd2UgZG9uJ3Qgd2FudCB0byBpbmhlcml0IHBhcmVudCdzIHBhZ2UgbWV0YSBjb25maWchXG4gICAgcmV0dXJuIHJvdXRlPy5yb3V0ZUNvbmZpZz8uZGF0YT8uY3hQYWdlTWV0YTtcbiAgfVxufVxuIl19