@angular/router
Version:
Angular - the routing library
399 lines • 93.5 kB
JavaScript
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { Location } from '@angular/common';
import { EnvironmentInjector, inject, Injectable } from '@angular/core';
import { BehaviorSubject, combineLatest, EMPTY, from, of, Subject } from 'rxjs';
import { catchError, defaultIfEmpty, filter, finalize, map, switchMap, take, takeUntil, tap } from 'rxjs/operators';
import { createRouterState } from './create_router_state';
import { INPUT_BINDER } from './directives/router_outlet';
import { BeforeActivateRoutes, GuardsCheckEnd, GuardsCheckStart, IMPERATIVE_NAVIGATION, NavigationCancel, NavigationEnd, NavigationError, NavigationSkipped, NavigationStart, RedirectRequest, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RoutesRecognized } from './events';
import { isNavigationCancelingError, isRedirectingNavigationCancelingError, redirectingNavigationError } from './navigation_canceling_error';
import { activateRoutes } from './operators/activate_routes';
import { checkGuards } from './operators/check_guards';
import { recognize } from './operators/recognize';
import { resolveData } from './operators/resolve_data';
import { switchTap } from './operators/switch_tap';
import { TitleStrategy } from './page_title_strategy';
import { ROUTER_CONFIGURATION } from './router_config';
import { RouterConfigLoader } from './router_config_loader';
import { ChildrenOutletContexts } from './router_outlet_context';
import { createEmptyState } from './router_state';
import { UrlHandlingStrategy } from './url_handling_strategy';
import { isUrlTree, UrlSerializer } from './url_tree';
import { getAllRouteGuards } from './utils/preactivation';
import { CREATE_VIEW_TRANSITION } from './utils/view_transition';
import * as i0 from "@angular/core";
export class NavigationTransitions {
get hasRequestedNavigation() {
return this.navigationId !== 0;
}
constructor() {
this.currentNavigation = null;
this.currentTransition = null;
this.lastSuccessfulNavigation = null;
/**
* These events are used to communicate back to the Router about the state of the transition. The
* Router wants to respond to these events in various ways. Because the `NavigationTransition`
* class is not public, this event subject is not publicly exposed.
*/
this.events = new Subject();
/**
* Used to abort the current transition with an error.
*/
this.transitionAbortSubject = new Subject();
this.configLoader = inject(RouterConfigLoader);
this.environmentInjector = inject(EnvironmentInjector);
this.urlSerializer = inject(UrlSerializer);
this.rootContexts = inject(ChildrenOutletContexts);
this.location = inject(Location);
this.inputBindingEnabled = inject(INPUT_BINDER, { optional: true }) !== null;
this.titleStrategy = inject(TitleStrategy);
this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
this.paramsInheritanceStrategy = this.options.paramsInheritanceStrategy || 'emptyOnly';
this.urlHandlingStrategy = inject(UrlHandlingStrategy);
this.createViewTransition = inject(CREATE_VIEW_TRANSITION, { optional: true });
this.navigationId = 0;
/**
* Hook that enables you to pause navigation after the preactivation phase.
* Used by `RouterModule`.
*
* @internal
*/
this.afterPreactivation = () => of(void 0);
/** @internal */
this.rootComponentType = null;
const onLoadStart = (r) => this.events.next(new RouteConfigLoadStart(r));
const onLoadEnd = (r) => this.events.next(new RouteConfigLoadEnd(r));
this.configLoader.onLoadEndListener = onLoadEnd;
this.configLoader.onLoadStartListener = onLoadStart;
}
complete() {
this.transitions?.complete();
}
handleNavigationRequest(request) {
const id = ++this.navigationId;
this.transitions?.next({ ...this.transitions.value, ...request, id });
}
setupNavigations(router, initialUrlTree, initialRouterState) {
this.transitions = new BehaviorSubject({
id: 0,
currentUrlTree: initialUrlTree,
currentRawUrl: initialUrlTree,
extractedUrl: this.urlHandlingStrategy.extract(initialUrlTree),
urlAfterRedirects: this.urlHandlingStrategy.extract(initialUrlTree),
rawUrl: initialUrlTree,
extras: {},
resolve: null,
reject: null,
promise: Promise.resolve(true),
source: IMPERATIVE_NAVIGATION,
restoredState: null,
currentSnapshot: initialRouterState.snapshot,
targetSnapshot: null,
currentRouterState: initialRouterState,
targetRouterState: null,
guards: { canActivateChecks: [], canDeactivateChecks: [] },
guardsResult: null,
});
return this.transitions.pipe(filter(t => t.id !== 0),
// Extract URL
map(t => ({ ...t, extractedUrl: this.urlHandlingStrategy.extract(t.rawUrl) })),
// Using switchMap so we cancel executing navigations when a new one comes in
switchMap(overallTransitionState => {
this.currentTransition = overallTransitionState;
let completed = false;
let errored = false;
return of(overallTransitionState)
.pipe(
// Store the Navigation object
tap(t => {
this.currentNavigation = {
id: t.id,
initialUrl: t.rawUrl,
extractedUrl: t.extractedUrl,
trigger: t.source,
extras: t.extras,
previousNavigation: !this.lastSuccessfulNavigation ? null : {
...this.lastSuccessfulNavigation,
previousNavigation: null,
},
};
}), switchMap(t => {
const urlTransition = !router.navigated ||
this.isUpdatingInternalState() || this.isUpdatedBrowserUrl();
const onSameUrlNavigation = t.extras.onSameUrlNavigation ?? router.onSameUrlNavigation;
if (!urlTransition && onSameUrlNavigation !== 'reload') {
const reason = (typeof ngDevMode === 'undefined' || ngDevMode) ?
`Navigation to ${t.rawUrl} was ignored because it is the same as the current Router URL.` :
'';
this.events.next(new NavigationSkipped(t.id, this.urlSerializer.serialize(t.rawUrl), reason, 0 /* NavigationSkippedCode.IgnoredSameUrlNavigation */));
t.resolve(null);
return EMPTY;
}
if (this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl)) {
return of(t).pipe(
// Fire NavigationStart event
switchMap(t => {
const transition = this.transitions?.getValue();
this.events.next(new NavigationStart(t.id, this.urlSerializer.serialize(t.extractedUrl), t.source, t.restoredState));
if (transition !== this.transitions?.getValue()) {
return EMPTY;
}
// This delay is required to match old behavior that forced
// navigation to always be async
return Promise.resolve(t);
}),
// Recognize
recognize(this.environmentInjector, this.configLoader, this.rootComponentType, router.config, this.urlSerializer, this.paramsInheritanceStrategy),
// Update URL if in `eager` update mode
tap(t => {
overallTransitionState.targetSnapshot = t.targetSnapshot;
overallTransitionState.urlAfterRedirects = t.urlAfterRedirects;
this.currentNavigation = {
...this.currentNavigation,
finalUrl: t.urlAfterRedirects
};
// Fire RoutesRecognized
const routesRecognized = new RoutesRecognized(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
this.events.next(routesRecognized);
}));
}
else if (urlTransition &&
this.urlHandlingStrategy.shouldProcessUrl(t.currentRawUrl)) {
/* When the current URL shouldn't be processed, but the previous one
* was, we handle this "error condition" by navigating to the
* previously successful URL, but leaving the URL intact.*/
const { id, extractedUrl, source, restoredState, extras } = t;
const navStart = new NavigationStart(id, this.urlSerializer.serialize(extractedUrl), source, restoredState);
this.events.next(navStart);
const targetSnapshot = createEmptyState(extractedUrl, this.rootComponentType).snapshot;
this.currentTransition = overallTransitionState = {
...t,
targetSnapshot,
urlAfterRedirects: extractedUrl,
extras: { ...extras, skipLocationChange: false, replaceUrl: false },
};
this.currentNavigation.finalUrl = extractedUrl;
return of(overallTransitionState);
}
else {
/* When neither the current or previous URL can be processed, do
* nothing other than update router's internal reference to the
* current "settled" URL. This way the next navigation will be coming
* from the current URL in the browser.
*/
const reason = (typeof ngDevMode === 'undefined' || ngDevMode) ?
`Navigation was ignored because the UrlHandlingStrategy` +
` indicated neither the current URL ${t.currentRawUrl} nor target URL ${t.rawUrl} should be processed.` :
'';
this.events.next(new NavigationSkipped(t.id, this.urlSerializer.serialize(t.extractedUrl), reason, 1 /* NavigationSkippedCode.IgnoredByUrlHandlingStrategy */));
t.resolve(null);
return EMPTY;
}
}),
// --- GUARDS ---
tap(t => {
const guardsStart = new GuardsCheckStart(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
this.events.next(guardsStart);
}), map(t => {
this.currentTransition = overallTransitionState = {
...t,
guards: getAllRouteGuards(t.targetSnapshot, t.currentSnapshot, this.rootContexts)
};
return overallTransitionState;
}), checkGuards(this.environmentInjector, (evt) => this.events.next(evt)), tap(t => {
overallTransitionState.guardsResult = t.guardsResult;
if (isUrlTree(t.guardsResult)) {
throw redirectingNavigationError(this.urlSerializer, t.guardsResult);
}
const guardsEnd = new GuardsCheckEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot, !!t.guardsResult);
this.events.next(guardsEnd);
}), filter(t => {
if (!t.guardsResult) {
this.cancelNavigationTransition(t, '', 3 /* NavigationCancellationCode.GuardRejected */);
return false;
}
return true;
}),
// --- RESOLVE ---
switchTap(t => {
if (t.guards.canActivateChecks.length) {
return of(t).pipe(tap(t => {
const resolveStart = new ResolveStart(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
this.events.next(resolveStart);
}), switchMap(t => {
let dataResolved = false;
return of(t).pipe(resolveData(this.paramsInheritanceStrategy, this.environmentInjector), tap({
next: () => dataResolved = true,
complete: () => {
if (!dataResolved) {
this.cancelNavigationTransition(t, (typeof ngDevMode === 'undefined' || ngDevMode) ?
`At least one route resolver didn't emit any value.` :
'', 2 /* NavigationCancellationCode.NoDataFromResolver */);
}
}
}));
}), tap(t => {
const resolveEnd = new ResolveEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
this.events.next(resolveEnd);
}));
}
return undefined;
}),
// --- LOAD COMPONENTS ---
switchTap((t) => {
const loadComponents = (route) => {
const loaders = [];
if (route.routeConfig?.loadComponent &&
!route.routeConfig._loadedComponent) {
loaders.push(this.configLoader.loadComponent(route.routeConfig)
.pipe(tap(loadedComponent => {
route.component = loadedComponent;
}), map(() => void 0)));
}
for (const child of route.children) {
loaders.push(...loadComponents(child));
}
return loaders;
};
return combineLatest(loadComponents(t.targetSnapshot.root))
.pipe(defaultIfEmpty(), take(1));
}), switchTap(() => this.afterPreactivation()), switchMap(() => {
const { currentSnapshot, targetSnapshot } = overallTransitionState;
const viewTransitionStarted = this.createViewTransition?.(this.environmentInjector, currentSnapshot.root, targetSnapshot.root);
// If view transitions are enabled, block the navigation until the view
// transition callback starts. Otherwise, continue immediately.
return viewTransitionStarted ?
from(viewTransitionStarted).pipe(map(() => overallTransitionState)) :
of(overallTransitionState);
}), map((t) => {
const targetRouterState = createRouterState(router.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
this.currentTransition =
overallTransitionState = { ...t, targetRouterState };
this.currentNavigation.targetRouterState = targetRouterState;
return overallTransitionState;
}), tap(() => {
this.events.next(new BeforeActivateRoutes());
}), activateRoutes(this.rootContexts, router.routeReuseStrategy, (evt) => this.events.next(evt), this.inputBindingEnabled),
// Ensure that if some observable used to drive the transition doesn't
// complete, the navigation still finalizes This should never happen, but
// this is done as a safety measure to avoid surfacing this error (#49567).
take(1), tap({
next: (t) => {
completed = true;
this.lastSuccessfulNavigation = this.currentNavigation;
this.events.next(new NavigationEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects)));
this.titleStrategy?.updateTitle(t.targetRouterState.snapshot);
t.resolve(true);
},
complete: () => {
completed = true;
}
}),
// There used to be a lot more logic happening directly within the
// transition Observable. Some of this logic has been refactored out to
// other places but there may still be errors that happen there. This gives
// us a way to cancel the transition from the outside. This may also be
// required in the future to support something like the abort signal of the
// Navigation API where the navigation gets aborted from outside the
// transition.
takeUntil(this.transitionAbortSubject.pipe(tap(err => {
throw err;
}))), finalize(() => {
/* When the navigation stream finishes either through error or success,
* we set the `completed` or `errored` flag. However, there are some
* situations where we could get here without either of those being set.
* For instance, a redirect during NavigationStart. Therefore, this is a
* catch-all to make sure the NavigationCancel event is fired when a
* navigation gets cancelled but not caught by other means. */
if (!completed && !errored) {
const cancelationReason = (typeof ngDevMode === 'undefined' || ngDevMode) ?
`Navigation ID ${overallTransitionState
.id} is not equal to the current navigation id ${this.navigationId}` :
'';
this.cancelNavigationTransition(overallTransitionState, cancelationReason, 1 /* NavigationCancellationCode.SupersededByNewNavigation */);
}
// Only clear current navigation if it is still set to the one that
// finalized.
if (this.currentNavigation?.id === overallTransitionState.id) {
this.currentNavigation = null;
}
}), catchError((e) => {
errored = true;
/* This error type is issued during Redirect, and is handled as a
* cancellation rather than an error. */
if (isNavigationCancelingError(e)) {
this.events.next(new NavigationCancel(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e.message, e.cancellationCode));
// When redirecting, we need to delay resolving the navigation
// promise and push it to the redirect navigation
if (!isRedirectingNavigationCancelingError(e)) {
overallTransitionState.resolve(false);
}
else {
this.events.next(new RedirectRequest(e.url));
}
/* All other errors should reset to the router's internal URL reference
* to the pre-error state. */
}
else {
this.events.next(new NavigationError(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e, overallTransitionState.targetSnapshot ?? undefined));
try {
overallTransitionState.resolve(router.errorHandler(e));
}
catch (ee) {
overallTransitionState.reject(ee);
}
}
return EMPTY;
}));
// casting because `pipe` returns observable({}) when called with 8+ arguments
}));
}
cancelNavigationTransition(t, reason, code) {
const navCancel = new NavigationCancel(t.id, this.urlSerializer.serialize(t.extractedUrl), reason, code);
this.events.next(navCancel);
t.resolve(false);
}
/**
* @returns Whether we're navigating to somewhere that is not what the Router is
* currently set to.
*/
isUpdatingInternalState() {
// TODO(atscott): The serializer should likely be used instead of
// `UrlTree.toString()`. Custom serializers are often written to handle
// things better than the default one (objects, for example will be
// [Object object] with the custom serializer and be "the same" when they
// aren't).
// (Same for isUpdatedBrowserUrl)
return this.currentTransition?.extractedUrl.toString() !==
this.currentTransition?.currentUrlTree.toString();
}
/**
* @returns Whether we're updating the browser URL to something new (navigation is going
* to somewhere not displayed in the URL bar and we will update the URL
* bar if navigation succeeds).
*/
isUpdatedBrowserUrl() {
// The extracted URL is the part of the URL that this application cares about. `extract` may
// return only part of the browser URL and that part may have not changed even if some other
// portion of the URL did.
const extractedBrowserUrl = this.urlHandlingStrategy.extract(this.urlSerializer.parse(this.location.path(true)));
return extractedBrowserUrl.toString() !== this.currentTransition?.extractedUrl.toString() &&
!this.currentTransition?.extras.skipLocationChange;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.6", ngImport: i0, type: NavigationTransitions, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.6", ngImport: i0, type: NavigationTransitions, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.6", ngImport: i0, type: NavigationTransitions, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}], ctorParameters: () => [] });
export function isBrowserTriggeredNavigation(source) {
return source !== IMPERATIVE_NAVIGATION;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF2aWdhdGlvbl90cmFuc2l0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvcm91dGVyL3NyYy9uYXZpZ2F0aW9uX3RyYW5zaXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFBQyxtQkFBbUIsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFPLE1BQU0sZUFBZSxDQUFDO0FBQzVFLE9BQU8sRUFBQyxlQUFlLEVBQUUsYUFBYSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQWMsRUFBRSxFQUFFLE9BQU8sRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUMxRixPQUFPLEVBQUMsVUFBVSxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUVsSCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUN4RCxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sNEJBQTRCLENBQUM7QUFDeEQsT0FBTyxFQUFDLG9CQUFvQixFQUFTLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRSxxQkFBcUIsRUFBRSxnQkFBZ0IsRUFBOEIsYUFBYSxFQUFFLGVBQWUsRUFBRSxpQkFBaUIsRUFBeUIsZUFBZSxFQUFxQixlQUFlLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxrQkFBa0IsRUFBRSxvQkFBb0IsRUFBRSxnQkFBZ0IsRUFBQyxNQUFNLFVBQVUsQ0FBQztBQUVqWCxPQUFPLEVBQUMsMEJBQTBCLEVBQUUscUNBQXFDLEVBQUUsMEJBQTBCLEVBQUMsTUFBTSw4QkFBOEIsQ0FBQztBQUMzSSxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sNkJBQTZCLENBQUM7QUFD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bGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtMb2NhdGlvbn0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7RW52aXJvbm1lbnRJbmplY3RvciwgaW5qZWN0LCBJbmplY3RhYmxlLCBUeXBlfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7QmVoYXZpb3JTdWJqZWN0LCBjb21iaW5lTGF0ZXN0LCBFTVBUWSwgZnJvbSwgT2JzZXJ2YWJsZSwgb2YsIFN1YmplY3R9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtjYXRjaEVycm9yLCBkZWZhdWx0SWZFbXB0eSwgZmlsdGVyLCBmaW5hbGl6ZSwgbWFwLCBzd2l0Y2hNYXAsIHRha2UsIHRha2VVbnRpbCwgdGFwfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7Y3JlYXRlUm91dGVyU3RhdGV9IGZyb20gJy4vY3JlYXRlX3JvdXRlcl9zdGF0ZSc7XG5pbXBvcnQge0lOUFVUX0JJTkRFUn0gZnJvbSAnLi9kaXJlY3RpdmVzL3JvdXRlcl9vdXRsZXQnO1xuaW1wb3J0IHtCZWZvcmVBY3RpdmF0ZVJvdXRlcywgRXZlbnQsIEd1YXJkc0NoZWNrRW5kLCBHdWFyZHNDaGVja1N0YXJ0LCBJTVBFUkFUSVZFX05BVklHQVRJT04sIE5hdmlnYXRpb25DYW5jZWwsIE5hdmlnYXRpb25DYW5jZWxsYXRpb25Db2RlLCBOYXZpZ2F0aW9uRW5kLCBOYXZpZ2F0aW9uRXJyb3IsIE5hdmlnYXRpb25Ta2lwcGVkLCBOYXZpZ2F0aW9uU2tpcHBlZENvZGUsIE5hdmlnYXRpb25TdGFydCwgTmF2aWdhdGlvblRyaWdnZXIsIFJlZGlyZWN0UmVxdWVzdCwgUmVzb2x2ZUVuZCwgUmVzb2x2ZVN0YXJ0LCBSb3V0ZUNvbmZpZ0xvYWRFbmQsIFJvdXRlQ29uZmlnTG9hZFN0YXJ0LCBSb3V0ZXNSZWNvZ25pemVkfSBmcm9tICcuL2V2ZW50cyc7XG5pbXBvcnQge05hdmlnYXRpb25CZWhhdmlvck9wdGlvbnMsIFF1ZXJ5UGFyYW1zSGFuZGxpbmcsIFJvdXRlLCBSb3V0ZXN9IGZyb20gJy4vbW9kZWxzJztcbmltcG9ydCB7aXNOYXZpZ2F0aW9uQ2FuY2VsaW5nRXJyb3IsIGlzUmVkaXJlY3RpbmdOYXZpZ2F0aW9uQ2FuY2VsaW5nRXJyb3IsIHJlZGlyZWN0aW5nTmF2aWdhdGlvbkVycm9yfSBmcm9tICcuL25hdmlnYXRpb25fY2FuY2VsaW5nX2Vycm9yJztcbmltcG9ydCB7YWN0aXZhdGVSb3V0ZXN9IGZyb20gJy4vb3BlcmF0b3JzL2FjdGl2YXRlX3JvdXRlcyc7XG5pbXBvcnQge2NoZWNrR3VhcmRzfSBmcm9tICcuL29wZXJhdG9ycy9jaGVja19ndWFyZHMnO1xuaW1wb3J0IHtyZWNvZ25pemV9IGZyb20gJy4vb3BlcmF0b3JzL3JlY29nbml6ZSc7XG5pbXBvcnQge3Jlc29sdmVEYXRhfSBmcm9tICcuL29wZXJhdG9ycy9yZXNvbHZlX2RhdGEnO1xuaW1wb3J0IHtzd2l0Y2hUYXB9IGZyb20gJy4vb3BlcmF0b3JzL3N3aXRjaF90YXAnO1xuaW1wb3J0IHtUaXRsZVN0cmF0ZWd5fSBmcm9tICcuL3BhZ2VfdGl0bGVfc3RyYXRlZ3knO1xuaW1wb3J0IHtSb3V0ZVJldXNlU3RyYXRlZ3l9IGZyb20gJy4vcm91dGVfcmV1c2Vfc3RyYXRlZ3knO1xuaW1wb3J0IHtST1VURVJfQ09ORklHVVJBVElPTn0gZnJvbSAnLi9yb3V0ZXJfY29uZmlnJztcbmltcG9ydCB7Um91dGVyQ29uZmlnTG9hZGVyfSBmcm9tICcuL3JvdXRlcl9jb25maWdfbG9hZGVyJztcbmltcG9ydCB7Q2hpbGRyZW5PdXRsZXRDb250ZXh0c30gZnJvbSAnLi9yb3V0ZXJfb3V0bGV0X2NvbnRleHQnO1xuaW1wb3J0IHtBY3RpdmF0ZWRSb3V0ZSwgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCwgY3JlYXRlRW1wdHlTdGF0ZSwgUm91dGVyU3RhdGUsIFJvdXRlclN0YXRlU25hcHNob3R9IGZyb20gJy4vcm91dGVyX3N0YXRlJztcbmltcG9ydCB7UGFyYW1zfSBmcm9tICcuL3NoYXJlZCc7XG5pbXBvcnQge1VybEhhbmRsaW5nU3RyYXRlZ3l9IGZyb20gJy4vdXJsX2hhbmRsaW5nX3N0cmF0ZWd5JztcbmltcG9ydCB7aXNVcmxUcmVlLCBVcmxTZXJpYWxpemVyLCBVcmxUcmVlfSBmcm9tICcuL3VybF90cmVlJztcbmltcG9ydCB7Q2hlY2tzLCBnZXRBbGxSb3V0ZUd1YXJkc30gZnJvbSAnLi91dGlscy9wcmVhY3RpdmF0aW9uJztcbmltcG9ydCB7Q1JFQVRFX1ZJRVdfVFJBTlNJVElPTn0gZnJvbSAnLi91dGlscy92aWV3X3RyYW5zaXRpb24nO1xuXG5cblxuLyoqXG4gKiBAZGVzY3JpcHRpb25cbiAqXG4gKiBPcHRpb25zIHRoYXQgbW9kaWZ5IHRoZSBgUm91dGVyYCBVUkwuXG4gKiBTdXBwbHkgYW4gb2JqZWN0IGNvbnRhaW5pbmcgYW55IG9mIHRoZXNlIHByb3BlcnRpZXMgdG8gYSBgUm91dGVyYCBuYXZpZ2F0aW9uIGZ1bmN0aW9uIHRvXG4gKiBjb250cm9sIGhvdyB0aGUgdGFyZ2V0IFVSTCBzaG91bGQgYmUgY29uc3RydWN0ZWQuXG4gKlxuICogQHNlZSB7QGxpbmsgUm91dGVyI25hdmlnYXRlfVxuICogQHNlZSB7QGxpbmsgUm91dGVyI2NyZWF0ZVVybFRyZWV9XG4gKiBAc2VlIFtSb3V0aW5nIGFuZCBOYXZpZ2F0aW9uIGd1aWRlXShndWlkZS9yb3V0ZXIpXG4gKlxuICogQHB1YmxpY0FwaVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFVybENyZWF0aW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgYSByb290IFVSSSB0byB1c2UgZm9yIHJlbGF0aXZlIG5hdmlnYXRpb24uXG4gICAqXG4gICAqIEZvciBleGFtcGxlLCBjb25zaWRlciB0aGUgZm9sbG93aW5nIHJvdXRlIGNvbmZpZ3VyYXRpb24gd2hlcmUgdGhlIHBhcmVudCByb3V0ZVxuICAgKiBoYXMgdHdvIGNoaWxkcmVuLlxuICAgKlxuICAgKiBgYGBcbiAgICogW3tcbiAgICogICBwYXRoOiAncGFyZW50JyxcbiAgICogICBjb21wb25lbnQ6IFBhcmVudENvbXBvbmVudCxcbiAgICogICBjaGlsZHJlbjogW3tcbiAgICogICAgIHBhdGg6ICdsaXN0JyxcbiAgICogICAgIGNvbXBvbmVudDogTGlzdENvbXBvbmVudFxuICAgKiAgIH0se1xuICAgKiAgICAgcGF0aDogJ2NoaWxkJyxcbiAgICogICAgIGNvbXBvbmVudDogQ2hpbGRDb21wb25lbnRcbiAgICogICB9XVxuICAgKiB9XVxuICAgKiBgYGBcbiAgICpcbiAgICogVGhlIGZvbGxvd2luZyBgZ28oKWAgZnVuY3Rpb24gbmF2aWdhdGVzIHRvIHRoZSBgbGlzdGAgcm91dGUgYnlcbiAgICogaW50ZXJwcmV0aW5nIHRoZSBkZXN0aW5hdGlvbiBVUkkgYXMgcmVsYXRpdmUgdG8gdGhlIGFjdGl2YXRlZCBgY2hpbGRgICByb3V0ZVxuICAgKlxuICAgKiBgYGBcbiAgICogIEBDb21wb25lbnQoey4uLn0pXG4gICAqICBjbGFzcyBDaGlsZENvbXBvbmVudCB7XG4gICAqICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsIHByaXZhdGUgcm91dGU6IEFjdGl2YXRlZFJvdXRlKSB7fVxuICAgKlxuICAgKiAgICBnbygpIHtcbiAgICogICAgICByb3V0ZXIubmF2aWdhdGUoWycuLi9saXN0J10sIHsgcmVsYXRpdmVUbzogdGhpcy5yb3V0ZSB9KTtcbiAgICogICAgfVxuICAgKiAgfVxuICAgKiBgYGBcbiAgICpcbiAgICogQSB2YWx1ZSBvZiBgbnVsbGAgb3IgYHVuZGVmaW5lZGAgaW5kaWNhdGVzIHRoYXQgdGhlIG5hdmlnYXRpb24gY29tbWFuZHMgc2hvdWxkIGJlIGFwcGxpZWRcbiAgICogcmVsYXRpdmUgdG8gdGhlIHJvb3QuXG4gICAqL1xuICByZWxhdGl2ZVRvPzogQWN0aXZhdGVkUm91dGV8bnVsbDtcblxuICAvKipcbiAgICogU2V0cyBxdWVyeSBwYXJhbWV0ZXJzIHRvIHRoZSBVUkwuXG4gICAqXG4gICAqIGBgYFxuICAgKiAvLyBOYXZpZ2F0ZSB0byAvcmVzdWx0cz9wYWdlPTFcbiAgICogcm91dGVyLm5hdmlnYXRlKFsnL3Jlc3VsdHMnXSwgeyBxdWVyeVBhcmFtczogeyBwYWdlOiAxIH0gfSk7XG4gICAqIGBgYFxuICAgKi9cbiAgcXVlcnlQYXJhbXM/OiBQYXJhbXN8bnVsbDtcblxuICAvKipcbiAgICogU2V0cyB0aGUgaGFzaCBmcmFnbWVudCBmb3IgdGhlIFVSTC5cbiAgICpcbiAgICogYGBgXG4gICAqIC8vIE5hdmlnYXRlIHRvIC9yZXN1bHRzI3RvcFxuICAgKiByb3V0ZXIubmF2aWdhdGUoWycvcmVzdWx0cyddLCB7IGZyYWdtZW50OiAndG9wJyB9KTtcbiAgICogYGBgXG4gICAqL1xuICBmcmFnbWVudD86IHN0cmluZztcblxuICAvKipcbiAgICogSG93IHRvIGhhbmRsZSBxdWVyeSBwYXJhbWV0ZXJzIGluIHRoZSByb3V0ZXIgbGluayBmb3IgdGhlIG5leHQgbmF2aWdhdGlvbi5cbiAgICogT25lIG9mOlxuICAgKiAqIGBwcmVzZXJ2ZWAgOiBQcmVzZXJ2ZSBjdXJyZW50IHBhcmFtZXRlcnMuXG4gICAqICogYG1lcmdlYCA6IE1lcmdlIG5ldyB3aXRoIGN1cnJlbnQgcGFyYW1ldGVycy5cbiAgICpcbiAgICogVGhlIFwicHJlc2VydmVcIiBvcHRpb24gZGlzY2FyZHMgYW55IG5ldyBxdWVyeSBwYXJhbXM6XG4gICAqIGBgYFxuICAgKiAvLyBmcm9tIC92aWV3MT9wYWdlPTEgdG8vdmlldzI/cGFnZT0xXG4gICAqIHJvdXRlci5uYXZpZ2F0ZShbJy92aWV3MiddLCB7IHF1ZXJ5UGFyYW1zOiB7IHBhZ2U6IDIgfSwgIHF1ZXJ5UGFyYW1zSGFuZGxpbmc6IFwicHJlc2VydmVcIlxuICAgKiB9KTtcbiAgICogYGBgXG4gICAqIFRoZSBcIm1lcmdlXCIgb3B0aW9uIGFwcGVuZHMgbmV3IHF1ZXJ5IHBhcmFtcyB0byB0aGUgcGFyYW1zIGZyb20gdGhlIGN1cnJlbnQgVVJMOlxuICAgKiBgYGBcbiAgICogLy8gZnJvbSAvdmlldzE/cGFnZT0xIHRvL3ZpZXcyP3BhZ2U9MSZvdGhlcktleT0yXG4gICAqIHJvdXRlci5uYXZpZ2F0ZShbJy92aWV3MiddLCB7IHF1ZXJ5UGFyYW1zOiB7IG90aGVyS2V5OiAyIH0sICBxdWVyeVBhcmFtc0hhbmRsaW5nOiBcIm1lcmdlXCJcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKiBJbiBjYXNlIG9mIGEga2V5IGNvbGxpc2lvbiBiZXR3ZWVuIGN1cnJlbnQgcGFyYW1ldGVycyBhbmQgdGhvc2UgaW4gdGhlIGBxdWVyeVBhcmFtc2Agb2JqZWN0LFxuICAgKiB0aGUgbmV3IHZhbHVlIGlzIHVzZWQuXG4gICAqXG4gICAqL1xuICBxdWVyeVBhcmFt