/** * @license Angular v6.0.9 * (c) 2010-2018 Google, Inc. https://angular.io/ * License: MIT */ import { Component, ɵisObservable, ɵisPromise, NgModuleRef, InjectionToken, NgModuleFactory, isDevMode, Attribute, Directive, ElementRef, HostBinding, HostListener, Input, Renderer2, ChangeDetectorRef, ContentChildren, ComponentFactoryResolver, EventEmitter, Output, ViewContainerRef, Compiler, Injectable, Injector, NgModuleFactoryLoader, ANALYZE_FOR_ENTRY_COMPONENTS, APP_BOOTSTRAP_LISTENER, APP_INITIALIZER, ApplicationRef, Inject, NgModule, NgProbeToken, Optional, SkipSelf, SystemJsNgModuleLoader, Version } from '@angular/core'; import { from, of, EmptyError, Observable, BehaviorSubject, Subject } from 'rxjs'; import { concatAll, every, last, map, mergeAll, catchError, first, mergeMap, concatMap, reduce, filter } from 'rxjs/operators'; import { LocationStrategy, APP_BASE_HREF, HashLocationStrategy, LOCATION_INITIALIZED, Location, PathLocationStrategy, PlatformLocation } from '@angular/common'; import { ɵgetDOM } from '@angular/platform-browser'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ /** * \@description * * Base for events the Router goes through, as opposed to events tied to a specific * Route. `RouterEvent`s will only be fired one time for any given navigation. * * Example: * * ``` * class MyService { * constructor(public router: Router, logger: Logger) { * router.events.filter(e => e instanceof RouterEvent).subscribe(e => { * logger.log(e.id, e.url); * }); * } * } * ``` * * \@experimental */ class RouterEvent { /** * @param {?} id * @param {?} url */ constructor(id, url) { this.id = id; this.url = url; } } /** * \@description * * Represents an event triggered when a navigation starts. * * */ class NavigationStart extends RouterEvent { /** * @param {?} id * @param {?} url * @param {?=} navigationTrigger * @param {?=} restoredState */ constructor(/** @docsNotRequired */ /** @docsNotRequired */ id, /** @docsNotRequired */ /** @docsNotRequired */ url, /** @docsNotRequired */ /** @docsNotRequired */ navigationTrigger = 'imperative', /** @docsNotRequired */ /** @docsNotRequired */ restoredState = null) { super(id, url); this.navigationTrigger = navigationTrigger; this.restoredState = restoredState; } /** * \@docsNotRequired * @return {?} */ toString() { return `NavigationStart(id: ${this.id}, url: '${this.url}')`; } } /** * \@description * * Represents an event triggered when a navigation ends successfully. * * */ class NavigationEnd extends RouterEvent { /** * @param {?} id * @param {?} url * @param {?} urlAfterRedirects */ constructor(/** @docsNotRequired */ /** @docsNotRequired */ id, /** @docsNotRequired */ /** @docsNotRequired */ url, urlAfterRedirects) { super(id, url); this.urlAfterRedirects = urlAfterRedirects; } /** * \@docsNotRequired * @return {?} */ toString() { return `NavigationEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}')`; } } /** * \@description * * Represents an event triggered when a navigation is canceled. * * */ class NavigationCancel extends RouterEvent { /** * @param {?} id * @param {?} url * @param {?} reason */ constructor(/** @docsNotRequired */ /** @docsNotRequired */ id, /** @docsNotRequired */ /** @docsNotRequired */ url, reason) { super(id, url); this.reason = reason; } /** * \@docsNotRequired * @return {?} */ toString() { return `NavigationCancel(id: ${this.id}, url: '${this.url}')`; } } /** * \@description * * Represents an event triggered when a navigation fails due to an unexpected error. * * */ class NavigationError extends RouterEvent { /** * @param {?} id * @param {?} url * @param {?} error */ constructor(/** @docsNotRequired */ /** @docsNotRequired */ id, /** @docsNotRequired */ /** @docsNotRequired */ url, error) { super(id, url); this.error = error; } /** * \@docsNotRequired * @return {?} */ toString() { return `NavigationError(id: ${this.id}, url: '${this.url}', error: ${this.error})`; } } /** * \@description * * Represents an event triggered when routes are recognized. * * */ class RoutesRecognized extends RouterEvent { /** * @param {?} id * @param {?} url * @param {?} urlAfterRedirects * @param {?} state */ constructor(/** @docsNotRequired */ /** @docsNotRequired */ id, /** @docsNotRequired */ /** @docsNotRequired */ url, urlAfterRedirects, state) { super(id, url); this.urlAfterRedirects = urlAfterRedirects; this.state = state; } /** * \@docsNotRequired * @return {?} */ toString() { return `RoutesRecognized(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; } } /** * \@description * * Represents the start of the Guard phase of routing. * * \@experimental */ class GuardsCheckStart extends RouterEvent { /** * @param {?} id * @param {?} url * @param {?} urlAfterRedirects * @param {?} state */ constructor(/** @docsNotRequired */ /** @docsNotRequired */ id, /** @docsNotRequired */ /** @docsNotRequired */ url, urlAfterRedirects, state) { super(id, url); this.urlAfterRedirects = urlAfterRedirects; this.state = state; } /** * @return {?} */ toString() { return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; } } /** * \@description * * Represents the end of the Guard phase of routing. * * \@experimental */ class GuardsCheckEnd extends RouterEvent { /** * @param {?} id * @param {?} url * @param {?} urlAfterRedirects * @param {?} state * @param {?} shouldActivate */ constructor(/** @docsNotRequired */ /** @docsNotRequired */ id, /** @docsNotRequired */ /** @docsNotRequired */ url, urlAfterRedirects, state, shouldActivate) { super(id, url); this.urlAfterRedirects = urlAfterRedirects; this.state = state; this.shouldActivate = shouldActivate; } /** * @return {?} */ toString() { return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`; } } /** * \@description * * Represents the start of the Resolve phase of routing. The timing of this * event may change, thus it's experimental. In the current iteration it will run * in the "resolve" phase whether there's things to resolve or not. In the future this * behavior may change to only run when there are things to be resolved. * * \@experimental */ class ResolveStart extends RouterEvent { /** * @param {?} id * @param {?} url * @param {?} urlAfterRedirects * @param {?} state */ constructor(/** @docsNotRequired */ /** @docsNotRequired */ id, /** @docsNotRequired */ /** @docsNotRequired */ url, urlAfterRedirects, state) { super(id, url); this.urlAfterRedirects = urlAfterRedirects; this.state = state; } /** * @return {?} */ toString() { return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; } } /** * \@description * * Represents the end of the Resolve phase of routing. See note on * `ResolveStart` for use of this experimental API. * * \@experimental */ class ResolveEnd extends RouterEvent { /** * @param {?} id * @param {?} url * @param {?} urlAfterRedirects * @param {?} state */ constructor(/** @docsNotRequired */ /** @docsNotRequired */ id, /** @docsNotRequired */ /** @docsNotRequired */ url, urlAfterRedirects, state) { super(id, url); this.urlAfterRedirects = urlAfterRedirects; this.state = state; } /** * @return {?} */ toString() { return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`; } } /** * \@description * * Represents an event triggered before lazy loading a route config. * * \@experimental */ class RouteConfigLoadStart { /** * @param {?} route */ constructor(route) { this.route = route; } /** * @return {?} */ toString() { return `RouteConfigLoadStart(path: ${this.route.path})`; } } /** * \@description * * Represents an event triggered when a route has been lazy loaded. * * \@experimental */ class RouteConfigLoadEnd { /** * @param {?} route */ constructor(route) { this.route = route; } /** * @return {?} */ toString() { return `RouteConfigLoadEnd(path: ${this.route.path})`; } } /** * \@description * * Represents the start of end of the Resolve phase of routing. See note on * `ChildActivationEnd` for use of this experimental API. * * \@experimental */ class ChildActivationStart { /** * @param {?} snapshot */ constructor(snapshot) { this.snapshot = snapshot; } /** * @return {?} */ toString() { const /** @type {?} */ path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ''; return `ChildActivationStart(path: '${path}')`; } } /** * \@description * * Represents the start of end of the Resolve phase of routing. See note on * `ChildActivationStart` for use of this experimental API. * * \@experimental */ class ChildActivationEnd { /** * @param {?} snapshot */ constructor(snapshot) { this.snapshot = snapshot; } /** * @return {?} */ toString() { const /** @type {?} */ path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ''; return `ChildActivationEnd(path: '${path}')`; } } /** * \@description * * Represents the start of end of the Resolve phase of routing. See note on * `ActivationEnd` for use of this experimental API. * * \@experimental */ class ActivationStart { /** * @param {?} snapshot */ constructor(snapshot) { this.snapshot = snapshot; } /** * @return {?} */ toString() { const /** @type {?} */ path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ''; return `ActivationStart(path: '${path}')`; } } /** * \@description * * Represents the start of end of the Resolve phase of routing. See note on * `ActivationStart` for use of this experimental API. * * \@experimental */ class ActivationEnd { /** * @param {?} snapshot */ constructor(snapshot) { this.snapshot = snapshot; } /** * @return {?} */ toString() { const /** @type {?} */ path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || ''; return `ActivationEnd(path: '${path}')`; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * This component is used internally within the router to be a placeholder when an empty * router-outlet is needed. For example, with a config such as: * * `{path: 'parent', outlet: 'nav', children: [...]}` * * In order to render, there needs to be a component on this config, which will default * to this `EmptyOutletComponent`. */ class EmptyOutletComponent { } EmptyOutletComponent.decorators = [ { type: Component, args: [{ template: `` }] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ /** * \@description * * Name of the primary outlet. * * */ const /** @type {?} */ PRIMARY_OUTLET = 'primary'; class ParamsAsMap { /** * @param {?} params */ constructor(params) { this.params = params || {}; } /** * @param {?} name * @return {?} */ has(name) { return this.params.hasOwnProperty(name); } /** * @param {?} name * @return {?} */ get(name) { if (this.has(name)) { const /** @type {?} */ v = this.params[name]; return Array.isArray(v) ? v[0] : v; } return null; } /** * @param {?} name * @return {?} */ getAll(name) { if (this.has(name)) { const /** @type {?} */ v = this.params[name]; return Array.isArray(v) ? v : [v]; } return []; } /** * @return {?} */ get keys() { return Object.keys(this.params); } } /** * Convert a `Params` instance to a `ParamMap`. * * * @param {?} params * @return {?} */ function convertToParamMap(params) { return new ParamsAsMap(params); } const /** @type {?} */ NAVIGATION_CANCELING_ERROR = 'ngNavigationCancelingError'; /** * @param {?} message * @return {?} */ function navigationCancelingError(message) { const /** @type {?} */ error = Error('NavigationCancelingError: ' + message); (/** @type {?} */ (error))[NAVIGATION_CANCELING_ERROR] = true; return error; } /** * @param {?} error * @return {?} */ function isNavigationCancelingError(error) { return error && (/** @type {?} */ (error))[NAVIGATION_CANCELING_ERROR]; } /** * @param {?} segments * @param {?} segmentGroup * @param {?} route * @return {?} */ function defaultUrlMatcher(segments, segmentGroup, route) { const /** @type {?} */ parts = /** @type {?} */ ((route.path)).split('/'); if (parts.length > segments.length) { // The actual URL is shorter than the config, no match return null; } if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || parts.length < segments.length)) { // The config is longer than the actual URL but we are looking for a full match, return null return null; } const /** @type {?} */ posParams = {}; // Check each config part against the actual URL for (let /** @type {?} */ index = 0; index < parts.length; index++) { const /** @type {?} */ part = parts[index]; const /** @type {?} */ segment = segments[index]; const /** @type {?} */ isParameter = part.startsWith(':'); if (isParameter) { posParams[part.substring(1)] = segment; } else if (part !== segment.path) { // The actual URL part does not match the config, no match return null; } } return { consumed: segments.slice(0, parts.length), posParams }; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class LoadedRouterConfig { /** * @param {?} routes * @param {?} module */ constructor(routes, module) { this.routes = routes; this.module = module; } } /** * @param {?} config * @param {?=} parentPath * @return {?} */ function validateConfig(config, parentPath = '') { // forEach doesn't iterate undefined values for (let /** @type {?} */ i = 0; i < config.length; i++) { const /** @type {?} */ route = config[i]; const /** @type {?} */ fullPath = getFullPath(parentPath, route); validateNode(route, fullPath); } } /** * @param {?} route * @param {?} fullPath * @return {?} */ function validateNode(route, fullPath) { if (!route) { throw new Error(` Invalid configuration of route '${fullPath}': Encountered undefined route. The reason might be an extra comma. Example: const routes: Routes = [ { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, { path: 'dashboard', component: DashboardComponent },, << two commas { path: 'detail/:id', component: HeroDetailComponent } ]; `); } if (Array.isArray(route)) { throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`); } if (!route.component && !route.children && !route.loadChildren && (route.outlet && route.outlet !== PRIMARY_OUTLET)) { throw new Error(`Invalid configuration of route '${fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`); } if (route.redirectTo && route.children) { throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`); } if (route.redirectTo && route.loadChildren) { throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`); } if (route.children && route.loadChildren) { throw new Error(`Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`); } if (route.redirectTo && route.component) { throw new Error(`Invalid configuration of route '${fullPath}': redirectTo and component cannot be used together`); } if (route.path && route.matcher) { throw new Error(`Invalid configuration of route '${fullPath}': path and matcher cannot be used together`); } if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) { throw new Error(`Invalid configuration of route '${fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`); } if (route.path === void 0 && route.matcher === void 0) { throw new Error(`Invalid configuration of route '${fullPath}': routes must have either a path or a matcher specified`); } if (typeof route.path === 'string' && route.path.charAt(0) === '/') { throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`); } if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) { const /** @type {?} */ exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`; throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`); } if (route.pathMatch !== void 0 && route.pathMatch !== 'full' && route.pathMatch !== 'prefix') { throw new Error(`Invalid configuration of route '${fullPath}': pathMatch can only be set to 'prefix' or 'full'`); } if (route.children) { validateConfig(route.children, fullPath); } } /** * @param {?} parentPath * @param {?} currentRoute * @return {?} */ function getFullPath(parentPath, currentRoute) { if (!currentRoute) { return parentPath; } if (!parentPath && !currentRoute.path) { return ''; } else if (parentPath && !currentRoute.path) { return `${parentPath}/`; } else if (!parentPath && currentRoute.path) { return currentRoute.path; } else { return `${parentPath}/${currentRoute.path}`; } } /** * Makes a copy of the config and adds any default required properties. * @param {?} r * @return {?} */ function standardizeConfig(r) { const /** @type {?} */ children = r.children && r.children.map(standardizeConfig); const /** @type {?} */ c = children ? Object.assign({}, r, { children }) : Object.assign({}, r); if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) { c.component = EmptyOutletComponent; } return c; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} a * @param {?} b * @return {?} */ function shallowEqualArrays(a, b) { if (a.length !== b.length) return false; for (let /** @type {?} */ i = 0; i < a.length; ++i) { if (!shallowEqual(a[i], b[i])) return false; } return true; } /** * @param {?} a * @param {?} b * @return {?} */ function shallowEqual(a, b) { const /** @type {?} */ k1 = Object.keys(a); const /** @type {?} */ k2 = Object.keys(b); if (k1.length != k2.length) { return false; } let /** @type {?} */ key; for (let /** @type {?} */ i = 0; i < k1.length; i++) { key = k1[i]; if (a[key] !== b[key]) { return false; } } return true; } /** * Flattens single-level nested arrays. * @template T * @param {?} arr * @return {?} */ function flatten(arr) { return Array.prototype.concat.apply([], arr); } /** * Return the last element of an array. * @template T * @param {?} a * @return {?} */ function last$1(a) { return a.length > 0 ? a[a.length - 1] : null; } /** * @template K, V * @param {?} map * @param {?} callback * @return {?} */ function forEach(map$$1, callback) { for (const /** @type {?} */ prop in map$$1) { if (map$$1.hasOwnProperty(prop)) { callback(map$$1[prop], prop); } } } /** * @template A, B * @param {?} obj * @param {?} fn * @return {?} */ function waitForMap(obj, fn) { if (Object.keys(obj).length === 0) { return of({}); } const /** @type {?} */ waitHead = []; const /** @type {?} */ waitTail = []; const /** @type {?} */ res = {}; forEach(obj, (a, k) => { const /** @type {?} */ mapped = fn(k, a).pipe(map((r) => res[k] = r)); if (k === PRIMARY_OUTLET) { waitHead.push(mapped); } else { waitTail.push(mapped); } }); // Closure compiler has problem with using spread operator here. So just using Array.concat. return of.apply(null, waitHead.concat(waitTail)).pipe(concatAll(), last(), map(() => res)); } /** * ANDs Observables by merging all input observables, reducing to an Observable verifying all * input Observables return `true`. * @param {?} observables * @return {?} */ function andObservables(observables) { return observables.pipe(mergeAll(), every((result) => result === true)); } /** * @template T * @param {?} value * @return {?} */ function wrapIntoObservable(value) { if (ɵisObservable(value)) { return value; } if (ɵisPromise(value)) { // Use `Promise.resolve()` to wrap promise-like instances. // Required ie when a Resolver returns a AngularJS `$q` promise to correctly trigger the // change detection. return from(Promise.resolve(value)); } return of(/** @type {?} */ (value)); } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @return {?} */ function createEmptyUrlTree() { return new UrlTree(new UrlSegmentGroup([], {}), {}, null); } /** * @param {?} container * @param {?} containee * @param {?} exact * @return {?} */ function containsTree(container, containee, exact) { if (exact) { return equalQueryParams(container.queryParams, containee.queryParams) && equalSegmentGroups(container.root, containee.root); } return containsQueryParams(container.queryParams, containee.queryParams) && containsSegmentGroup(container.root, containee.root); } /** * @param {?} container * @param {?} containee * @return {?} */ function equalQueryParams(container, containee) { return shallowEqual(container, containee); } /** * @param {?} container * @param {?} containee * @return {?} */ function equalSegmentGroups(container, containee) { if (!equalPath(container.segments, containee.segments)) return false; if (container.numberOfChildren !== containee.numberOfChildren) return false; for (const /** @type {?} */ c in containee.children) { if (!container.children[c]) return false; if (!equalSegmentGroups(container.children[c], containee.children[c])) return false; } return true; } /** * @param {?} container * @param {?} containee * @return {?} */ function containsQueryParams(container, containee) { return Object.keys(containee).length <= Object.keys(container).length && Object.keys(containee).every(key => containee[key] === container[key]); } /** * @param {?} container * @param {?} containee * @return {?} */ function containsSegmentGroup(container, containee) { return containsSegmentGroupHelper(container, containee, containee.segments); } /** * @param {?} container * @param {?} containee * @param {?} containeePaths * @return {?} */ function containsSegmentGroupHelper(container, containee, containeePaths) { if (container.segments.length > containeePaths.length) { const /** @type {?} */ current = container.segments.slice(0, containeePaths.length); if (!equalPath(current, containeePaths)) return false; if (containee.hasChildren()) return false; return true; } else if (container.segments.length === containeePaths.length) { if (!equalPath(container.segments, containeePaths)) return false; for (const /** @type {?} */ c in containee.children) { if (!container.children[c]) return false; if (!containsSegmentGroup(container.children[c], containee.children[c])) return false; } return true; } else { const /** @type {?} */ current = containeePaths.slice(0, container.segments.length); const /** @type {?} */ next = containeePaths.slice(container.segments.length); if (!equalPath(container.segments, current)) return false; if (!container.children[PRIMARY_OUTLET]) return false; return containsSegmentGroupHelper(container.children[PRIMARY_OUTLET], containee, next); } } /** * \@description * * Represents the parsed URL. * * Since a router state is a tree, and the URL is nothing but a serialized state, the URL is a * serialized tree. * UrlTree is a data structure that provides a lot of affordances in dealing with URLs * * ### Example * * ``` * \@Component({templateUrl:'template.html'}) * class MyComponent { * constructor(router: Router) { * const tree: UrlTree = * router.parseUrl('/team/33/(user/victor//support:help)?debug=true#fragment'); * const f = tree.fragment; // return 'fragment' * const q = tree.queryParams; // returns {debug: 'true'} * const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET]; * const s: UrlSegment[] = g.segments; // returns 2 segments 'team' and '33' * g.children[PRIMARY_OUTLET].segments; // returns 2 segments 'user' and 'victor' * g.children['support'].segments; // return 1 segment 'help' * } * } * ``` * * */ class UrlTree { /** * \@internal * @param {?} root * @param {?} queryParams * @param {?} fragment */ constructor(root, queryParams, fragment) { this.root = root; this.queryParams = queryParams; this.fragment = fragment; } /** * @return {?} */ get queryParamMap() { if (!this._queryParamMap) { this._queryParamMap = convertToParamMap(this.queryParams); } return this._queryParamMap; } /** * \@docsNotRequired * @return {?} */ toString() { return DEFAULT_SERIALIZER.serialize(this); } } /** * \@description * * Represents the parsed URL segment group. * * See `UrlTree` for more information. * * */ class UrlSegmentGroup { /** * @param {?} segments * @param {?} children */ constructor(segments, children) { this.segments = segments; this.children = children; /** * The parent node in the url tree */ this.parent = null; forEach(children, (v, k) => v.parent = this); } /** * Whether the segment has child segments * @return {?} */ hasChildren() { return this.numberOfChildren > 0; } /** * Number of child segments * @return {?} */ get numberOfChildren() { return Object.keys(this.children).length; } /** * \@docsNotRequired * @return {?} */ toString() { return serializePaths(this); } } /** * \@description * * Represents a single URL segment. * * A UrlSegment is a part of a URL between the two slashes. It contains a path and the matrix * parameters associated with the segment. * *  ## Example * * ``` * \@Component({templateUrl:'template.html'}) * class MyComponent { * constructor(router: Router) { * const tree: UrlTree = router.parseUrl('/team;id=33'); * const g: UrlSegmentGroup = tree.root.children[PRIMARY_OUTLET]; * const s: UrlSegment[] = g.segments; * s[0].path; // returns 'team' * s[0].parameters; // returns {id: 33} * } * } * ``` * * */ class UrlSegment { /** * @param {?} path * @param {?} parameters */ constructor(path, parameters) { this.path = path; this.parameters = parameters; } /** * @return {?} */ get parameterMap() { if (!this._parameterMap) { this._parameterMap = convertToParamMap(this.parameters); } return this._parameterMap; } /** * \@docsNotRequired * @return {?} */ toString() { return serializePath(this); } } /** * @param {?} as * @param {?} bs * @return {?} */ function equalSegments(as, bs) { return equalPath(as, bs) && as.every((a, i) => shallowEqual(a.parameters, bs[i].parameters)); } /** * @param {?} as * @param {?} bs * @return {?} */ function equalPath(as, bs) { if (as.length !== bs.length) return false; return as.every((a, i) => a.path === bs[i].path); } /** * @template T * @param {?} segment * @param {?} fn * @return {?} */ function mapChildrenIntoArray(segment, fn) { let /** @type {?} */ res = []; forEach(segment.children, (child, childOutlet) => { if (childOutlet === PRIMARY_OUTLET) { res = res.concat(fn(child, childOutlet)); } }); forEach(segment.children, (child, childOutlet) => { if (childOutlet !== PRIMARY_OUTLET) { res = res.concat(fn(child, childOutlet)); } }); return res; } /** * \@description * * Serializes and deserializes a URL string into a URL tree. * * The url serialization strategy is customizable. You can * make all URLs case insensitive by providing a custom UrlSerializer. * * See `DefaultUrlSerializer` for an example of a URL serializer. * * * @abstract */ class UrlSerializer { } /** * \@description * * A default implementation of the `UrlSerializer`. * * Example URLs: * * ``` * /inbox/33(popup:compose) * /inbox/33;open=true/messages/44 * ``` * * DefaultUrlSerializer uses parentheses to serialize secondary segments (e.g., popup:compose), the * colon syntax to specify the outlet, and the ';parameter=value' syntax (e.g., open=true) to * specify route specific parameters. * * */ class DefaultUrlSerializer { /** * Parses a url into a `UrlTree` * @param {?} url * @return {?} */ parse(url) { const /** @type {?} */ p = new UrlParser(url); return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment()); } /** * Converts a `UrlTree` into a url * @param {?} tree * @return {?} */ serialize(tree) { const /** @type {?} */ segment = `/${serializeSegment(tree.root, true)}`; const /** @type {?} */ query = serializeQueryParams(tree.queryParams); const /** @type {?} */ fragment = typeof tree.fragment === `string` ? `#${encodeUriFragment((/** @type {?} */ ((tree.fragment))))}` : ''; return `${segment}${query}${fragment}`; } } const /** @type {?} */ DEFAULT_SERIALIZER = new DefaultUrlSerializer(); /** * @param {?} segment * @return {?} */ function serializePaths(segment) { return segment.segments.map(p => serializePath(p)).join('/'); } /** * @param {?} segment * @param {?} root * @return {?} */ function serializeSegment(segment, root) { if (!segment.hasChildren()) { return serializePaths(segment); } if (root) { const /** @type {?} */ primary = segment.children[PRIMARY_OUTLET] ? serializeSegment(segment.children[PRIMARY_OUTLET], false) : ''; const /** @type {?} */ children = []; forEach(segment.children, (v, k) => { if (k !== PRIMARY_OUTLET) { children.push(`${k}:${serializeSegment(v, false)}`); } }); return children.length > 0 ? `${primary}(${children.join('//')})` : primary; } else { const /** @type {?} */ children = mapChildrenIntoArray(segment, (v, k) => { if (k === PRIMARY_OUTLET) { return [serializeSegment(segment.children[PRIMARY_OUTLET], false)]; } return [`${k}:${serializeSegment(v, false)}`]; }); return `${serializePaths(segment)}/(${children.join('//')})`; } } /** * Encodes a URI string with the default encoding. This function will only ever be called from * `encodeUriQuery` or `encodeUriSegment` as it's the base set of encodings to be used. We need * a custom encoding because encodeURIComponent is too aggressive and encodes stuff that doesn't * have to be encoded per https://url.spec.whatwg.org. * @param {?} s * @return {?} */ function encodeUriString(s) { return encodeURIComponent(s) .replace(/%40/g, '@') .replace(/%3A/gi, ':') .replace(/%24/g, '$') .replace(/%2C/gi, ','); } /** * This function should be used to encode both keys and values in a query string key/value. In * the following URL, you need to call encodeUriQuery on "k" and "v": * * http://www.site.org/html;mk=mv?k=v#f * @param {?} s * @return {?} */ function encodeUriQuery(s) { return encodeUriString(s).replace(/%3B/gi, ';'); } /** * This function should be used to encode a URL fragment. In the following URL, you need to call * encodeUriFragment on "f": * * http://www.site.org/html;mk=mv?k=v#f * @param {?} s * @return {?} */ function encodeUriFragment(s) { return encodeURI(s); } /** * This function should be run on any URI segment as well as the key and value in a key/value * pair for matrix params. In the following URL, you need to call encodeUriSegment on "html", * "mk", and "mv": * * http://www.site.org/html;mk=mv?k=v#f * @param {?} s * @return {?} */ function encodeUriSegment(s) { return encodeUriString(s).replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/%26/gi, '&'); } /** * @param {?} s * @return {?} */ function decode(s) { return decodeURIComponent(s); } /** * @param {?} s * @return {?} */ function decodeQuery(s) { return decode(s.replace(/\+/g, '%20')); } /** * @param {?} path * @return {?} */ function serializePath(path) { return `${encodeUriSegment(path.path)}${serializeMatrixParams(path.parameters)}`; } /** * @param {?} params * @return {?} */ function serializeMatrixParams(params) { return Object.keys(params) .map(key => `;${encodeUriSegment(key)}=${encodeUriSegment(params[key])}`) .join(''); } /** * @param {?} params * @return {?} */ function serializeQueryParams(params) { const /** @type {?} */ strParams = Object.keys(params).map((name) => { const /** @type {?} */ value = params[name]; return Array.isArray(value) ? value.map(v => `${encodeUriQuery(name)}=${encodeUriQuery(v)}`).join('&') : `${encodeUriQuery(name)}=${encodeUriQuery(value)}`; }); return strParams.length ? `?${strParams.join("&")}` : ''; } const /** @type {?} */ SEGMENT_RE = /^[^\/()?;=#]+/; /** * @param {?} str * @return {?} */ function matchSegments(str) { const /** @type {?} */ match = str.match(SEGMENT_RE); return match ? match[0] : ''; } const /** @type {?} */ QUERY_PARAM_RE = /^[^=?&#]+/; /** * @param {?} str * @return {?} */ function matchQueryParams(str) { const /** @type {?} */ match = str.match(QUERY_PARAM_RE); return match ? match[0] : ''; } const /** @type {?} */ QUERY_PARAM_VALUE_RE = /^[^?&#]+/; /** * @param {?} str * @return {?} */ function matchUrlQueryParamValue(str) { const /** @type {?} */ match = str.match(QUERY_PARAM_VALUE_RE); return match ? match[0] : ''; } class UrlParser { /** * @param {?} url */ constructor(url) { this.url = url; this.remaining = url; } /** * @return {?} */ parseRootSegment() { this.consumeOptional('/'); if (this.remaining === '' || this.peekStartsWith('?') || this.peekStartsWith('#')) { return new UrlSegmentGroup([], {}); } // The root segment group never has segments return new UrlSegmentGroup([], this.parseChildren()); } /** * @return {?} */ parseQueryParams() { const /** @type {?} */ params = {}; if (this.consumeOptional('?')) { do { this.parseQueryParam(params); } while (this.consumeOptional('&')); } return params; } /** * @return {?} */ parseFragment() { return this.consumeOptional('#') ? decodeURIComponent(this.remaining) : null; } /** * @return {?} */ parseChildren() { if (this.remaining === '') { return {}; } this.consumeOptional('/'); const /** @type {?} */ segments = []; if (!this.peekStartsWith('(')) { segments.push(this.parseSegment()); } while (this.peekStartsWith('/') && !this.peekStartsWith('//') && !this.peekStartsWith('/(')) { this.capture('/'); segments.push(this.parseSegment()); } let /** @type {?} */ children = {}; if (this.peekStartsWith('/(')) { this.capture('/'); children = this.parseParens(true); } let /** @type {?} */ res = {}; if (this.peekStartsWith('(')) { res = this.parseParens(false); } if (segments.length > 0 || Object.keys(children).length > 0) { res[PRIMARY_OUTLET] = new UrlSegmentGroup(segments, children); } return res; } /** * @return {?} */ parseSegment() { const /** @type {?} */ path = matchSegments(this.remaining); if (path === '' && this.peekStartsWith(';')) { throw new Error(`Empty path url segment cannot have parameters: '${this.remaining}'.`); } this.capture(path); return new UrlSegment(decode(path), this.parseMatrixParams()); } /** * @return {?} */ parseMatrixParams() { const /** @type {?} */ params = {}; while (this.consumeOptional(';')) { this.parseParam(params); } return params; } /** * @param {?} params * @return {?} */ parseParam(params) { const /** @type {?} */ key = matchSegments(this.remaining); if (!key) { return; } this.capture(key); let /** @type {?} */ value = ''; if (this.consumeOptional('=')) { const /** @type {?} */ valueMatch = matchSegments(this.remaining); if (valueMatch) { value = valueMatch; this.capture(value); } } params[decode(key)] = decode(value); } /** * @param {?} params * @return {?} */ parseQueryParam(params) { const /** @type {?} */ key = matchQueryParams(this.remaining); if (!key) { return; } this.capture(key); let /** @type {?} */ value = ''; if (this.consumeOptional('=')) { const /** @type {?} */ valueMatch = matchUrlQueryParamValue(this.remaining); if (valueMatch) { value = valueMatch; this.capture(value); } } const /** @type {?} */ decodedKey = decodeQuery(key); const /** @type {?} */ decodedVal = decodeQuery(value); if (params.hasOwnProperty(decodedKey)) { // Append to existing values let /** @type {?} */ currentVal = params[decodedKey]; if (!Array.isArray(currentVal)) { currentVal = [currentVal]; params[decodedKey] = currentVal; } currentVal.push(decodedVal); } else { // Create a new value params[decodedKey] = decodedVal; } } /** * @param {?} allowPrimary * @return {?} */ parseParens(allowPrimary) { const /** @type {?} */ segments = {}; this.capture('('); while (!this.consumeOptional(')') && this.remaining.length > 0) { const /** @type {?} */ path = matchSegments(this.remaining); const /** @type {?} */ next = this.remaining[path.length]; // if is is not one of these characters, then the segment was unescaped // or the group was not closed if (next !== '/' && next !== ')' && next !== ';') { throw new Error(`Cannot parse url '${this.url}'`); } let /** @type {?} */ outletName = /** @type {?} */ ((undefined)); if (path.indexOf(':') > -1) { outletName = path.substr(0, path.indexOf(':')); this.capture(outletName); this.capture(':'); } else if (allowPrimary) { outletName = PRIMARY_OUTLET; } const /** @type {?} */ children = this.parseChildren(); segments[outletName] = Object.keys(children).length === 1 ? children[PRIMARY_OUTLET] : new UrlSegmentGroup([], children); this.consumeOptional('//'); } return segments; } /** * @param {?} str * @return {?} */ peekStartsWith(str) { return this.remaining.startsWith(str); } /** * @param {?} str * @return {?} */ consumeOptional(str) { if (this.peekStartsWith(str)) { this.remaining = this.remaining.substring(str.length); return true; } return false; } /** * @param {?} str * @return {?} */ capture(str) { if (!this.consumeOptional(str)) { throw new Error(`Expected "${str}".`); } } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NoMatch { /** * @param {?=} segmentGroup */ constructor(segmentGroup) { this.segmentGroup = segmentGroup || null; } } class AbsoluteRedirect { /** * @param {?} urlTree */ constructor(urlTree) { this.urlTree = urlTree; } } /** * @param {?} segmentGroup * @return {?} */ function noMatch(segmentGroup) { return new Observable((obs) => obs.error(new NoMatch(segmentGroup))); } /** * @param {?} newTree * @return {?} */ function absoluteRedirect(newTree) { return new Observable((obs) => obs.error(new AbsoluteRedirect(newTree))); } /** * @param {?} redirectTo * @return {?} */ function namedOutletsRedirect(redirectTo) { return new Observable((obs) => obs.error(new Error(`Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`))); } /** * @param {?} route * @return {?} */ function canLoadFails(route) { return new Observable((obs) => obs.error(navigationCancelingError(`Cannot load children because the guard of the route "path: '${route.path}'" returned false`))); } /** * Returns the `UrlTree` with the redirection applied. * * Lazy modules are loaded along the way. * @param {?} moduleInjector * @param {?} configLoader * @param {?} urlSerializer * @param {?} urlTree * @param {?} config * @return {?} */ function applyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config) { return new ApplyRedirects(moduleInjector, configLoader, urlSerializer, urlTree, config).apply(); } class ApplyRedirects { /** * @param {?} moduleInjector * @param {?} configLoader * @param {?} urlSerializer * @param {?} urlTree * @param {?} config */ constructor(moduleInjector, configLoader, urlSerializer, urlTree, config) { this.configLoader = configLoader; this.urlSerializer = urlSerializer; this.urlTree = urlTree; this.config = config; this.allowRedirects = true; this.ngModule = moduleInjector.get(NgModuleRef); } /** * @return {?} */ apply() { const /** @type {?} */ expanded$ = this.expandSegmentGroup(this.ngModule, this.config, this.urlTree.root, PRIMARY_OUTLET); const /** @type {?} */ urlTrees$ = expanded$.pipe(map((rootSegmentGroup) => this.createUrlTree(rootSegmentGroup, this.urlTree.queryParams, /** @type {?} */ ((this.urlTree.fragment))))); return urlTrees$.pipe(catchError((e) => { if (e instanceof AbsoluteRedirect) { // after an absolute redirect we do not apply any more redirects! this.allowRedirects = false; // we need to run matching, so we can fetch all lazy-loaded modules return this.match(e.urlTree); } if (e instanceof NoMatch) { throw this.noMatchError(e); } throw e; })); } /** * @param {?} tree * @return {?} */ match(tree) { const /** @type {?} */ expanded$ = this.expandSegmentGroup(this.ngModule, this.config, tree.root, PRIMARY_OUTLET); const /** @type {?} */ mapped$ = expanded$.pipe(map((rootSegmentGroup) => this.createUrlTree(rootSegmentGroup, tree.queryParams, /** @type {?} */ ((tree.fragment))))); return mapped$.pipe(catchError((e) => { if (e instanceof NoMatch) { throw this.noMatchError(e); } throw e; })); } /** * @param {?} e * @return {?} */ noMatchError(e) { return new Error(`Cannot match any routes. URL Segment: '${e.segmentGroup}'`); } /** * @param {?} rootCandidate * @param {?} queryParams * @param {?} fragment * @return {?} */ createUrlTree(rootCandidate, queryParams, fragment) { const /** @type {?} */ root = rootCandidate.segments.length > 0 ? new UrlSegmentGroup([], { [PRIMARY_OUTLET]: rootCandidate }) : rootCandidate; return new UrlTree(root, queryParams, fragment); } /** * @param {?} ngModule * @param {?} routes * @param {?} segmentGroup * @param {?} outlet * @return {?} */ expandSegmentGroup(ngModule, routes, segmentGroup, outlet) { if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) { return this.expandChildren(ngModule, routes, segmentGroup) .pipe(map((children) => new UrlSegmentGroup([], children))); } return this.expandSegment(ngModule, segmentGroup, routes, segmentGroup.segments, outlet, true); } /** * @param {?} ngModule * @param {?} routes * @param {?} segmentGroup * @return {?} */ expandChildren(ngModule, routes, segmentGroup) { return waitForMap(segmentGroup.children, (childOutlet, child) => this.expandSegmentGroup(ngModule, routes, child, childOutlet)); } /** * @param {?} ngModule * @param {?} segmentGroup * @param {?} routes * @param {?} segments * @param {?} outlet * @param {?} allowRedirects * @return {?} */ expandSegment(ngModule, segmentGroup, routes, segments, outlet, allowRedirects) { return of(...routes).pipe(map((r) => { const /** @type {?} */ expanded$ = this.expandSegmentAgainstRoute(ngModule, segmentGroup, routes, r, segments, outlet, allowRedirects); return expanded$.pipe(catchError((e) => { if (e instanceof NoMatch) { // TODO(i): this return type doesn't match the declared Observable - // talk to Jason return /** @type {?} */ (of(null)); } throw e; })); }), concatAll(), first((s) => !!s), catchError((e, _) => { if (e instanceof EmptyError || e.name === 'EmptyError') { if (this.noLeftoversInUrl(segmentGroup, segments, outlet)) { return of(new UrlSegmentGroup([], {})); } throw new NoMatch(segmentGroup); } throw e; })); } /** * @param {?} segmentGroup * @param {?} segments * @param {?} outlet * @return {?} */ noLeftoversInUrl(segmentGroup, segments, outlet) { return segments.length === 0 && !segmentGroup.children[outlet]; } /** * @param {?} ngModule * @param {?} segmentGroup * @param {?} routes * @param {?} route * @param {?} paths * @param {?} outlet * @param {?} allowRedirects * @return {?} */ expandSegmentAgainstRoute(ngModule, segmentGroup, routes, route, paths, outlet, allowRedirects) { if (getOutlet(route) !== outlet) { return noMatch(segmentGroup); } if (route.redirectTo === undefined) { return this.matchSegmentAgainstRoute(ngModule, segmentGroup, route, paths); } if (allowRedirects && this.allowRedirects) { return this.expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, paths, outlet); } return noMatch(segmentGroup); } /** * @param {?} ngModule * @param {?} segmentGroup * @param {?} routes * @param {?} route * @param {?} segments * @param {?} outlet * @return {?} */ expandSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) { if (route.path === '**') { return this.expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet); } return this.expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet); } /** * @param {?} ngModule * @param {?} routes * @param {?} route * @param {?} outlet * @return {?} */ expandWildCardWithParamsAgainstRouteUsingRedirect(ngModule, routes, route, outlet) { const /** @type {?} */ newTree = this.applyRedirectCommands([], /** @type {?} */ ((route.redirectTo)), {}); if (/** @type {?} */ ((route.redirectTo)).startsWith('/')) { return absoluteRedirect(newTree); } return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => { const /** @type {?} */ group = new UrlSegmentGroup(newSegments, {}); return this.expandSegment(ngModule, group, routes, newSegments, outlet, false); })); } /** * @param {?} ngModule * @param {?} segmentGroup * @param {?} routes * @param {?} route * @param {?} segments * @param {?} outlet * @return {?} */ expandRegularSegmentAgainstRouteUsingRedirect(ngModule, segmentGroup, routes, route, segments, outlet) { const { matched, consumedSegments, lastChild, positionalParamSegments } = match(segmentGroup, route, segments); if (!matched) return noMatch(segmentGroup); const /** @type {?} */ newTree = this.applyRedirectCommands(consumedSegments, /** @type {?} */ ((route.redirectTo)), /** @type {?} */ (positionalParamSegments)); if (/** @type {?} */ ((route.redirectTo)).startsWith('/')) { return absoluteRedirect(newTree); } return this.lineralizeSegments(route, newTree).pipe(mergeMap((newSegments) => { return this.expandSegment(ngModule, segmentGroup, routes, newSegments.concat(segments.slice(lastChild)), outlet, false); })); } /** * @param {?} ngModule * @param {?} rawSegmentGroup * @param {?} route * @param {?} segments * @return {?} */ matchSegmentAgainstRoute(ngModule, rawSegmentGroup, route, segments) { if (route.path === '**') { if (route.loadChildren) { return this.configLoader.load(ngModule.injector, route) .pipe(map((cfg) => { route._loadedConfig = cfg; return new UrlSegmentGroup(segments, {}); })); } return of(new UrlSegmentGroup(segments, {})); } const { matched, consumedSegments, lastChild } = match(rawSegmentGroup, route, segments); if (!matched) return noMatch(rawSegmentGroup); const /** @type {?} */ rawSlicedSegments = segments.slice(lastChild); const /** @type {?} */ childConfig$ = this.getChildConfig(ngModule, route); return childConfig$.pipe(mergeMap((routerConfig) => { const /** @type {?} */ childModule = routerConfig.module; const /** @type {?} */ childConfig = routerConfig.routes; const { segmentGroup, slicedSegments } = split(rawSegmentGroup, consumedSegments, rawSlicedSegments, childConfig); if (slicedSegments.length === 0 && segmentGroup.hasChildren()) { const /** @type {?} */ expanded$ = this.expandChildren(childModule, childConfig, segmentGroup); return expanded$.pipe(map((children) => new UrlSegmentGroup(consumedSegments, children))); } if (childConfig.length === 0 && slicedSegments.length === 0) { return of(new UrlSegmentGroup(consumedSegments, {})); } const /** @type {?} */ expanded$ = this.expandSegment(childModule, segmentGroup, childConfig, slicedSegments, PRIMARY_OUTLET, true); return expanded$.pipe(map((cs) => new UrlSegmentGroup(consumedSegments.concat(cs.segments), cs.children))); })); } /** * @param {?} ngModule * @param {?} route * @return {?} */ getChildConfig(ngModule, route) { if (route.children) { // The children belong to the same module return of(new LoadedRouterConfig(route.children, ngModule)); } if (route.loadChildren) { // lazy children belong to the loaded module if (route._loadedConfig !== undefined) { return of(route._loadedConfig); } return runCanLoadGuard(ngModule.injector, route).pipe(mergeMap((shouldLoad) => { if (shouldLoad) { return this.configLoader.load(ngModule.injector, route) .pipe(map((cfg) => { route._loadedConfig = cfg; return cfg; })); } return canLoadFails(route); })); } return of(new LoadedRouterConfig([], ngModule)); } /** * @param {?} route * @param {?} urlTree * @return {?} */ lineralizeSegments(route, urlTree) { let /** @type {?} */ res = []; let /** @type {?} */ c = urlTree.root; while (true) { res = res.concat(c.segments); if (c.numberOfChildren === 0) { return of(res); } if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) { return namedOutletsRedirect(/** @type {?} */ ((route.redirectTo))); } c = c.children[PRIMARY_OUTLET]; } } /** * @param {?} segments * @param {?} redirectTo * @param {?} posParams * @return {?} */ applyRedirectCommands(segments, redirectTo, posParams) { return this.applyRedirectCreatreUrlTree(redirectTo, this.urlSerializer.parse(redirectTo), segments, posParams); } /** * @param {?} redirectTo * @param {?} urlTree * @param {?} segments * @param {?} posParams * @return {?} */ applyRedirectCreatreUrlTree(redirectTo, urlTree, segments, posParams) { const /** @type {?} */ newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams); return new UrlTree(newRoot, this.createQueryParams(urlTree.queryParams, this.urlTree.queryParams), urlTree.fragment); } /** * @param {?} redirectToParams * @param {?} actualParams * @return {?} */ createQueryParams(redirectToParams, actualParams) { const /** @type {?} */ res = {}; forEach(redirectToParams, (v, k) => { const /** @type {?} */ copySourceValue = typeof v === 'string' && v.startsWith(':'); if (copySourceValue) { const /** @type {?} */ sourceName = v.substring(1); res[k] = actualParams[sourceName]; } else { res[k] = v; } }); return res; } /** * @param {?} redirectTo * @param {?} group * @param {?} segments * @param {?} posParams * @return {?} */ createSegmentGroup(redirectTo, group, segments, posParams) { const /** @type {?} */ updatedSegments = this.createSegments(redirectTo, group.segments, segments, posParams); let /** @type {?} */ children = {}; forEach(group.children, (child, name) => { children[name] = this.createSegmentGroup(redirectTo, child, segments, posParams); }); return new UrlSegmentGroup(updatedSegments, children); } /** * @param {?} redirectTo * @param {?} redirectToSegments * @param {?} actualSegments * @param {?} posParams * @return {?} */ createSegments(redirectTo, redirectToSegments, actualSegments, posParams) { return redirectToSegments.map(s => s.path.startsWith(':') ? this.findPosParam(redirectTo, s, posParams) : this.findOrReturn(s, actualSegments)); } /** * @param {?} redirectTo * @param {?} redirectToUrlSegment * @param {?} posParams * @return {?} */ findPosParam(redirectTo, redirectToUrlSegment, posParams) { const /** @type {?} */ pos = posParams[redirectToUrlSegment.path.substring(1)]; if (!pos) throw new Error(`Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`); return pos; } /** * @param {?} redirectToUrlSegment * @param {?} actualSegments * @return {?} */ findOrReturn(redirectToUrlSegment, actualSegments) { let /** @type {?} */ idx = 0; for (const /** @type {?} */ s of actualSegments) { if (s.path === redirectToUrlSegment.path) { actualSegments.splice(idx); return s; } idx++; } return redirectToUrlSegment; } } /** * @param {?} moduleInjector * @param {?} route * @return {?} */ function runCanLoadGuard(moduleInjector, route) { const /** @type {?} */ canLoad = route.canLoad; if (!canLoad || canLoad.length === 0) return of(true); const /** @type {?} */ obs = from(canLoad).pipe(map((injectionToken) => { const /** @type {?} */ guard = moduleInjector.get(injectionToken); return wrapIntoObservable(guard.canLoad ? guard.canLoad(route) : guard(route)); })); return andObservables(obs); } /** * @param {?} segmentGroup * @param {?} route * @param {?} segments * @return {?} */ function match(segmentGroup, route, segments) { if (route.path === '') { if ((route.pathMatch === 'full') && (segmentGroup.hasChildren() || segments.length > 0)) { return { matched: false, consumedSegments: [], lastChild: 0, positionalParamSegments: {} }; } return { matched: true, consumedSegments: [], lastChild: 0, positionalParamSegments: {} }; } const /** @type {?} */ matcher = route.matcher || defaultUrlMatcher; const /** @type {?} */ res = matcher(segments, segmentGroup, route); if (!res) { return { matched: false, consumedSegments: /** @type {?} */ ([]), lastChild: 0, positionalParamSegments: {}, }; } return { matched: true, consumedSegments: /** @type {?} */ ((res.consumed)), lastChild: /** @type {?} */ ((res.consumed.length)), positionalParamSegments: /** @type {?} */ ((res.posParams)), }; } /** * @param {?} segmentGroup * @param {?} consumedSegments * @param {?} slicedSegments * @param {?} config * @return {?} */ function split(segmentGroup, consumedSegments, slicedSegments, config) { if (slicedSegments.length > 0 && containsEmptyPathRedirectsWithNamedOutlets(segmentGroup, slicedSegments, config)) { const /** @type {?} */ s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptySegments(config, new UrlSegmentGroup(slicedSegments, segmentGroup.children))); return { segmentGroup: mergeTrivialChildren(s), slicedSegments: [] }; } if (slicedSegments.length === 0 && containsEmptyPathRedirects(segmentGroup, slicedSegments, config)) { const /** @type {?} */ s = new UrlSegmentGroup(segmentGroup.segments, addEmptySegmentsToChildrenIfNeeded(segmentGroup, slicedSegments, config, segmentGroup.children)); return { segmentGroup: mergeTrivialChildren(s), slicedSegments }; } return { segmentGroup, slicedSegments }; } /** * @param {?} s * @return {?} */ function mergeTrivialChildren(s) { if (s.numberOfChildren === 1 && s.children[PRIMARY_OUTLET]) { const /** @type {?} */ c = s.children[PRIMARY_OUTLET]; return new UrlSegmentGroup(s.segments.concat(c.segments), c.children); } return s; } /** * @param {?} segmentGroup * @param {?} slicedSegments * @param {?} routes * @param {?} children * @return {?} */ function addEmptySegmentsToChildrenIfNeeded(segmentGroup, slicedSegments, routes, children) { const /** @type {?} */ res = {}; for (const /** @type {?} */ r of routes) { if (isEmptyPathRedirect(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) { res[getOutlet(r)] = new UrlSegmentGroup([], {}); } } return Object.assign({}, children, res); } /** * @param {?} routes * @param {?} primarySegmentGroup * @return {?} */ function createChildrenForEmptySegments(routes, primarySegmentGroup) { const /** @type {?} */ res = {}; res[PRIMARY_OUTLET] = primarySegmentGroup; for (const /** @type {?} */ r of routes) { if (r.path === '' && getOutlet(r) !== PRIMARY_OUTLET) { res[getOutlet(r)] = new UrlSegmentGroup([], {}); } } return res; } /** * @param {?} segmentGroup * @param {?} segments * @param {?} routes * @return {?} */ function containsEmptyPathRedirectsWithNamedOutlets(segmentGroup, segments, routes) { return routes.some(r => isEmptyPathRedirect(segmentGroup, segments, r) && getOutlet(r) !== PRIMARY_OUTLET); } /** * @param {?} segmentGroup * @param {?} segments * @param {?} routes * @return {?} */ function containsEmptyPathRedirects(segmentGroup, segments, routes) { return routes.some(r => isEmptyPathRedirect(segmentGroup, segments, r)); } /** * @param {?} segmentGroup * @param {?} segments * @param {?} r * @return {?} */ function isEmptyPathRedirect(segmentGroup, segments, r) { if ((segmentGroup.hasChildren() || segments.length > 0) && r.pathMatch === 'full') { return false; } return r.path === '' && r.redirectTo !== undefined; } /** * @param {?} route * @return {?} */ function getOutlet(route) { return route.outlet || PRIMARY_OUTLET; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ /** * @template T */ class Tree { /** * @param {?} root */ constructor(root) { this._root = root; } /** * @return {?} */ get root() { return this._root.value; } /** * \@internal * @param {?} t * @return {?} */ parent(t) { const /** @type {?} */ p = this.pathFromRoot(t); return p.length > 1 ? p[p.length - 2] : null; } /** * \@internal * @param {?} t * @return {?} */ children(t) { const /** @type {?} */ n = findNode(t, this._root); return n ? n.children.map(t => t.value) : []; } /** * \@internal * @param {?} t * @return {?} */ firstChild(t) { const /** @type {?} */ n = findNode(t, this._root); return n && n.children.length > 0 ? n.children[0].value : null; } /** * \@internal * @param {?} t * @return {?} */ siblings(t) { const /** @type {?} */ p = findPath(t, this._root); if (p.length < 2) return []; const /** @type {?} */ c = p[p.length - 2].children.map(c => c.value); return c.filter(cc => cc !== t); } /** * \@internal * @param {?} t * @return {?} */ pathFromRoot(t) { return findPath(t, this._root).map(s => s.value); } } /** * @template T * @param {?} value * @param {?} node * @return {?} */ function findNode(value, node) { if (value === node.value) return node; for (const /** @type {?} */ child of node.children) { const /** @type {?} */ node = findNode(value, child); if (node) return node; } return null; } /** * @template T * @param {?} value * @param {?} node * @return {?} */ function findPath(value, node) { if (value === node.value) return [node]; for (const /** @type {?} */ child of node.children) { const /** @type {?} */ path = findPath(value, child); if (path.length) { path.unshift(node); return path; } } return []; } /** * @template T */ class TreeNode { /** * @param {?} value * @param {?} children */ constructor(value, children) { this.value = value; this.children = children; } /** * @return {?} */ toString() { return `TreeNode(${this.value})`; } } /** * @template T * @param {?} node * @return {?} */ function nodeChildrenAsMap(node) { const /** @type {?} */ map$$1 = {}; if (node) { node.children.forEach(child => map$$1[child.value.outlet] = child); } return map$$1; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * \@description * * Represents the state of the router. * * RouterState is a tree of activated routes. Every node in this tree knows about the "consumed" URL * segments, the extracted parameters, and the resolved data. * * ### Example * * ``` * \@Component({templateUrl:'template.html'}) * class MyComponent { * constructor(router: Router) { * const state: RouterState = router.routerState; * const root: ActivatedRoute = state.root; * const child = root.firstChild; * const id: Observable = child.params.map(p => p.id); * //... * } * } * ``` * * See `ActivatedRoute` for more information. * * */ class RouterState extends Tree { /** * \@internal * @param {?} root * @param {?} snapshot */ constructor(root, snapshot) { super(root); this.snapshot = snapshot; setRouterState(/** @type {?} */ (this), root); } /** * @return {?} */ toString() { return this.snapshot.toString(); } } /** * @param {?} urlTree * @param {?} rootComponent * @return {?} */ function createEmptyState(urlTree, rootComponent) { const /** @type {?} */ snapshot = createEmptyStateSnapshot(urlTree, rootComponent); const /** @type {?} */ emptyUrl = new BehaviorSubject([new UrlSegment('', {})]); const /** @type {?} */ emptyParams = new BehaviorSubject({}); const /** @type {?} */ emptyData = new BehaviorSubject({}); const /** @type {?} */ emptyQueryParams = new BehaviorSubject({}); const /** @type {?} */ fragment = new BehaviorSubject(''); const /** @type {?} */ activated = new ActivatedRoute(emptyUrl, emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, snapshot.root); activated.snapshot = snapshot.root; return new RouterState(new TreeNode(activated, []), snapshot); } /** * @param {?} urlTree * @param {?} rootComponent * @return {?} */ function createEmptyStateSnapshot(urlTree, rootComponent) { const /** @type {?} */ emptyParams = {}; const /** @type {?} */ emptyData = {}; const /** @type {?} */ emptyQueryParams = {}; const /** @type {?} */ fragment = ''; const /** @type {?} */ activated = new ActivatedRouteSnapshot([], emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, null, urlTree.root, -1, {}); return new RouterStateSnapshot('', new TreeNode(activated, [])); } /** * \@description * * Contains the information about a route associated with a component loaded in an * outlet. An `ActivatedRoute` can also be used to traverse the router state tree. * * ``` * \@Component({...}) * class MyComponent { * constructor(route: ActivatedRoute) { * const id: Observable = route.params.map(p => p.id); * const url: Observable = route.url.map(segments => segments.join('')); * // route.data includes both `data` and `resolve` * const user = route.data.map(d => d.user); * } * } * ``` * * */ class ActivatedRoute { /** * \@internal * @param {?} url * @param {?} params * @param {?} queryParams * @param {?} fragment * @param {?} data * @param {?} outlet * @param {?} component * @param {?} futureSnapshot */ constructor(url, params, queryParams, fragment, data, outlet, component, futureSnapshot) { this.url = url; this.params = params; this.queryParams = queryParams; this.fragment = fragment; this.data = data; this.outlet = outlet; this.component = component; this._futureSnapshot = futureSnapshot; } /** * The configuration used to match this route * @return {?} */ get routeConfig() { return this._futureSnapshot.routeConfig; } /** * The root of the router state * @return {?} */ get root() { return this._routerState.root; } /** * The parent of this route in the router state tree * @return {?} */ get parent() { return this._routerState.parent(this); } /** * The first child of this route in the router state tree * @return {?} */ get firstChild() { return this._routerState.firstChild(this); } /** * The children of this route in the router state tree * @return {?} */ get children() { return this._routerState.children(this); } /** * The path from the root of the router state tree to this route * @return {?} */ get pathFromRoot() { return this._routerState.pathFromRoot(this); } /** * @return {?} */ get paramMap() { if (!this._paramMap) { this._paramMap = this.params.pipe(map((p) => convertToParamMap(p))); } return this._paramMap; } /** * @return {?} */ get queryParamMap() { if (!this._queryParamMap) { this._queryParamMap = this.queryParams.pipe(map((p) => convertToParamMap(p))); } return this._queryParamMap; } /** * @return {?} */ toString() { return this.snapshot ? this.snapshot.toString() : `Future(${this._futureSnapshot})`; } } /** * Returns the inherited params, data, and resolve for a given route. * By default, this only inherits values up to the nearest path-less or component-less route. * \@internal * @param {?} route * @param {?=} paramsInheritanceStrategy * @return {?} */ function inheritedParamsDataResolve(route, paramsInheritanceStrategy = 'emptyOnly') { const /** @type {?} */ pathFromRoot = route.pathFromRoot; let /** @type {?} */ inheritingStartingFrom = 0; if (paramsInheritanceStrategy !== 'always') { inheritingStartingFrom = pathFromRoot.length - 1; while (inheritingStartingFrom >= 1) { const /** @type {?} */ current = pathFromRoot[inheritingStartingFrom]; const /** @type {?} */ parent = pathFromRoot[inheritingStartingFrom - 1]; // current route is an empty path => inherits its parent's params and data if (current.routeConfig && current.routeConfig.path === '') { inheritingStartingFrom--; // parent is componentless => current route should inherit its params and data } else if (!parent.component) { inheritingStartingFrom--; } else { break; } } } return flattenInherited(pathFromRoot.slice(inheritingStartingFrom)); } /** * \@internal * @param {?} pathFromRoot * @return {?} */ function flattenInherited(pathFromRoot) { return pathFromRoot.reduce((res, curr) => { const /** @type {?} */ params = Object.assign({}, res.params, curr.params); const /** @type {?} */ data = Object.assign({}, res.data, curr.data); const /** @type {?} */ resolve = Object.assign({}, res.resolve, curr._resolvedData); return { params, data, resolve }; }, /** @type {?} */ ({ params: {}, data: {}, resolve: {} })); } /** * \@description * * Contains the information about a route associated with a component loaded in an * outlet at a particular moment in time. ActivatedRouteSnapshot can also be used to * traverse the router state tree. * * ``` * \@Component({templateUrl:'./my-component.html'}) * class MyComponent { * constructor(route: ActivatedRoute) { * const id: string = route.snapshot.params.id; * const url: string = route.snapshot.url.join(''); * const user = route.snapshot.data.user; * } * } * ``` * * */ class ActivatedRouteSnapshot { /** * \@internal * @param {?} url * @param {?} params * @param {?} queryParams * @param {?} fragment * @param {?} data * @param {?} outlet * @param {?} component * @param {?} routeConfig * @param {?} urlSegment * @param {?} lastPathIndex * @param {?} resolve */ constructor(url, params, queryParams, fragment, data, outlet, component, routeConfig, urlSegment, lastPathIndex, resolve) { this.url = url; this.params = params; this.queryParams = queryParams; this.fragment = fragment; this.data = data; this.outlet = outlet; this.component = component; this.routeConfig = routeConfig; this._urlSegment = urlSegment; this._lastPathIndex = lastPathIndex; this._resolve = resolve; } /** * The root of the router state * @return {?} */ get root() { return this._routerState.root; } /** * The parent of this route in the router state tree * @return {?} */ get parent() { return this._routerState.parent(this); } /** * The first child of this route in the router state tree * @return {?} */ get firstChild() { return this._routerState.firstChild(this); } /** * The children of this route in the router state tree * @return {?} */ get children() { return this._routerState.children(this); } /** * The path from the root of the router state tree to this route * @return {?} */ get pathFromRoot() { return this._routerState.pathFromRoot(this); } /** * @return {?} */ get paramMap() { if (!this._paramMap) { this._paramMap = convertToParamMap(this.params); } return this._paramMap; } /** * @return {?} */ get queryParamMap() { if (!this._queryParamMap) { this._queryParamMap = convertToParamMap(this.queryParams); } return this._queryParamMap; } /** * @return {?} */ toString() { const /** @type {?} */ url = this.url.map(segment => segment.toString()).join('/'); const /** @type {?} */ matched = this.routeConfig ? this.routeConfig.path : ''; return `Route(url:'${url}', path:'${matched}')`; } } /** * \@description * * Represents the state of the router at a moment in time. * * This is a tree of activated route snapshots. Every node in this tree knows about * the "consumed" URL segments, the extracted parameters, and the resolved data. * * ### Example * * ``` * \@Component({templateUrl:'template.html'}) * class MyComponent { * constructor(router: Router) { * const state: RouterState = router.routerState; * const snapshot: RouterStateSnapshot = state.snapshot; * const root: ActivatedRouteSnapshot = snapshot.root; * const child = root.firstChild; * const id: Observable = child.params.map(p => p.id); * //... * } * } * ``` * * */ class RouterStateSnapshot extends Tree { /** * \@internal * @param {?} url * @param {?} root */ constructor(url, root) { super(root); this.url = url; setRouterState(/** @type {?} */ (this), root); } /** * @return {?} */ toString() { return serializeNode(this._root); } } /** * @template U, T * @param {?} state * @param {?} node * @return {?} */ function setRouterState(state, node) { node.value._routerState = state; node.children.forEach(c => setRouterState(state, c)); } /** * @param {?} node * @return {?} */ function serializeNode(node) { const /** @type {?} */ c = node.children.length > 0 ? ` { ${node.children.map(serializeNode).join(', ')} } ` : ''; return `${node.value}${c}`; } /** * The expectation is that the activate route is created with the right set of parameters. * So we push new values into the observables only when they are not the initial values. * And we detect that by checking if the snapshot field is set. * @param {?} route * @return {?} */ function advanceActivatedRoute(route) { if (route.snapshot) { const /** @type {?} */ currentSnapshot = route.snapshot; const /** @type {?} */ nextSnapshot = route._futureSnapshot; route.snapshot = nextSnapshot; if (!shallowEqual(currentSnapshot.queryParams, nextSnapshot.queryParams)) { (/** @type {?} */ (route.queryParams)).next(nextSnapshot.queryParams); } if (currentSnapshot.fragment !== nextSnapshot.fragment) { (/** @type {?} */ (route.fragment)).next(nextSnapshot.fragment); } if (!shallowEqual(currentSnapshot.params, nextSnapshot.params)) { (/** @type {?} */ (route.params)).next(nextSnapshot.params); } if (!shallowEqualArrays(currentSnapshot.url, nextSnapshot.url)) { (/** @type {?} */ (route.url)).next(nextSnapshot.url); } if (!shallowEqual(currentSnapshot.data, nextSnapshot.data)) { (/** @type {?} */ (route.data)).next(nextSnapshot.data); } } else { route.snapshot = route._futureSnapshot; // this is for resolved data (/** @type {?} */ (route.data)).next(route._futureSnapshot.data); } } /** * @param {?} a * @param {?} b * @return {?} */ function equalParamsAndUrlSegments(a, b) { const /** @type {?} */ equalUrlParams = shallowEqual(a.params, b.params) && equalSegments(a.url, b.url); const /** @type {?} */ parentsMismatch = !a.parent !== !b.parent; return equalUrlParams && !parentsMismatch && (!a.parent || equalParamsAndUrlSegments(a.parent, /** @type {?} */ ((b.parent)))); } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} routeReuseStrategy * @param {?} curr * @param {?} prevState * @return {?} */ function createRouterState(routeReuseStrategy, curr, prevState) { const /** @type {?} */ root = createNode(routeReuseStrategy, curr._root, prevState ? prevState._root : undefined); return new RouterState(root, curr); } /** * @param {?} routeReuseStrategy * @param {?} curr * @param {?=} prevState * @return {?} */ function createNode(routeReuseStrategy, curr, prevState) { // reuse an activated route that is currently displayed on the screen if (prevState && routeReuseStrategy.shouldReuseRoute(curr.value, prevState.value.snapshot)) { const /** @type {?} */ value = prevState.value; value._futureSnapshot = curr.value; const /** @type {?} */ children = createOrReuseChildren(routeReuseStrategy, curr, prevState); return new TreeNode(value, children); // retrieve an activated route that is used to be displayed, but is not currently displayed } else { const /** @type {?} */ detachedRouteHandle = /** @type {?} */ (routeReuseStrategy.retrieve(curr.value)); if (detachedRouteHandle) { const /** @type {?} */ tree = detachedRouteHandle.route; setFutureSnapshotsOfActivatedRoutes(curr, tree); return tree; } else { const /** @type {?} */ value = createActivatedRoute(curr.value); const /** @type {?} */ children = curr.children.map(c => createNode(routeReuseStrategy, c)); return new TreeNode(value, children); } } } /** * @param {?} curr * @param {?} result * @return {?} */ function setFutureSnapshotsOfActivatedRoutes(curr, result) { if (curr.value.routeConfig !== result.value.routeConfig) { throw new Error('Cannot reattach ActivatedRouteSnapshot created from a different route'); } if (curr.children.length !== result.children.length) { throw new Error('Cannot reattach ActivatedRouteSnapshot with a different number of children'); } result.value._futureSnapshot = curr.value; for (let /** @type {?} */ i = 0; i < curr.children.length; ++i) { setFutureSnapshotsOfActivatedRoutes(curr.children[i], result.children[i]); } } /** * @param {?} routeReuseStrategy * @param {?} curr * @param {?} prevState * @return {?} */ function createOrReuseChildren(routeReuseStrategy, curr, prevState) { return curr.children.map(child => { for (const /** @type {?} */ p of prevState.children) { if (routeReuseStrategy.shouldReuseRoute(p.value.snapshot, child.value)) { return createNode(routeReuseStrategy, child, p); } } return createNode(routeReuseStrategy, child); }); } /** * @param {?} c * @return {?} */ function createActivatedRoute(c) { return new ActivatedRoute(new BehaviorSubject(c.url), new BehaviorSubject(c.params), new BehaviorSubject(c.queryParams), new BehaviorSubject(c.fragment), new BehaviorSubject(c.data), c.outlet, c.component, c); } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} route * @param {?} urlTree * @param {?} commands * @param {?} queryParams * @param {?} fragment * @return {?} */ function createUrlTree(route, urlTree, commands, queryParams, fragment) { if (commands.length === 0) { return tree(urlTree.root, urlTree.root, urlTree, queryParams, fragment); } const /** @type {?} */ nav = computeNavigation(commands); if (nav.toRoot()) { return tree(urlTree.root, new UrlSegmentGroup([], {}), urlTree, queryParams, fragment); } const /** @type {?} */ startingPosition = findStartingPosition(nav, urlTree, route); const /** @type {?} */ segmentGroup = startingPosition.processChildren ? updateSegmentGroupChildren(startingPosition.segmentGroup, startingPosition.index, nav.commands) : updateSegmentGroup(startingPosition.segmentGroup, startingPosition.index, nav.commands); return tree(startingPosition.segmentGroup, segmentGroup, urlTree, queryParams, fragment); } /** * @param {?} command * @return {?} */ function isMatrixParams(command) { return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath; } /** * @param {?} oldSegmentGroup * @param {?} newSegmentGroup * @param {?} urlTree * @param {?} queryParams * @param {?} fragment * @return {?} */ function tree(oldSegmentGroup, newSegmentGroup, urlTree, queryParams, fragment) { let /** @type {?} */ qp = {}; if (queryParams) { forEach(queryParams, (value, name) => { qp[name] = Array.isArray(value) ? value.map((v) => `${v}`) : `${value}`; }); } if (urlTree.root === oldSegmentGroup) { return new UrlTree(newSegmentGroup, qp, fragment); } return new UrlTree(replaceSegment(urlTree.root, oldSegmentGroup, newSegmentGroup), qp, fragment); } /** * @param {?} current * @param {?} oldSegment * @param {?} newSegment * @return {?} */ function replaceSegment(current, oldSegment, newSegment) { const /** @type {?} */ children = {}; forEach(current.children, (c, outletName) => { if (c === oldSegment) { children[outletName] = newSegment; } else { children[outletName] = replaceSegment(c, oldSegment, newSegment); } }); return new UrlSegmentGroup(current.segments, children); } class Navigation { /** * @param {?} isAbsolute * @param {?} numberOfDoubleDots * @param {?} commands */ constructor(isAbsolute, numberOfDoubleDots, commands) { this.isAbsolute = isAbsolute; this.numberOfDoubleDots = numberOfDoubleDots; this.commands = commands; if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) { throw new Error('Root segment cannot have matrix parameters'); } const /** @type {?} */ cmdWithOutlet = commands.find(c => typeof c === 'object' && c != null && c.outlets); if (cmdWithOutlet && cmdWithOutlet !== last$1(commands)) { throw new Error('{outlets:{}} has to be the last command'); } } /** * @return {?} */ toRoot() { return this.isAbsolute && this.commands.length === 1 && this.commands[0] == '/'; } } /** * Transforms commands to a normalized `Navigation` * @param {?} commands * @return {?} */ function computeNavigation(commands) { if ((typeof commands[0] === 'string') && commands.length === 1 && commands[0] === '/') { return new Navigation(true, 0, commands); } let /** @type {?} */ numberOfDoubleDots = 0; let /** @type {?} */ isAbsolute = false; const /** @type {?} */ res = commands.reduce((res, cmd, cmdIdx) => { if (typeof cmd === 'object' && cmd != null) { if (cmd.outlets) { const /** @type {?} */ outlets = {}; forEach(cmd.outlets, (commands, name) => { outlets[name] = typeof commands === 'string' ? commands.split('/') : commands; }); return [...res, { outlets }]; } if (cmd.segmentPath) { return [...res, cmd.segmentPath]; } } if (!(typeof cmd === 'string')) { return [...res, cmd]; } if (cmdIdx === 0) { cmd.split('/').forEach((urlPart, partIndex) => { if (partIndex == 0 && urlPart === '.') ; else if (partIndex == 0 && urlPart === '') { // '/a' isAbsolute = true; } else if (urlPart === '..') { // '../a' numberOfDoubleDots++; } else if (urlPart != '') { res.push(urlPart); } }); return res; } return [...res, cmd]; }, []); return new Navigation(isAbsolute, numberOfDoubleDots, res); } class Position { /** * @param {?} segmentGroup * @param {?} processChildren * @param {?} index */ constructor(segmentGroup, processChildren, index) { this.segmentGroup = segmentGroup; this.processChildren = processChildren; this.index = index; } } /** * @param {?} nav * @param {?} tree * @param {?} route * @return {?} */ function findStartingPosition(nav, tree, route) { if (nav.isAbsolute) { return new Position(tree.root, true, 0); } if (route.snapshot._lastPathIndex === -1) { return new Position(route.snapshot._urlSegment, true, 0); } const /** @type {?} */ modifier = isMatrixParams(nav.commands[0]) ? 0 : 1; const /** @type {?} */ index = route.snapshot._lastPathIndex + modifier; return createPositionApplyingDoubleDots(route.snapshot._urlSegment, index, nav.numberOfDoubleDots); } /** * @param {?} group * @param {?} index * @param {?} numberOfDoubleDots * @return {?} */ function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) { let /** @type {?} */ g = group; let /** @type {?} */ ci = index; let /** @type {?} */ dd = numberOfDoubleDots; while (dd > ci) { dd -= ci; g = /** @type {?} */ ((g.parent)); if (!g) { throw new Error('Invalid number of \'../\''); } ci = g.segments.length; } return new Position(g, false, ci - dd); } /** * @param {?} command * @return {?} */ function getPath(command) { if (typeof command === 'object' && command != null && command.outlets) { return command.outlets[PRIMARY_OUTLET]; } return `${command}`; } /** * @param {?} commands * @return {?} */ function getOutlets(commands) { if (!(typeof commands[0] === 'object')) return { [PRIMARY_OUTLET]: commands }; if (commands[0].outlets === undefined) return { [PRIMARY_OUTLET]: commands }; return commands[0].outlets; } /** * @param {?} segmentGroup * @param {?} startIndex * @param {?} commands * @return {?} */ function updateSegmentGroup(segmentGroup, startIndex, commands) { if (!segmentGroup) { segmentGroup = new UrlSegmentGroup([], {}); } if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) { return updateSegmentGroupChildren(segmentGroup, startIndex, commands); } const /** @type {?} */ m = prefixedWith(segmentGroup, startIndex, commands); const /** @type {?} */ slicedCommands = commands.slice(m.commandIndex); if (m.match && m.pathIndex < segmentGroup.segments.length) { const /** @type {?} */ g = new UrlSegmentGroup(segmentGroup.segments.slice(0, m.pathIndex), {}); g.children[PRIMARY_OUTLET] = new UrlSegmentGroup(segmentGroup.segments.slice(m.pathIndex), segmentGroup.children); return updateSegmentGroupChildren(g, 0, slicedCommands); } else if (m.match && slicedCommands.length === 0) { return new UrlSegmentGroup(segmentGroup.segments, {}); } else if (m.match && !segmentGroup.hasChildren()) { return createNewSegmentGroup(segmentGroup, startIndex, commands); } else if (m.match) { return updateSegmentGroupChildren(segmentGroup, 0, slicedCommands); } else { return createNewSegmentGroup(segmentGroup, startIndex, commands); } } /** * @param {?} segmentGroup * @param {?} startIndex * @param {?} commands * @return {?} */ function updateSegmentGroupChildren(segmentGroup, startIndex, commands) { if (commands.length === 0) { return new UrlSegmentGroup(segmentGroup.segments, {}); } else { const /** @type {?} */ outlets = getOutlets(commands); const /** @type {?} */ children = {}; forEach(outlets, (commands, outlet) => { if (commands !== null) { children[outlet] = updateSegmentGroup(segmentGroup.children[outlet], startIndex, commands); } }); forEach(segmentGroup.children, (child, childOutlet) => { if (outlets[childOutlet] === undefined) { children[childOutlet] = child; } }); return new UrlSegmentGroup(segmentGroup.segments, children); } } /** * @param {?} segmentGroup * @param {?} startIndex * @param {?} commands * @return {?} */ function prefixedWith(segmentGroup, startIndex, commands) { let /** @type {?} */ currentCommandIndex = 0; let /** @type {?} */ currentPathIndex = startIndex; const /** @type {?} */ noMatch = { match: false, pathIndex: 0, commandIndex: 0 }; while (currentPathIndex < segmentGroup.segments.length) { if (currentCommandIndex >= commands.length) return noMatch; const /** @type {?} */ path = segmentGroup.segments[currentPathIndex]; const /** @type {?} */ curr = getPath(commands[currentCommandIndex]); const /** @type {?} */ next = currentCommandIndex < commands.length - 1 ? commands[currentCommandIndex + 1] : null; if (currentPathIndex > 0 && curr === undefined) break; if (curr && next && (typeof next === 'object') && next.outlets === undefined) { if (!compare(curr, next, path)) return noMatch; currentCommandIndex += 2; } else { if (!compare(curr, {}, path)) return noMatch; currentCommandIndex++; } currentPathIndex++; } return { match: true, pathIndex: currentPathIndex, commandIndex: currentCommandIndex }; } /** * @param {?} segmentGroup * @param {?} startIndex * @param {?} commands * @return {?} */ function createNewSegmentGroup(segmentGroup, startIndex, commands) { const /** @type {?} */ paths = segmentGroup.segments.slice(0, startIndex); let /** @type {?} */ i = 0; while (i < commands.length) { if (typeof commands[i] === 'object' && commands[i].outlets !== undefined) { const /** @type {?} */ children = createNewSegmentChildren(commands[i].outlets); return new UrlSegmentGroup(paths, children); } // if we start with an object literal, we need to reuse the path part from the segment if (i === 0 && isMatrixParams(commands[0])) { const /** @type {?} */ p = segmentGroup.segments[startIndex]; paths.push(new UrlSegment(p.path, commands[0])); i++; continue; } const /** @type {?} */ curr = getPath(commands[i]); const /** @type {?} */ next = (i < commands.length - 1) ? commands[i + 1] : null; if (curr && next && isMatrixParams(next)) { paths.push(new UrlSegment(curr, stringify(next))); i += 2; } else { paths.push(new UrlSegment(curr, {})); i++; } } return new UrlSegmentGroup(paths, {}); } /** * @param {?} outlets * @return {?} */ function createNewSegmentChildren(outlets) { const /** @type {?} */ children = {}; forEach(outlets, (commands, outlet) => { if (commands !== null) { children[outlet] = createNewSegmentGroup(new UrlSegmentGroup([], {}), 0, commands); } }); return children; } /** * @param {?} params * @return {?} */ function stringify(params) { const /** @type {?} */ res = {}; forEach(params, (v, k) => res[k] = `${v}`); return res; } /** * @param {?} path * @param {?} params * @param {?} segment * @return {?} */ function compare(path, params, segment) { return path == segment.path && shallowEqual(params, segment.parameters); } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class CanActivate { /** * @param {?} path */ constructor(path) { this.path = path; this.route = this.path[this.path.length - 1]; } } class CanDeactivate { /** * @param {?} component * @param {?} route */ constructor(component, route) { this.component = component; this.route = route; } } /** * This class bundles the actions involved in preactivation of a route. */ class PreActivation { /** * @param {?} future * @param {?} curr * @param {?} moduleInjector * @param {?=} forwardEvent */ constructor(future, curr, moduleInjector, forwardEvent) { this.future = future; this.curr = curr; this.moduleInjector = moduleInjector; this.forwardEvent = forwardEvent; this.canActivateChecks = []; this.canDeactivateChecks = []; } /** * @param {?} parentContexts * @return {?} */ initialize(parentContexts) { const /** @type {?} */ futureRoot = this.future._root; const /** @type {?} */ currRoot = this.curr ? this.curr._root : null; this.setupChildRouteGuards(futureRoot, currRoot, parentContexts, [futureRoot.value]); } /** * @return {?} */ checkGuards() { if (!this.isDeactivating() && !this.isActivating()) { return of(true); } const /** @type {?} */ canDeactivate$ = this.runCanDeactivateChecks(); return canDeactivate$.pipe(mergeMap((canDeactivate) => canDeactivate ? this.runCanActivateChecks() : of(false))); } /** * @param {?} paramsInheritanceStrategy * @return {?} */ resolveData(paramsInheritanceStrategy) { if (!this.isActivating()) return of(null); return from(this.canActivateChecks) .pipe(concatMap((check) => this.runResolve(check.route, paramsInheritanceStrategy)), reduce((_, __) => _)); } /** * @return {?} */ isDeactivating() { return this.canDeactivateChecks.length !== 0; } /** * @return {?} */ isActivating() { return this.canActivateChecks.length !== 0; } /** * Iterates over child routes and calls recursive `setupRouteGuards` to get `this` instance in * proper state to run `checkGuards()` method. * @param {?} futureNode * @param {?} currNode * @param {?} contexts * @param {?} futurePath * @return {?} */ setupChildRouteGuards(futureNode, currNode, contexts, futurePath) { const /** @type {?} */ prevChildren = nodeChildrenAsMap(currNode); // Process the children of the future route futureNode.children.forEach(c => { this.setupRouteGuards(c, prevChildren[c.value.outlet], contexts, futurePath.concat([c.value])); delete prevChildren[c.value.outlet]; }); // Process any children left from the current route (not active for the future route) forEach(prevChildren, (v, k) => this.deactivateRouteAndItsChildren(v, /** @type {?} */ ((contexts)).getContext(k))); } /** * Iterates over child routes and calls recursive `setupRouteGuards` to get `this` instance in * proper state to run `checkGuards()` method. * @param {?} futureNode * @param {?} currNode * @param {?} parentContexts * @param {?} futurePath * @return {?} */ setupRouteGuards(futureNode, currNode, parentContexts, futurePath) { const /** @type {?} */ future = futureNode.value; const /** @type {?} */ curr = currNode ? currNode.value : null; const /** @type {?} */ context = parentContexts ? parentContexts.getContext(futureNode.value.outlet) : null; // reusing the node if (curr && future.routeConfig === curr.routeConfig) { const /** @type {?} */ shouldRunGuardsAndResolvers = this.shouldRunGuardsAndResolvers(curr, future, /** @type {?} */ ((future.routeConfig)).runGuardsAndResolvers); if (shouldRunGuardsAndResolvers) { this.canActivateChecks.push(new CanActivate(futurePath)); } else { // we need to set the data future.data = curr.data; future._resolvedData = curr._resolvedData; } // If we have a component, we need to go through an outlet. if (future.component) { this.setupChildRouteGuards(futureNode, currNode, context ? context.children : null, futurePath); // if we have a componentless route, we recurse but keep the same outlet map. } else { this.setupChildRouteGuards(futureNode, currNode, parentContexts, futurePath); } if (shouldRunGuardsAndResolvers) { const /** @type {?} */ outlet = /** @type {?} */ ((/** @type {?} */ ((context)).outlet)); this.canDeactivateChecks.push(new CanDeactivate(outlet.component, curr)); } } else { if (curr) { this.deactivateRouteAndItsChildren(currNode, context); } this.canActivateChecks.push(new CanActivate(futurePath)); // If we have a component, we need to go through an outlet. if (future.component) { this.setupChildRouteGuards(futureNode, null, context ? context.children : null, futurePath); // if we have a componentless route, we recurse but keep the same outlet map. } else { this.setupChildRouteGuards(futureNode, null, parentContexts, futurePath); } } } /** * @param {?} curr * @param {?} future * @param {?} mode * @return {?} */ shouldRunGuardsAndResolvers(curr, future, mode) { switch (mode) { case 'always': return true; case 'paramsOrQueryParamsChange': return !equalParamsAndUrlSegments(curr, future) || !shallowEqual(curr.queryParams, future.queryParams); case 'paramsChange': default: return !equalParamsAndUrlSegments(curr, future); } } /** * @param {?} route * @param {?} context * @return {?} */ deactivateRouteAndItsChildren(route, context) { const /** @type {?} */ children = nodeChildrenAsMap(route); const /** @type {?} */ r = route.value; forEach(children, (node, childName) => { if (!r.component) { this.deactivateRouteAndItsChildren(node, context); } else if (context) { this.deactivateRouteAndItsChildren(node, context.children.getContext(childName)); } else { this.deactivateRouteAndItsChildren(node, null); } }); if (!r.component) { this.canDeactivateChecks.push(new CanDeactivate(null, r)); } else if (context && context.outlet && context.outlet.isActivated) { this.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, r)); } else { this.canDeactivateChecks.push(new CanDeactivate(null, r)); } } /** * @return {?} */ runCanDeactivateChecks() { return from(this.canDeactivateChecks) .pipe(mergeMap((check) => this.runCanDeactivate(check.component, check.route)), every((result) => result === true)); } /** * @return {?} */ runCanActivateChecks() { return from(this.canActivateChecks) .pipe(concatMap((check) => andObservables(from([ this.fireChildActivationStart(check.route.parent), this.fireActivationStart(check.route), this.runCanActivateChild(check.path), this.runCanActivate(check.route) ]))), every((result) => result === true)); // this.fireChildActivationStart(check.path), } /** * This should fire off `ActivationStart` events for each route being activated at this * level. * In other words, if you're activating `a` and `b` below, `path` will contain the * `ActivatedRouteSnapshot`s for both and we will fire `ActivationStart` for both. Always * return * `true` so checks continue to run. * @param {?} snapshot * @return {?} */ fireActivationStart(snapshot) { if (snapshot !== null && this.forwardEvent) { this.forwardEvent(new ActivationStart(snapshot)); } return of(true); } /** * This should fire off `ChildActivationStart` events for each route being activated at this * level. * In other words, if you're activating `a` and `b` below, `path` will contain the * `ActivatedRouteSnapshot`s for both and we will fire `ChildActivationStart` for both. Always * return * `true` so checks continue to run. * @param {?} snapshot * @return {?} */ fireChildActivationStart(snapshot) { if (snapshot !== null && this.forwardEvent) { this.forwardEvent(new ChildActivationStart(snapshot)); } return of(true); } /** * @param {?} future * @return {?} */ runCanActivate(future) { const /** @type {?} */ canActivate = future.routeConfig ? future.routeConfig.canActivate : null; if (!canActivate || canActivate.length === 0) return of(true); const /** @type {?} */ obs = from(canActivate).pipe(map((c) => { const /** @type {?} */ guard = this.getToken(c, future); let /** @type {?} */ observable; if (guard.canActivate) { observable = wrapIntoObservable(guard.canActivate(future, this.future)); } else { observable = wrapIntoObservable(guard(future, this.future)); } return observable.pipe(first()); })); return andObservables(obs); } /** * @param {?} path * @return {?} */ runCanActivateChild(path) { const /** @type {?} */ future = path[path.length - 1]; const /** @type {?} */ canActivateChildGuards = path.slice(0, path.length - 1) .reverse() .map(p => this.extractCanActivateChild(p)) .filter(_ => _ !== null); return andObservables(from(canActivateChildGuards).pipe(map((d) => { const /** @type {?} */ obs = from(d.guards).pipe(map((c) => { const /** @type {?} */ guard = this.getToken(c, d.node); let /** @type {?} */ observable; if (guard.canActivateChild) { observable = wrapIntoObservable(guard.canActivateChild(future, this.future)); } else { observable = wrapIntoObservable(guard(future, this.future)); } return observable.pipe(first()); })); return andObservables(obs); }))); } /** * @param {?} p * @return {?} */ extractCanActivateChild(p) { const /** @type {?} */ canActivateChild = p.routeConfig ? p.routeConfig.canActivateChild : null; if (!canActivateChild || canActivateChild.length === 0) return null; return { node: p, guards: canActivateChild }; } /** * @param {?} component * @param {?} curr * @return {?} */ runCanDeactivate(component, curr) { const /** @type {?} */ canDeactivate = curr && curr.routeConfig ? curr.routeConfig.canDeactivate : null; if (!canDeactivate || canDeactivate.length === 0) return of(true); const /** @type {?} */ canDeactivate$ = from(canDeactivate).pipe(mergeMap((c) => { const /** @type {?} */ guard = this.getToken(c, curr); let /** @type {?} */ observable; if (guard.canDeactivate) { observable = wrapIntoObservable(guard.canDeactivate(component, curr, this.curr, this.future)); } else { observable = wrapIntoObservable(guard(component, curr, this.curr, this.future)); } return observable.pipe(first()); })); return canDeactivate$.pipe(every((result) => result === true)); } /** * @param {?} future * @param {?} paramsInheritanceStrategy * @return {?} */ runResolve(future, paramsInheritanceStrategy) { const /** @type {?} */ resolve = future._resolve; return this.resolveNode(resolve, future).pipe(map((resolvedData) => { future._resolvedData = resolvedData; future.data = Object.assign({}, future.data, inheritedParamsDataResolve(future, paramsInheritanceStrategy).resolve); return null; })); } /** * @param {?} resolve * @param {?} future * @return {?} */ resolveNode(resolve, future) { const /** @type {?} */ keys = Object.keys(resolve); if (keys.length === 0) { return of({}); } if (keys.length === 1) { const /** @type {?} */ key = keys[0]; return this.getResolver(resolve[key], future).pipe(map((value) => { return { [key]: value }; })); } const /** @type {?} */ data = {}; const /** @type {?} */ runningResolvers$ = from(keys).pipe(mergeMap((key) => { return this.getResolver(resolve[key], future).pipe(map((value) => { data[key] = value; return value; })); })); return runningResolvers$.pipe(last(), map(() => data)); } /** * @param {?} injectionToken * @param {?} future * @return {?} */ getResolver(injectionToken, future) { const /** @type {?} */ resolver = this.getToken(injectionToken, future); return resolver.resolve ? wrapIntoObservable(resolver.resolve(future, this.future)) : wrapIntoObservable(resolver(future, this.future)); } /** * @param {?} token * @param {?} snapshot * @return {?} */ getToken(token, snapshot) { const /** @type {?} */ config = closestLoadedConfig(snapshot); const /** @type {?} */ injector = config ? config.module.injector : this.moduleInjector; return injector.get(token); } } /** * @param {?} snapshot * @return {?} */ function closestLoadedConfig(snapshot) { if (!snapshot) return null; for (let /** @type {?} */ s = snapshot.parent; s; s = s.parent) { const /** @type {?} */ route = s.routeConfig; if (route && route._loadedConfig) return route._loadedConfig; } return null; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class NoMatch$1 { } /** * @param {?} rootComponentType * @param {?} config * @param {?} urlTree * @param {?} url * @param {?=} paramsInheritanceStrategy * @return {?} */ function recognize(rootComponentType, config, urlTree, url, paramsInheritanceStrategy = 'emptyOnly') { return new Recognizer(rootComponentType, config, urlTree, url, paramsInheritanceStrategy) .recognize(); } class Recognizer { /** * @param {?} rootComponentType * @param {?} config * @param {?} urlTree * @param {?} url * @param {?} paramsInheritanceStrategy */ constructor(rootComponentType, config, urlTree, url, paramsInheritanceStrategy) { this.rootComponentType = rootComponentType; this.config = config; this.urlTree = urlTree; this.url = url; this.paramsInheritanceStrategy = paramsInheritanceStrategy; } /** * @return {?} */ recognize() { try { const /** @type {?} */ rootSegmentGroup = split$1(this.urlTree.root, [], [], this.config).segmentGroup; const /** @type {?} */ children = this.processSegmentGroup(this.config, rootSegmentGroup, PRIMARY_OUTLET); const /** @type {?} */ root = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze(Object.assign({}, this.urlTree.queryParams)), /** @type {?} */ ((this.urlTree.fragment)), {}, PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {}); const /** @type {?} */ rootNode = new TreeNode(root, children); const /** @type {?} */ routeState = new RouterStateSnapshot(this.url, rootNode); this.inheritParamsAndData(routeState._root); return of(routeState); } catch (/** @type {?} */ e) { return new Observable((obs) => obs.error(e)); } } /** * @param {?} routeNode * @return {?} */ inheritParamsAndData(routeNode) { const /** @type {?} */ route = routeNode.value; const /** @type {?} */ i = inheritedParamsDataResolve(route, this.paramsInheritanceStrategy); route.params = Object.freeze(i.params); route.data = Object.freeze(i.data); routeNode.children.forEach(n => this.inheritParamsAndData(n)); } /** * @param {?} config * @param {?} segmentGroup * @param {?} outlet * @return {?} */ processSegmentGroup(config, segmentGroup, outlet) { if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) { return this.processChildren(config, segmentGroup); } return this.processSegment(config, segmentGroup, segmentGroup.segments, outlet); } /** * @param {?} config * @param {?} segmentGroup * @return {?} */ processChildren(config, segmentGroup) { const /** @type {?} */ children = mapChildrenIntoArray(segmentGroup, (child, childOutlet) => this.processSegmentGroup(config, child, childOutlet)); checkOutletNameUniqueness(children); sortActivatedRouteSnapshots(children); return children; } /** * @param {?} config * @param {?} segmentGroup * @param {?} segments * @param {?} outlet * @return {?} */ processSegment(config, segmentGroup, segments, outlet) { for (const /** @type {?} */ r of config) { try { return this.processSegmentAgainstRoute(r, segmentGroup, segments, outlet); } catch (/** @type {?} */ e) { if (!(e instanceof NoMatch$1)) throw e; } } if (this.noLeftoversInUrl(segmentGroup, segments, outlet)) { return []; } throw new NoMatch$1(); } /** * @param {?} segmentGroup * @param {?} segments * @param {?} outlet * @return {?} */ noLeftoversInUrl(segmentGroup, segments, outlet) { return segments.length === 0 && !segmentGroup.children[outlet]; } /** * @param {?} route * @param {?} rawSegment * @param {?} segments * @param {?} outlet * @return {?} */ processSegmentAgainstRoute(route, rawSegment, segments, outlet) { if (route.redirectTo) throw new NoMatch$1(); if ((route.outlet || PRIMARY_OUTLET) !== outlet) throw new NoMatch$1(); let /** @type {?} */ snapshot; let /** @type {?} */ consumedSegments = []; let /** @type {?} */ rawSlicedSegments = []; if (route.path === '**') { const /** @type {?} */ params = segments.length > 0 ? /** @type {?} */ ((last$1(segments))).parameters : {}; snapshot = new ActivatedRouteSnapshot(segments, params, Object.freeze(Object.assign({}, this.urlTree.queryParams)), /** @type {?} */ ((this.urlTree.fragment)), getData(route), outlet, /** @type {?} */ ((route.component)), route, getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + segments.length, getResolve(route)); } else { const /** @type {?} */ result = match$1(rawSegment, route, segments); consumedSegments = result.consumedSegments; rawSlicedSegments = segments.slice(result.lastChild); snapshot = new ActivatedRouteSnapshot(consumedSegments, result.parameters, Object.freeze(Object.assign({}, this.urlTree.queryParams)), /** @type {?} */ ((this.urlTree.fragment)), getData(route), outlet, /** @type {?} */ ((route.component)), route, getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + consumedSegments.length, getResolve(route)); } const /** @type {?} */ childConfig = getChildConfig(route); const { segmentGroup, slicedSegments } = split$1(rawSegment, consumedSegments, rawSlicedSegments, childConfig); if (slicedSegments.length === 0 && segmentGroup.hasChildren()) { const /** @type {?} */ children = this.processChildren(childConfig, segmentGroup); return [new TreeNode(snapshot, children)]; } if (childConfig.length === 0 && slicedSegments.length === 0) { return [new TreeNode(snapshot, [])]; } const /** @type {?} */ children = this.processSegment(childConfig, segmentGroup, slicedSegments, PRIMARY_OUTLET); return [new TreeNode(snapshot, children)]; } } /** * @param {?} nodes * @return {?} */ function sortActivatedRouteSnapshots(nodes) { nodes.sort((a, b) => { if (a.value.outlet === PRIMARY_OUTLET) return -1; if (b.value.outlet === PRIMARY_OUTLET) return 1; return a.value.outlet.localeCompare(b.value.outlet); }); } /** * @param {?} route * @return {?} */ function getChildConfig(route) { if (route.children) { return route.children; } if (route.loadChildren) { return /** @type {?} */ ((route._loadedConfig)).routes; } return []; } /** * @param {?} segmentGroup * @param {?} route * @param {?} segments * @return {?} */ function match$1(segmentGroup, route, segments) { if (route.path === '') { if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) { throw new NoMatch$1(); } return { consumedSegments: [], lastChild: 0, parameters: {} }; } const /** @type {?} */ matcher = route.matcher || defaultUrlMatcher; const /** @type {?} */ res = matcher(segments, segmentGroup, route); if (!res) throw new NoMatch$1(); const /** @type {?} */ posParams = {}; forEach(/** @type {?} */ ((res.posParams)), (v, k) => { posParams[k] = v.path; }); const /** @type {?} */ parameters = res.consumed.length > 0 ? Object.assign({}, posParams, res.consumed[res.consumed.length - 1].parameters) : posParams; return { consumedSegments: res.consumed, lastChild: res.consumed.length, parameters }; } /** * @param {?} nodes * @return {?} */ function checkOutletNameUniqueness(nodes) { const /** @type {?} */ names = {}; nodes.forEach(n => { const /** @type {?} */ routeWithSameOutletName = names[n.value.outlet]; if (routeWithSameOutletName) { const /** @type {?} */ p = routeWithSameOutletName.url.map(s => s.toString()).join('/'); const /** @type {?} */ c = n.value.url.map(s => s.toString()).join('/'); throw new Error(`Two segments cannot have the same outlet name: '${p}' and '${c}'.`); } names[n.value.outlet] = n.value; }); } /** * @param {?} segmentGroup * @return {?} */ function getSourceSegmentGroup(segmentGroup) { let /** @type {?} */ s = segmentGroup; while (s._sourceSegment) { s = s._sourceSegment; } return s; } /** * @param {?} segmentGroup * @return {?} */ function getPathIndexShift(segmentGroup) { let /** @type {?} */ s = segmentGroup; let /** @type {?} */ res = (s._segmentIndexShift ? s._segmentIndexShift : 0); while (s._sourceSegment) { s = s._sourceSegment; res += (s._segmentIndexShift ? s._segmentIndexShift : 0); } return res - 1; } /** * @param {?} segmentGroup * @param {?} consumedSegments * @param {?} slicedSegments * @param {?} config * @return {?} */ function split$1(segmentGroup, consumedSegments, slicedSegments, config) { if (slicedSegments.length > 0 && containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) { const /** @type {?} */ s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptyPaths(segmentGroup, consumedSegments, config, new UrlSegmentGroup(slicedSegments, segmentGroup.children))); s._sourceSegment = segmentGroup; s._segmentIndexShift = consumedSegments.length; return { segmentGroup: s, slicedSegments: [] }; } if (slicedSegments.length === 0 && containsEmptyPathMatches(segmentGroup, slicedSegments, config)) { const /** @type {?} */ s = new UrlSegmentGroup(segmentGroup.segments, addEmptyPathsToChildrenIfNeeded(segmentGroup, slicedSegments, config, segmentGroup.children)); s._sourceSegment = segmentGroup; s._segmentIndexShift = consumedSegments.length; return { segmentGroup: s, slicedSegments }; } const /** @type {?} */ s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children); s._sourceSegment = segmentGroup; s._segmentIndexShift = consumedSegments.length; return { segmentGroup: s, slicedSegments }; } /** * @param {?} segmentGroup * @param {?} slicedSegments * @param {?} routes * @param {?} children * @return {?} */ function addEmptyPathsToChildrenIfNeeded(segmentGroup, slicedSegments, routes, children) { const /** @type {?} */ res = {}; for (const /** @type {?} */ r of routes) { if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet$1(r)]) { const /** @type {?} */ s = new UrlSegmentGroup([], {}); s._sourceSegment = segmentGroup; s._segmentIndexShift = segmentGroup.segments.length; res[getOutlet$1(r)] = s; } } return Object.assign({}, children, res); } /** * @param {?} segmentGroup * @param {?} consumedSegments * @param {?} routes * @param {?} primarySegment * @return {?} */ function createChildrenForEmptyPaths(segmentGroup, consumedSegments, routes, primarySegment) { const /** @type {?} */ res = {}; res[PRIMARY_OUTLET] = primarySegment; primarySegment._sourceSegment = segmentGroup; primarySegment._segmentIndexShift = consumedSegments.length; for (const /** @type {?} */ r of routes) { if (r.path === '' && getOutlet$1(r) !== PRIMARY_OUTLET) { const /** @type {?} */ s = new UrlSegmentGroup([], {}); s._sourceSegment = segmentGroup; s._segmentIndexShift = consumedSegments.length; res[getOutlet$1(r)] = s; } } return res; } /** * @param {?} segmentGroup * @param {?} slicedSegments * @param {?} routes * @return {?} */ function containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, routes) { return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r) && getOutlet$1(r) !== PRIMARY_OUTLET); } /** * @param {?} segmentGroup * @param {?} slicedSegments * @param {?} routes * @return {?} */ function containsEmptyPathMatches(segmentGroup, slicedSegments, routes) { return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r)); } /** * @param {?} segmentGroup * @param {?} slicedSegments * @param {?} r * @return {?} */ function emptyPathMatch(segmentGroup, slicedSegments, r) { if ((segmentGroup.hasChildren() || slicedSegments.length > 0) && r.pathMatch === 'full') { return false; } return r.path === '' && r.redirectTo === undefined; } /** * @param {?} route * @return {?} */ function getOutlet$1(route) { return route.outlet || PRIMARY_OUTLET; } /** * @param {?} route * @return {?} */ function getData(route) { return route.data || {}; } /** * @param {?} route * @return {?} */ function getResolve(route) { return route.resolve || {}; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ /** * \@description * * Provides a way to customize when activated routes get reused. * * \@experimental * @abstract */ class RouteReuseStrategy { } /** * Does not detach any subtrees. Reuses routes as long as their route config is the same. */ class DefaultRouteReuseStrategy { /** * @param {?} route * @return {?} */ shouldDetach(route) { return false; } /** * @param {?} route * @param {?} detachedTree * @return {?} */ store(route, detachedTree) { } /** * @param {?} route * @return {?} */ shouldAttach(route) { return false; } /** * @param {?} route * @return {?} */ retrieve(route) { return null; } /** * @param {?} future * @param {?} curr * @return {?} */ shouldReuseRoute(future, curr) { return future.routeConfig === curr.routeConfig; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * \@docsNotRequired * \@experimental */ const /** @type {?} */ ROUTES = new InjectionToken('ROUTES'); class RouterConfigLoader { /** * @param {?} loader * @param {?} compiler * @param {?=} onLoadStartListener * @param {?=} onLoadEndListener */ constructor(loader, compiler, onLoadStartListener, onLoadEndListener) { this.loader = loader; this.compiler = compiler; this.onLoadStartListener = onLoadStartListener; this.onLoadEndListener = onLoadEndListener; } /** * @param {?} parentInjector * @param {?} route * @return {?} */ load(parentInjector, route) { if (this.onLoadStartListener) { this.onLoadStartListener(route); } const /** @type {?} */ moduleFactory$ = this.loadModuleFactory(/** @type {?} */ ((route.loadChildren))); return moduleFactory$.pipe(map((factory) => { if (this.onLoadEndListener) { this.onLoadEndListener(route); } const /** @type {?} */ module = factory.create(parentInjector); return new LoadedRouterConfig(flatten(module.injector.get(ROUTES)).map(standardizeConfig), module); })); } /** * @param {?} loadChildren * @return {?} */ loadModuleFactory(loadChildren) { if (typeof loadChildren === 'string') { return from(this.loader.load(loadChildren)); } else { return wrapIntoObservable(loadChildren()).pipe(mergeMap((t) => { if (t instanceof NgModuleFactory) { return of(t); } else { return from(this.compiler.compileModuleAsync(t)); } })); } } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ /** * \@description * * Provides a way to migrate AngularJS applications to Angular. * * \@experimental * @abstract */ class UrlHandlingStrategy { } /** * \@experimental */ class DefaultUrlHandlingStrategy { /** * @param {?} url * @return {?} */ shouldProcessUrl(url) { return true; } /** * @param {?} url * @return {?} */ extract(url) { return url; } /** * @param {?} newUrlPart * @param {?} wholeUrl * @return {?} */ merge(newUrlPart, wholeUrl) { return newUrlPart; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @param {?} error * @return {?} */ function defaultErrorHandler(error) { throw error; } /** * @param {?} error * @param {?} urlSerializer * @param {?} url * @return {?} */ function defaultMalformedUriErrorHandler(error, urlSerializer, url) { return urlSerializer.parse('/'); } /** * \@internal * @param {?} snapshot * @return {?} */ function defaultRouterHook(snapshot) { return /** @type {?} */ (of(null)); } /** * \@description * * Provides the navigation and url manipulation capabilities. * * See `Routes` for more details and examples. * * \@ngModule RouterModule * * */ class Router { /** * Creates the router service. * @param {?} rootComponentType * @param {?} urlSerializer * @param {?} rootContexts * @param {?} location * @param {?} injector * @param {?} loader * @param {?} compiler * @param {?} config */ constructor(rootComponentType, urlSerializer, rootContexts, location, injector, loader, compiler, config) { this.rootComponentType = rootComponentType; this.urlSerializer = urlSerializer; this.rootContexts = rootContexts; this.location = location; this.config = config; this.navigations = new BehaviorSubject(/** @type {?} */ ((null))); this.navigationId = 0; this.events = new Subject(); /** * Error handler that is invoked when a navigation errors. * * See `ErrorHandler` for more information. */ this.errorHandler = defaultErrorHandler; /** * Malformed uri error handler is invoked when `Router.parseUrl(url)` throws an * error due to containing an invalid character. The most common case would be a `%` sign * that's not encoded and is not part of a percent encoded sequence. */ this.malformedUriErrorHandler = defaultMalformedUriErrorHandler; /** * Indicates if at least one navigation happened. */ this.navigated = false; this.lastSuccessfulId = -1; /** * Used by RouterModule. This allows us to * pause the navigation either before preactivation or after it. * \@internal */ this.hooks = { beforePreactivation: defaultRouterHook, afterPreactivation: defaultRouterHook }; /** * Extracts and merges URLs. Used for AngularJS to Angular migrations. */ this.urlHandlingStrategy = new DefaultUrlHandlingStrategy(); this.routeReuseStrategy = new DefaultRouteReuseStrategy(); /** * Define what the router should do if it receives a navigation request to the current URL. * By default, the router will ignore this navigation. However, this prevents features such * as a "refresh" button. Use this option to configure the behavior when navigating to the * current URL. Default is 'ignore'. */ this.onSameUrlNavigation = 'ignore'; /** * Defines how the router merges params, data and resolved data from parent to child * routes. Available options are: * * - `'emptyOnly'`, the default, only inherits parent params for path-less or component-less * routes. * - `'always'`, enables unconditional inheritance of parent params. */ this.paramsInheritanceStrategy = 'emptyOnly'; const /** @type {?} */ onLoadStart = (r) => this.triggerEvent(new RouteConfigLoadStart(r)); const /** @type {?} */ onLoadEnd = (r) => this.triggerEvent(new RouteConfigLoadEnd(r)); this.ngModule = injector.get(NgModuleRef); this.resetConfig(config); this.currentUrlTree = createEmptyUrlTree(); this.rawUrlTree = this.currentUrlTree; this.configLoader = new RouterConfigLoader(loader, compiler, onLoadStart, onLoadEnd); this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType); this.processNavigations(); } /** * \@internal * TODO: this should be removed once the constructor of the router made internal * @param {?} rootComponentType * @return {?} */ resetRootComponentType(rootComponentType) { this.rootComponentType = rootComponentType; // TODO: vsavkin router 4.0 should make the root component set to null // this will simplify the lifecycle of the router. this.routerState.root.component = this.rootComponentType; } /** * Sets up the location change listener and performs the initial navigation. * @return {?} */ initialNavigation() { this.setUpLocationChangeListener(); if (this.navigationId === 0) { this.navigateByUrl(this.location.path(true), { replaceUrl: true }); } } /** * Sets up the location change listener. * @return {?} */ setUpLocationChangeListener() { // Don't need to use Zone.wrap any more, because zone.js // already patch onPopState, so location change callback will // run into ngZone if (!this.locationSubscription) { this.locationSubscription = /** @type {?} */ (this.location.subscribe((change) => { let /** @type {?} */ rawUrlTree = this.parseUrl(change['url']); const /** @type {?} */ source = change['type'] === 'popstate' ? 'popstate' : 'hashchange'; const /** @type {?} */ state = change.state && change.state.navigationId ? { navigationId: change.state.navigationId } : null; setTimeout(() => { this.scheduleNavigation(rawUrlTree, source, state, { replaceUrl: true }); }, 0); })); } } /** * The current url * @return {?} */ get url() { return this.serializeUrl(this.currentUrlTree); } /** * \@internal * @param {?} e * @return {?} */ triggerEvent(e) { (/** @type {?} */ (this.events)).next(e); } /** * Resets the configuration used for navigation and generating links. * * ### Usage * * ``` * router.resetConfig([ * { path: 'team/:id', component: TeamCmp, children: [ * { path: 'simple', component: SimpleCmp }, * { path: 'user/:name', component: UserCmp } * ]} * ]); * ``` * @param {?} config * @return {?} */ resetConfig(config) { validateConfig(config); this.config = config.map(standardizeConfig); this.navigated = false; this.lastSuccessfulId = -1; } /** * \@docsNotRequired * @return {?} */ ngOnDestroy() { this.dispose(); } /** * Disposes of the router * @return {?} */ dispose() { if (this.locationSubscription) { this.locationSubscription.unsubscribe(); this.locationSubscription = /** @type {?} */ ((null)); } } /** * Applies an array of commands to the current url tree and creates a new url tree. * * When given an activate route, applies the given commands starting from the route. * When not given a route, applies the given command starting from the root. * * ### Usage * * ``` * // create /team/33/user/11 * router.createUrlTree(['/team', 33, 'user', 11]); * * // create /team/33;expand=true/user/11 * router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]); * * // you can collapse static segments like this (this works only with the first passed-in value): * router.createUrlTree(['/team/33/user', userId]); * * // If the first segment can contain slashes, and you do not want the router to split it, you * // can do the following: * * router.createUrlTree([{segmentPath: '/one/two'}]); * * // create /team/33/(user/11//right:chat) * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]); * * // remove the right secondary node * router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: null}}]); * * // assuming the current url is `/team/33/user/11` and the route points to `user/11` * * // navigate to /team/33/user/11/details * router.createUrlTree(['details'], {relativeTo: route}); * * // navigate to /team/33/user/22 * router.createUrlTree(['../22'], {relativeTo: route}); * * // navigate to /team/44/user/22 * router.createUrlTree(['../../team/44/user/22'], {relativeTo: route}); * ``` * @param {?} commands * @param {?=} navigationExtras * @return {?} */ createUrlTree(commands, navigationExtras = {}) { const { relativeTo, queryParams, fragment, preserveQueryParams, queryParamsHandling, preserveFragment } = navigationExtras; if (isDevMode() && preserveQueryParams && /** @type {?} */ (console) && /** @type {?} */ (console.warn)) { console.warn('preserveQueryParams is deprecated, use queryParamsHandling instead.'); } const /** @type {?} */ a = relativeTo || this.routerState.root; const /** @type {?} */ f = preserveFragment ? this.currentUrlTree.fragment : fragment; let /** @type {?} */ q = null; if (queryParamsHandling) { switch (queryParamsHandling) { case 'merge': q = Object.assign({}, this.currentUrlTree.queryParams, queryParams); break; case 'preserve': q = this.currentUrlTree.queryParams; break; default: q = queryParams || null; } } else { q = preserveQueryParams ? this.currentUrlTree.queryParams : queryParams || null; } if (q !== null) { q = this.removeEmptyProps(q); } return createUrlTree(a, this.currentUrlTree, commands, /** @type {?} */ ((q)), /** @type {?} */ ((f))); } /** * Navigate based on the provided url. This navigation is always absolute. * * Returns a promise that: * - resolves to 'true' when navigation succeeds, * - resolves to 'false' when navigation fails, * - is rejected when an error happens. * * ### Usage * * ``` * router.navigateByUrl("/team/33/user/11"); * * // Navigate without updating the URL * router.navigateByUrl("/team/33/user/11", { skipLocationChange: true }); * ``` * * In opposite to `navigate`, `navigateByUrl` takes a whole URL * and does not apply any delta to the current one. * @param {?} url * @param {?=} extras * @return {?} */ navigateByUrl(url, extras = { skipLocationChange: false }) { const /** @type {?} */ urlTree = url instanceof UrlTree ? url : this.parseUrl(url); const /** @type {?} */ mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree); return this.scheduleNavigation(mergedTree, 'imperative', null, extras); } /** * Navigate based on the provided array of commands and a starting point. * If no starting route is provided, the navigation is absolute. * * Returns a promise that: * - resolves to 'true' when navigation succeeds, * - resolves to 'false' when navigation fails, * - is rejected when an error happens. * * ### Usage * * ``` * router.navigate(['team', 33, 'user', 11], {relativeTo: route}); * * // Navigate without updating the URL * router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true}); * ``` * * In opposite to `navigateByUrl`, `navigate` always takes a delta that is applied to the current * URL. * @param {?} commands * @param {?=} extras * @return {?} */ navigate(commands, extras = { skipLocationChange: false }) { validateCommands(commands); return this.navigateByUrl(this.createUrlTree(commands, extras), extras); } /** * Serializes a `UrlTree` into a string * @param {?} url * @return {?} */ serializeUrl(url) { return this.urlSerializer.serialize(url); } /** * Parses a string into a `UrlTree` * @param {?} url * @return {?} */ parseUrl(url) { let /** @type {?} */ urlTree; try { urlTree = this.urlSerializer.parse(url); } catch (/** @type {?} */ e) { urlTree = this.malformedUriErrorHandler(e, this.urlSerializer, url); } return urlTree; } /** * Returns whether the url is activated * @param {?} url * @param {?} exact * @return {?} */ isActive(url, exact) { if (url instanceof UrlTree) { return containsTree(this.currentUrlTree, url, exact); } const /** @type {?} */ urlTree = this.parseUrl(url); return containsTree(this.currentUrlTree, urlTree, exact); } /** * @param {?} params * @return {?} */ removeEmptyProps(params) { return Object.keys(params).reduce((result, key) => { const /** @type {?} */ value = params[key]; if (value !== null && value !== undefined) { result[key] = value; } return result; }, {}); } /** * @return {?} */ processNavigations() { this.navigations .pipe(concatMap((nav) => { if (nav) { this.executeScheduledNavigation(nav); // a failed navigation should not stop the router from processing // further navigations => the catch return nav.promise.catch(() => { }); } else { return /** @type {?} */ (of(null)); } })) .subscribe(() => { }); } /** * @param {?} rawUrl * @param {?} source * @param {?} state * @param {?} extras * @return {?} */ scheduleNavigation(rawUrl, source, state, extras) { const /** @type {?} */ lastNavigation = this.navigations.value; // If the user triggers a navigation imperatively (e.g., by using navigateByUrl), // and that navigation results in 'replaceState' that leads to the same URL, // we should skip those. if (lastNavigation && source !== 'imperative' && lastNavigation.source === 'imperative' && lastNavigation.rawUrl.toString() === rawUrl.toString()) { return Promise.resolve(true); // return value is not used } // Because of a bug in IE and Edge, the location class fires two events (popstate and // hashchange) every single time. The second one should be ignored. Otherwise, the URL will // flicker. Handles the case when a popstate was emitted first. if (lastNavigation && source == 'hashchange' && lastNavigation.source === 'popstate' && lastNavigation.rawUrl.toString() === rawUrl.toString()) { return Promise.resolve(true); // return value is not used } // Because of a bug in IE and Edge, the location class fires two events (popstate and // hashchange) every single time. The second one should be ignored. Otherwise, the URL will // flicker. Handles the case when a hashchange was emitted first. if (lastNavigation && source == 'popstate' && lastNavigation.source === 'hashchange' && lastNavigation.rawUrl.toString() === rawUrl.toString()) { return Promise.resolve(true); // return value is not used } let /** @type {?} */ resolve = null; let /** @type {?} */ reject = null; const /** @type {?} */ promise = new Promise((res, rej) => { resolve = res; reject = rej; }); const /** @type {?} */ id = ++this.navigationId; this.navigations.next({ id, source, state, rawUrl, extras, resolve, reject, promise }); // Make sure that the error is propagated even though `processNavigations` catch // handler does not rethrow return promise.catch((e) => Promise.reject(e)); } /** * @param {?} __0 * @return {?} */ executeScheduledNavigation({ id, rawUrl, extras, resolve, reject, source, state }) { const /** @type {?} */ url = this.urlHandlingStrategy.extract(rawUrl); const /** @type {?} */ urlTransition = !this.navigated || url.toString() !== this.currentUrlTree.toString(); if ((this.onSameUrlNavigation === 'reload' ? true : urlTransition) && this.urlHandlingStrategy.shouldProcessUrl(rawUrl)) { (/** @type {?} */ (this.events)) .next(new NavigationStart(id, this.serializeUrl(url), source, state)); Promise.resolve() .then((_) => this.runNavigate(url, rawUrl, !!extras.skipLocationChange, !!extras.replaceUrl, id, null)) .then(resolve, reject); // we cannot process the current URL, but we could process the previous one => // we need to do some cleanup } else if (urlTransition && this.rawUrlTree && this.urlHandlingStrategy.shouldProcessUrl(this.rawUrlTree)) { (/** @type {?} */ (this.events)) .next(new NavigationStart(id, this.serializeUrl(url), source, state)); Promise.resolve() .then((_) => this.runNavigate(url, rawUrl, false, false, id, createEmptyState(url, this.rootComponentType).snapshot)) .then(resolve, reject); } else { this.rawUrlTree = rawUrl; resolve(null); } } /** * @param {?} url * @param {?} rawUrl * @param {?} skipLocationChange * @param {?} replaceUrl * @param {?} id * @param {?} precreatedState * @return {?} */ runNavigate(url, rawUrl, skipLocationChange, replaceUrl, id, precreatedState) { if (id !== this.navigationId) { (/** @type {?} */ (this.events)) .next(new NavigationCancel(id, this.serializeUrl(url), `Navigation ID ${id} is not equal to the current navigation id ${this.navigationId}`)); return Promise.resolve(false); } return new Promise((resolvePromise, rejectPromise) => { // create an observable of the url and route state snapshot // this operation do not result in any side effects let /** @type {?} */ urlAndSnapshot$; if (!precreatedState) { const /** @type {?} */ moduleInjector = this.ngModule.injector; const /** @type {?} */ redirectsApplied$ = applyRedirects(moduleInjector, this.configLoader, this.urlSerializer, url, this.config); urlAndSnapshot$ = redirectsApplied$.pipe(mergeMap((appliedUrl) => { return recognize(this.rootComponentType, this.config, appliedUrl, this.serializeUrl(appliedUrl), this.paramsInheritanceStrategy) .pipe(map((snapshot) => { (/** @type {?} */ (this.events)) .next(new RoutesRecognized(id, this.serializeUrl(url), this.serializeUrl(appliedUrl), snapshot)); return { appliedUrl, snapshot }; })); })); } else { urlAndSnapshot$ = of({ appliedUrl: url, snapshot: precreatedState }); } const /** @type {?} */ beforePreactivationDone$ = urlAndSnapshot$.pipe(mergeMap((p) => { if (typeof p === 'boolean') return of(p); return this.hooks.beforePreactivation(p.snapshot).pipe(map(() => p)); })); // run preactivation: guards and data resolvers let /** @type {?} */ preActivation; const /** @type {?} */ preactivationSetup$ = beforePreactivationDone$.pipe(map((p) => { if (typeof p === 'boolean') return p; const { appliedUrl, snapshot } = p; const /** @type {?} */ moduleInjector = this.ngModule.injector; preActivation = new PreActivation(snapshot, this.routerState.snapshot, moduleInjector, (evt) => this.triggerEvent(evt)); preActivation.initialize(this.rootContexts); return { appliedUrl, snapshot }; })); const /** @type {?} */ preactivationCheckGuards$ = preactivationSetup$.pipe(mergeMap((p) => { if (typeof p === 'boolean' || this.navigationId !== id) return of(false); const { appliedUrl, snapshot } = p; this.triggerEvent(new GuardsCheckStart(id, this.serializeUrl(url), this.serializeUrl(appliedUrl), snapshot)); return preActivation.checkGuards().pipe(map((shouldActivate) => { this.triggerEvent(new GuardsCheckEnd(id, this.serializeUrl(url), this.serializeUrl(appliedUrl), snapshot, shouldActivate)); return { appliedUrl: appliedUrl, snapshot: snapshot, shouldActivate: shouldActivate }; })); })); const /** @type {?} */ preactivationResolveData$ = preactivationCheckGuards$.pipe(mergeMap((p) => { if (typeof p === 'boolean' || this.navigationId !== id) return of(false); if (p.shouldActivate && preActivation.isActivating()) { this.triggerEvent(new ResolveStart(id, this.serializeUrl(url), this.serializeUrl(p.appliedUrl), p.snapshot)); return preActivation.resolveData(this.paramsInheritanceStrategy).pipe(map(() => { this.triggerEvent(new ResolveEnd(id, this.serializeUrl(url), this.serializeUrl(p.appliedUrl), p.snapshot)); return p; })); } else { return of(p); } })); const /** @type {?} */ preactivationDone$ = preactivationResolveData$.pipe(mergeMap((p) => { if (typeof p === 'boolean' || this.navigationId !== id) return of(false); return this.hooks.afterPreactivation(p.snapshot).pipe(map(() => p)); })); // create router state // this operation has side effects => route state is being affected const /** @type {?} */ routerState$ = preactivationDone$.pipe(map((p) => { if (typeof p === 'boolean' || this.navigationId !== id) return false; const { appliedUrl, snapshot, shouldActivate } = p; if (shouldActivate) { const /** @type {?} */ state = createRouterState(this.routeReuseStrategy, snapshot, this.routerState); return { appliedUrl, state, shouldActivate }; } else { return { appliedUrl, state: null, shouldActivate }; } })); this.activateRoutes(routerState$, this.routerState, this.currentUrlTree, id, url, rawUrl, skipLocationChange, replaceUrl, resolvePromise, rejectPromise); }); } /** * Performs the logic of activating routes. This is a synchronous process by default. While this * is a private method, it could be overridden to make activation asynchronous. * @param {?} state * @param {?} storedState * @param {?} storedUrl * @param {?} id * @param {?} url * @param {?} rawUrl * @param {?} skipLocationChange * @param {?} replaceUrl * @param {?} resolvePromise * @param {?} rejectPromise * @return {?} */ activateRoutes(state, storedState, storedUrl, id, url, rawUrl, skipLocationChange, replaceUrl, resolvePromise, rejectPromise) { // applied the new router state // this operation has side effects let /** @type {?} */ navigationIsSuccessful; state .forEach((p) => { if (typeof p === 'boolean' || !p.shouldActivate || id !== this.navigationId || !p.state) { navigationIsSuccessful = false; return; } const { appliedUrl, state } = p; this.currentUrlTree = appliedUrl; this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, rawUrl); (/** @type {?} */ (this)).routerState = state; if (!skipLocationChange) { const /** @type {?} */ path = this.urlSerializer.serialize(this.rawUrlTree); if (this.location.isCurrentPathEqualTo(path) || replaceUrl) { this.location.replaceState(path, '', { navigationId: id }); } else { this.location.go(path, '', { navigationId: id }); } } new ActivateRoutes(this.routeReuseStrategy, state, storedState, (evt) => this.triggerEvent(evt)) .activate(this.rootContexts); navigationIsSuccessful = true; }) .then(() => { if (navigationIsSuccessful) { this.navigated = true; this.lastSuccessfulId = id; (/** @type {?} */ (this.events)) .next(new NavigationEnd(id, this.serializeUrl(url), this.serializeUrl(this.currentUrlTree))); resolvePromise(true); } else { this.resetUrlToCurrentUrlTree(); (/** @type {?} */ (this.events)) .next(new NavigationCancel(id, this.serializeUrl(url), '')); resolvePromise(false); } }, (e) => { if (isNavigationCancelingError(e)) { this.navigated = true; this.resetStateAndUrl(storedState, storedUrl, rawUrl); (/** @type {?} */ (this.events)) .next(new NavigationCancel(id, this.serializeUrl(url), e.message)); resolvePromise(false); } else { this.resetStateAndUrl(storedState, storedUrl, rawUrl); (/** @type {?} */ (this.events)) .next(new NavigationError(id, this.serializeUrl(url), e)); try { resolvePromise(this.errorHandler(e)); } catch (/** @type {?} */ ee) { rejectPromise(ee); } } }); } /** * @param {?} storedState * @param {?} storedUrl * @param {?} rawUrl * @return {?} */ resetStateAndUrl(storedState, storedUrl, rawUrl) { (/** @type {?} */ (this)).routerState = storedState; this.currentUrlTree = storedUrl; this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, rawUrl); this.resetUrlToCurrentUrlTree(); } /** * @return {?} */ resetUrlToCurrentUrlTree() { this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', { navigationId: this.lastSuccessfulId }); } } class ActivateRoutes { /** * @param {?} routeReuseStrategy * @param {?} futureState * @param {?} currState * @param {?} forwardEvent */ constructor(routeReuseStrategy, futureState, currState, forwardEvent) { this.routeReuseStrategy = routeReuseStrategy; this.futureState = futureState; this.currState = currState; this.forwardEvent = forwardEvent; } /** * @param {?} parentContexts * @return {?} */ activate(parentContexts) { const /** @type {?} */ futureRoot = this.futureState._root; const /** @type {?} */ currRoot = this.currState ? this.currState._root : null; this.deactivateChildRoutes(futureRoot, currRoot, parentContexts); advanceActivatedRoute(this.futureState.root); this.activateChildRoutes(futureRoot, currRoot, parentContexts); } /** * @param {?} futureNode * @param {?} currNode * @param {?} contexts * @return {?} */ deactivateChildRoutes(futureNode, currNode, contexts) { const /** @type {?} */ children = nodeChildrenAsMap(currNode); // Recurse on the routes active in the future state to de-activate deeper children futureNode.children.forEach(futureChild => { const /** @type {?} */ childOutletName = futureChild.value.outlet; this.deactivateRoutes(futureChild, children[childOutletName], contexts); delete children[childOutletName]; }); // De-activate the routes that will not be re-used forEach(children, (v, childName) => { this.deactivateRouteAndItsChildren(v, contexts); }); } /** * @param {?} futureNode * @param {?} currNode * @param {?} parentContext * @return {?} */ deactivateRoutes(futureNode, currNode, parentContext) { const /** @type {?} */ future = futureNode.value; const /** @type {?} */ curr = currNode ? currNode.value : null; if (future === curr) { // Reusing the node, check to see if the children need to be de-activated if (future.component) { // If we have a normal route, we need to go through an outlet. const /** @type {?} */ context = parentContext.getContext(future.outlet); if (context) { this.deactivateChildRoutes(futureNode, currNode, context.children); } } else { // if we have a componentless route, we recurse but keep the same outlet map. this.deactivateChildRoutes(futureNode, currNode, parentContext); } } else { if (curr) { // Deactivate the current route which will not be re-used this.deactivateRouteAndItsChildren(currNode, parentContext); } } } /** * @param {?} route * @param {?} parentContexts * @return {?} */ deactivateRouteAndItsChildren(route, parentContexts) { if (this.routeReuseStrategy.shouldDetach(route.value.snapshot)) { this.detachAndStoreRouteSubtree(route, parentContexts); } else { this.deactivateRouteAndOutlet(route, parentContexts); } } /** * @param {?} route * @param {?} parentContexts * @return {?} */ detachAndStoreRouteSubtree(route, parentContexts) { const /** @type {?} */ context = parentContexts.getContext(route.value.outlet); if (context && context.outlet) { const /** @type {?} */ componentRef = context.outlet.detach(); const /** @type {?} */ contexts = context.children.onOutletDeactivated(); this.routeReuseStrategy.store(route.value.snapshot, { componentRef, route, contexts }); } } /** * @param {?} route * @param {?} parentContexts * @return {?} */ deactivateRouteAndOutlet(route, parentContexts) { const /** @type {?} */ context = parentContexts.getContext(route.value.outlet); if (context) { const /** @type {?} */ children = nodeChildrenAsMap(route); const /** @type {?} */ contexts = route.value.component ? context.children : parentContexts; forEach(children, (v, k) => this.deactivateRouteAndItsChildren(v, contexts)); if (context.outlet) { // Destroy the component context.outlet.deactivate(); // Destroy the contexts for all the outlets that were in the component context.children.onOutletDeactivated(); } } } /** * @param {?} futureNode * @param {?} currNode * @param {?} contexts * @return {?} */ activateChildRoutes(futureNode, currNode, contexts) { const /** @type {?} */ children = nodeChildrenAsMap(currNode); futureNode.children.forEach(c => { this.activateRoutes(c, children[c.value.outlet], contexts); this.forwardEvent(new ActivationEnd(c.value.snapshot)); }); if (futureNode.children.length) { this.forwardEvent(new ChildActivationEnd(futureNode.value.snapshot)); } } /** * @param {?} futureNode * @param {?} currNode * @param {?} parentContexts * @return {?} */ activateRoutes(futureNode, currNode, parentContexts) { const /** @type {?} */ future = futureNode.value; const /** @type {?} */ curr = currNode ? currNode.value : null; advanceActivatedRoute(future); // reusing the node if (future === curr) { if (future.component) { // If we have a normal route, we need to go through an outlet. const /** @type {?} */ context = parentContexts.getOrCreateContext(future.outlet); this.activateChildRoutes(futureNode, currNode, context.children); } else { // if we have a componentless route, we recurse but keep the same outlet map. this.activateChildRoutes(futureNode, currNode, parentContexts); } } else { if (future.component) { // if we have a normal route, we need to place the component into the outlet and recurse. const /** @type {?} */ context = parentContexts.getOrCreateContext(future.outlet); if (this.routeReuseStrategy.shouldAttach(future.snapshot)) { const /** @type {?} */ stored = (/** @type {?} */ (this.routeReuseStrategy.retrieve(future.snapshot))); this.routeReuseStrategy.store(future.snapshot, null); context.children.onOutletReAttached(stored.contexts); context.attachRef = stored.componentRef; context.route = stored.route.value; if (context.outlet) { // Attach right away when the outlet has already been instantiated // Otherwise attach from `RouterOutlet.ngOnInit` when it is instantiated context.outlet.attach(stored.componentRef, stored.route.value); } advanceActivatedRouteNodeAndItsChildren(stored.route); } else { const /** @type {?} */ config = parentLoadedConfig(future.snapshot); const /** @type {?} */ cmpFactoryResolver = config ? config.module.componentFactoryResolver : null; context.route = future; context.resolver = cmpFactoryResolver; if (context.outlet) { // Activate the outlet when it has already been instantiated // Otherwise it will get activated from its `ngOnInit` when instantiated context.outlet.activateWith(future, cmpFactoryResolver); } this.activateChildRoutes(futureNode, null, context.children); } } else { // if we have a componentless route, we recurse but keep the same outlet map. this.activateChildRoutes(futureNode, null, parentContexts); } } } } /** * @param {?} node * @return {?} */ function advanceActivatedRouteNodeAndItsChildren(node) { advanceActivatedRoute(node.value); node.children.forEach(advanceActivatedRouteNodeAndItsChildren); } /** * @param {?} snapshot * @return {?} */ function parentLoadedConfig(snapshot) { for (let /** @type {?} */ s = snapshot.parent; s; s = s.parent) { const /** @type {?} */ route = s.routeConfig; if (route && route._loadedConfig) return route._loadedConfig; if (route && route.component) return null; } return null; } /** * @param {?} commands * @return {?} */ function validateCommands(commands) { for (let /** @type {?} */ i = 0; i < commands.length; i++) { const /** @type {?} */ cmd = commands[i]; if (cmd == null) { throw new Error(`The requested path contains ${cmd} segment at index ${i}`); } } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * \@description * * Lets you link to specific routes in your app. * * Consider the following route configuration: * `[{ path: 'user/:name', component: UserCmp }]`. * When linking to this `user/:name` route, you use the `RouterLink` directive. * * If the link is static, you can use the directive as follows: * `link to user component` * * If you use dynamic values to generate the link, you can pass an array of path * segments, followed by the params for each segment. * * For instance `['/team', teamId, 'user', userName, {details: true}]` * means that we want to generate a link to `/team/11/user/bob;details=true`. * * Multiple static segments can be merged into one * (e.g., `['/team/11/user', userName, {details: true}]`). * * The first segment name can be prepended with `/`, `./`, or `../`: * * If the first segment begins with `/`, the router will look up the route from the root of the * app. * * If the first segment begins with `./`, or doesn't begin with a slash, the router will * instead look in the children of the current activated route. * * And if the first segment begins with `../`, the router will go up one level. * * You can set query params and fragment as follows: * * ``` * * link to user component * * ``` * RouterLink will use these to generate this link: `/user/bob#education?debug=true`. * * (Deprecated in v4.0.0 use `queryParamsHandling` instead) You can also tell the * directive to preserve the current query params and fragment: * * ``` * * link to user component * * ``` * * You can tell the directive to how to handle queryParams, available options are: * - `'merge'`: merge the queryParams into the current queryParams * - `'preserve'`: preserve the current queryParams * - default/`''`: use the queryParams only * * Same options for {\@link NavigationExtras#queryParamsHandling * NavigationExtras#queryParamsHandling}. * * ``` * * link to user component * * ``` * * The router link directive always treats the provided input as a delta to the current url. * * For instance, if the current url is `/user/(box//aux:team)`. * * Then the following link `Jim` will generate the link * `/user/(jim//aux:team)`. * * See {\@link Router#createUrlTree createUrlTree} for more information. * * \@ngModule RouterModule * * */ class RouterLink { /** * @param {?} router * @param {?} route * @param {?} tabIndex * @param {?} renderer * @param {?} el */ constructor(router, route, tabIndex, renderer, el) { this.router = router; this.route = route; this.commands = []; if (tabIndex == null) { renderer.setAttribute(el.nativeElement, 'tabindex', '0'); } } /** * @param {?} commands * @return {?} */ set routerLink(commands) { if (commands != null) { this.commands = Array.isArray(commands) ? commands : [commands]; } else { this.commands = []; } } /** * @deprecated 4.0.0 use `queryParamsHandling` instead. * @param {?} value * @return {?} */ set preserveQueryParams(value) { if (isDevMode() && /** @type {?} */ (console) && /** @type {?} */ (console.warn)) { console.warn('preserveQueryParams is deprecated!, use queryParamsHandling instead.'); } this.preserve = value; } /** * @return {?} */ onClick() { const /** @type {?} */ extras = { skipLocationChange: attrBoolValue(this.skipLocationChange), replaceUrl: attrBoolValue(this.replaceUrl), }; this.router.navigateByUrl(this.urlTree, extras); return true; } /** * @return {?} */ get urlTree() { return this.router.createUrlTree(this.commands, { relativeTo: this.route, queryParams: this.queryParams, fragment: this.fragment, preserveQueryParams: attrBoolValue(this.preserve), queryParamsHandling: this.queryParamsHandling, preserveFragment: attrBoolValue(this.preserveFragment), }); } } RouterLink.decorators = [ { type: Directive, args: [{ selector: ':not(a)[routerLink]' },] } ]; /** @nocollapse */ RouterLink.ctorParameters = () => [ { type: Router }, { type: ActivatedRoute }, { type: String, decorators: [{ type: Attribute, args: ['tabindex',] }] }, { type: Renderer2 }, { type: ElementRef } ]; RouterLink.propDecorators = { queryParams: [{ type: Input }], fragment: [{ type: Input }], queryParamsHandling: [{ type: Input }], preserveFragment: [{ type: Input }], skipLocationChange: [{ type: Input }], replaceUrl: [{ type: Input }], routerLink: [{ type: Input }], preserveQueryParams: [{ type: Input }], onClick: [{ type: HostListener, args: ['click',] }] }; /** * \@description * * Lets you link to specific routes in your app. * * See `RouterLink` for more information. * * \@ngModule RouterModule * * */ class RouterLinkWithHref { /** * @param {?} router * @param {?} route * @param {?} locationStrategy */ constructor(router, route, locationStrategy) { this.router = router; this.route = route; this.locationStrategy = locationStrategy; this.commands = []; this.subscription = router.events.subscribe((s) => { if (s instanceof NavigationEnd) { this.updateTargetUrlAndHref(); } }); } /** * @param {?} commands * @return {?} */ set routerLink(commands) { if (commands != null) { this.commands = Array.isArray(commands) ? commands : [commands]; } else { this.commands = []; } } /** * @param {?} value * @return {?} */ set preserveQueryParams(value) { if (isDevMode() && /** @type {?} */ (console) && /** @type {?} */ (console.warn)) { console.warn('preserveQueryParams is deprecated, use queryParamsHandling instead.'); } this.preserve = value; } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { this.updateTargetUrlAndHref(); } /** * @return {?} */ ngOnDestroy() { this.subscription.unsubscribe(); } /** * @param {?} button * @param {?} ctrlKey * @param {?} metaKey * @param {?} shiftKey * @return {?} */ onClick(button, ctrlKey, metaKey, shiftKey) { if (button !== 0 || ctrlKey || metaKey || shiftKey) { return true; } if (typeof this.target === 'string' && this.target != '_self') { return true; } const /** @type {?} */ extras = { skipLocationChange: attrBoolValue(this.skipLocationChange), replaceUrl: attrBoolValue(this.replaceUrl), }; this.router.navigateByUrl(this.urlTree, extras); return false; } /** * @return {?} */ updateTargetUrlAndHref() { this.href = this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(this.urlTree)); } /** * @return {?} */ get urlTree() { return this.router.createUrlTree(this.commands, { relativeTo: this.route, queryParams: this.queryParams, fragment: this.fragment, preserveQueryParams: attrBoolValue(this.preserve), queryParamsHandling: this.queryParamsHandling, preserveFragment: attrBoolValue(this.preserveFragment), }); } } RouterLinkWithHref.decorators = [ { type: Directive, args: [{ selector: 'a[routerLink]' },] } ]; /** @nocollapse */ RouterLinkWithHref.ctorParameters = () => [ { type: Router }, { type: ActivatedRoute }, { type: LocationStrategy } ]; RouterLinkWithHref.propDecorators = { target: [{ type: HostBinding, args: ['attr.target',] }, { type: Input }], queryParams: [{ type: Input }], fragment: [{ type: Input }], queryParamsHandling: [{ type: Input }], preserveFragment: [{ type: Input }], skipLocationChange: [{ type: Input }], replaceUrl: [{ type: Input }], href: [{ type: HostBinding }], routerLink: [{ type: Input }], preserveQueryParams: [{ type: Input }], onClick: [{ type: HostListener, args: ['click', ['$event.button', '$event.ctrlKey', '$event.metaKey', '$event.shiftKey'],] }] }; /** * @param {?} s * @return {?} */ function attrBoolValue(s) { return s === '' || !!s; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * * \@description * * Lets you add a CSS class to an element when the link's route becomes active. * * This directive lets you add a CSS class to an element when the link's route * becomes active. * * Consider the following example: * * ``` * Bob * ``` * * When the url is either '/user' or '/user/bob', the active-link class will * be added to the `a` tag. If the url changes, the class will be removed. * * You can set more than one class, as follows: * * ``` * Bob * Bob * ``` * * You can configure RouterLinkActive by passing `exact: true`. This will add the classes * only when the url matches the link exactly. * * ``` * Bob * ``` * * You can assign the RouterLinkActive instance to a template variable and directly check * the `isActive` status. * ``` * * Bob {{ rla.isActive ? '(already open)' : ''}} * * ``` * * Finally, you can apply the RouterLinkActive directive to an ancestor of a RouterLink. * * ``` *
* Jim * Bob *
* ``` * * This will set the active-link class on the div tag if the url is either '/user/jim' or * '/user/bob'. * * \@ngModule RouterModule * * */ class RouterLinkActive { /** * @param {?} router * @param {?} element * @param {?} renderer * @param {?} cdr */ constructor(router, element, renderer, cdr) { this.router = router; this.element = element; this.renderer = renderer; this.cdr = cdr; this.classes = []; this.isActive = false; this.routerLinkActiveOptions = { exact: false }; this.subscription = router.events.subscribe((s) => { if (s instanceof NavigationEnd) { this.update(); } }); } /** * @return {?} */ ngAfterContentInit() { this.links.changes.subscribe(_ => this.update()); this.linksWithHrefs.changes.subscribe(_ => this.update()); this.update(); } /** * @param {?} data * @return {?} */ set routerLinkActive(data) { const /** @type {?} */ classes = Array.isArray(data) ? data : data.split(' '); this.classes = classes.filter(c => !!c); } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { this.update(); } /** * @return {?} */ ngOnDestroy() { this.subscription.unsubscribe(); } /** * @return {?} */ update() { if (!this.links || !this.linksWithHrefs || !this.router.navigated) return; Promise.resolve().then(() => { const /** @type {?} */ hasActiveLinks = this.hasActiveLinks(); if (this.isActive !== hasActiveLinks) { (/** @type {?} */ (this)).isActive = hasActiveLinks; this.classes.forEach((c) => { if (hasActiveLinks) { this.renderer.addClass(this.element.nativeElement, c); } else { this.renderer.removeClass(this.element.nativeElement, c); } }); } }); } /** * @param {?} router * @return {?} */ isLinkActive(router) { return (link) => router.isActive(link.urlTree, this.routerLinkActiveOptions.exact); } /** * @return {?} */ hasActiveLinks() { return this.links.some(this.isLinkActive(this.router)) || this.linksWithHrefs.some(this.isLinkActive(this.router)); } } RouterLinkActive.decorators = [ { type: Directive, args: [{ selector: '[routerLinkActive]', exportAs: 'routerLinkActive', },] } ]; /** @nocollapse */ RouterLinkActive.ctorParameters = () => [ { type: Router }, { type: ElementRef }, { type: Renderer2 }, { type: ChangeDetectorRef } ]; RouterLinkActive.propDecorators = { links: [{ type: ContentChildren, args: [RouterLink, { descendants: true },] }], linksWithHrefs: [{ type: ContentChildren, args: [RouterLinkWithHref, { descendants: true },] }], routerLinkActiveOptions: [{ type: Input }], routerLinkActive: [{ type: Input }] }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @license * Copyright Google Inc. 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 */ /** * Store contextual information about a `RouterOutlet` * * */ class OutletContext { constructor() { this.outlet = null; this.route = null; this.resolver = null; this.children = new ChildrenOutletContexts(); this.attachRef = null; } } /** * Store contextual information about the children (= nested) `RouterOutlet` * * */ class ChildrenOutletContexts { constructor() { this.contexts = new Map(); } /** * Called when a `RouterOutlet` directive is instantiated * @param {?} childName * @param {?} outlet * @return {?} */ onChildOutletCreated(childName, outlet) { const /** @type {?} */ context = this.getOrCreateContext(childName); context.outlet = outlet; this.contexts.set(childName, context); } /** * Called when a `RouterOutlet` directive is destroyed. * We need to keep the context as the outlet could be destroyed inside a NgIf and might be * re-created later. * @param {?} childName * @return {?} */ onChildOutletDestroyed(childName) { const /** @type {?} */ context = this.getContext(childName); if (context) { context.outlet = null; } } /** * Called when the corresponding route is deactivated during navigation. * Because the component get destroyed, all children outlet are destroyed. * @return {?} */ onOutletDeactivated() { const /** @type {?} */ contexts = this.contexts; this.contexts = new Map(); return contexts; } /** * @param {?} contexts * @return {?} */ onOutletReAttached(contexts) { this.contexts = contexts; } /** * @param {?} childName * @return {?} */ getOrCreateContext(childName) { let /** @type {?} */ context = this.getContext(childName); if (!context) { context = new OutletContext(); this.contexts.set(childName, context); } return context; } /** * @param {?} childName * @return {?} */ getContext(childName) { return this.contexts.get(childName) || null; } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * \@description * * Acts as a placeholder that Angular dynamically fills based on the current router state. * * ``` * * * * ``` * * A router outlet will emit an activate event any time a new component is being instantiated, * and a deactivate event when it is being destroyed. * * ``` * * ``` * \@ngModule RouterModule * * */ class RouterOutlet { /** * @param {?} parentContexts * @param {?} location * @param {?} resolver * @param {?} name * @param {?} changeDetector */ constructor(parentContexts, location, resolver, name, changeDetector) { this.parentContexts = parentContexts; this.location = location; this.resolver = resolver; this.changeDetector = changeDetector; this.activated = null; this._activatedRoute = null; this.activateEvents = new EventEmitter(); this.deactivateEvents = new EventEmitter(); this.name = name || PRIMARY_OUTLET; parentContexts.onChildOutletCreated(this.name, this); } /** * @return {?} */ ngOnDestroy() { this.parentContexts.onChildOutletDestroyed(this.name); } /** * @return {?} */ ngOnInit() { if (!this.activated) { // If the outlet was not instantiated at the time the route got activated we need to populate // the outlet when it is initialized (ie inside a NgIf) const /** @type {?} */ context = this.parentContexts.getContext(this.name); if (context && context.route) { if (context.attachRef) { // `attachRef` is populated when there is an existing component to mount this.attach(context.attachRef, context.route); } else { // otherwise the component defined in the configuration is created this.activateWith(context.route, context.resolver || null); } } } } /** * @return {?} */ get isActivated() { return !!this.activated; } /** * @return {?} */ get component() { if (!this.activated) throw new Error('Outlet is not activated'); return this.activated.instance; } /** * @return {?} */ get activatedRoute() { if (!this.activated) throw new Error('Outlet is not activated'); return /** @type {?} */ (this._activatedRoute); } /** * @return {?} */ get activatedRouteData() { if (this._activatedRoute) { return this._activatedRoute.snapshot.data; } return {}; } /** * Called when the `RouteReuseStrategy` instructs to detach the subtree * @return {?} */ detach() { if (!this.activated) throw new Error('Outlet is not activated'); this.location.detach(); const /** @type {?} */ cmp = this.activated; this.activated = null; this._activatedRoute = null; return cmp; } /** * Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree * @param {?} ref * @param {?} activatedRoute * @return {?} */ attach(ref, activatedRoute) { this.activated = ref; this._activatedRoute = activatedRoute; this.location.insert(ref.hostView); } /** * @return {?} */ deactivate() { if (this.activated) { const /** @type {?} */ c = this.component; this.activated.destroy(); this.activated = null; this._activatedRoute = null; this.deactivateEvents.emit(c); } } /** * @param {?} activatedRoute * @param {?} resolver * @return {?} */ activateWith(activatedRoute, resolver) { if (this.isActivated) { throw new Error('Cannot activate an already activated outlet'); } this._activatedRoute = activatedRoute; const /** @type {?} */ snapshot = activatedRoute._futureSnapshot; const /** @type {?} */ component = /** @type {?} */ (/** @type {?} */ ((snapshot.routeConfig)).component); resolver = resolver || this.resolver; const /** @type {?} */ factory = resolver.resolveComponentFactory(component); const /** @type {?} */ childContexts = this.parentContexts.getOrCreateContext(this.name).children; const /** @type {?} */ injector = new OutletInjector(activatedRoute, childContexts, this.location.injector); this.activated = this.location.createComponent(factory, this.location.length, injector); // Calling `markForCheck` to make sure we will run the change detection when the // `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component. this.changeDetector.markForCheck(); this.activateEvents.emit(this.activated.instance); } } RouterOutlet.decorators = [ { type: Directive, args: [{ selector: 'router-outlet', exportAs: 'outlet' },] } ]; /** @nocollapse */ RouterOutlet.ctorParameters = () => [ { type: ChildrenOutletContexts }, { type: ViewContainerRef }, { type: ComponentFactoryResolver }, { type: String, decorators: [{ type: Attribute, args: ['name',] }] }, { type: ChangeDetectorRef } ]; RouterOutlet.propDecorators = { activateEvents: [{ type: Output, args: ['activate',] }], deactivateEvents: [{ type: Output, args: ['deactivate',] }] }; class OutletInjector { /** * @param {?} route * @param {?} childContexts * @param {?} parent */ constructor(route, childContexts, parent) { this.route = route; this.childContexts = childContexts; this.parent = parent; } /** * @param {?} token * @param {?=} notFoundValue * @return {?} */ get(token, notFoundValue) { if (token === ActivatedRoute) { return this.route; } if (token === ChildrenOutletContexts) { return this.childContexts; } return this.parent.get(token, notFoundValue); } } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * \@description * * Provides a preloading strategy. * * \@experimental * @abstract */ class PreloadingStrategy { } /** * \@description * * Provides a preloading strategy that preloads all modules as quickly as possible. * * ``` * RouteModule.forRoot(ROUTES, {preloadingStrategy: PreloadAllModules}) * ``` * * \@experimental */ class PreloadAllModules { /** * @param {?} route * @param {?} fn * @return {?} */ preload(route, fn) { return fn().pipe(catchError(() => of(null))); } } /** * \@description * * Provides a preloading strategy that does not preload any modules. * * This strategy is enabled by default. * * \@experimental */ class NoPreloading { /** * @param {?} route * @param {?} fn * @return {?} */ preload(route, fn) { return of(null); } } /** * The preloader optimistically loads all router configurations to * make navigations into lazily-loaded sections of the application faster. * * The preloader runs in the background. When the router bootstraps, the preloader * starts listening to all navigation events. After every such event, the preloader * will check if any configurations can be loaded lazily. * * If a route is protected by `canLoad` guards, the preloaded will not load it. * * */ class RouterPreloader { /** * @param {?} router * @param {?} moduleLoader * @param {?} compiler * @param {?} injector * @param {?} preloadingStrategy */ constructor(router, moduleLoader, compiler, injector, preloadingStrategy) { this.router = router; this.injector = injector; this.preloadingStrategy = preloadingStrategy; const /** @type {?} */ onStartLoad = (r) => router.triggerEvent(new RouteConfigLoadStart(r)); const /** @type {?} */ onEndLoad = (r) => router.triggerEvent(new RouteConfigLoadEnd(r)); this.loader = new RouterConfigLoader(moduleLoader, compiler, onStartLoad, onEndLoad); } /** * @return {?} */ setUpPreloading() { this.subscription = this.router.events .pipe(filter((e) => e instanceof NavigationEnd), concatMap(() => this.preload())) .subscribe(() => { }); } /** * @return {?} */ preload() { const /** @type {?} */ ngModule = this.injector.get(NgModuleRef); return this.processRoutes(ngModule, this.router.config); } /** * @return {?} */ ngOnDestroy() { this.subscription.unsubscribe(); } /** * @param {?} ngModule * @param {?} routes * @return {?} */ processRoutes(ngModule, routes) { const /** @type {?} */ res = []; for (const /** @type {?} */ route of routes) { // we already have the config loaded, just recurse if (route.loadChildren && !route.canLoad && route._loadedConfig) { const /** @type {?} */ childConfig = route._loadedConfig; res.push(this.processRoutes(childConfig.module, childConfig.routes)); // no config loaded, fetch the config } else if (route.loadChildren && !route.canLoad) { res.push(this.preloadConfig(ngModule, route)); // recurse into children } else if (route.children) { res.push(this.processRoutes(ngModule, route.children)); } } return from(res).pipe(mergeAll(), map((_) => void 0)); } /** * @param {?} ngModule * @param {?} route * @return {?} */ preloadConfig(ngModule, route) { return this.preloadingStrategy.preload(route, () => { const /** @type {?} */ loaded$ = this.loader.load(ngModule.injector, route); return loaded$.pipe(mergeMap((config) => { route._loadedConfig = config; return this.processRoutes(config.module, config.routes); })); }); } } RouterPreloader.decorators = [ { type: Injectable } ]; /** @nocollapse */ RouterPreloader.ctorParameters = () => [ { type: Router }, { type: NgModuleFactoryLoader }, { type: Compiler }, { type: Injector }, { type: PreloadingStrategy } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * \@description * * Contains a list of directives * * */ const /** @type {?} */ ROUTER_DIRECTIVES = [RouterOutlet, RouterLink, RouterLinkWithHref, RouterLinkActive, EmptyOutletComponent]; /** * \@description * * Is used in DI to configure the router. * * */ const /** @type {?} */ ROUTER_CONFIGURATION = new InjectionToken('ROUTER_CONFIGURATION'); /** * \@docsNotRequired */ const /** @type {?} */ ROUTER_FORROOT_GUARD = new InjectionToken('ROUTER_FORROOT_GUARD'); const /** @type {?} */ ROUTER_PROVIDERS = [ Location, { provide: UrlSerializer, useClass: DefaultUrlSerializer }, { provide: Router, useFactory: setupRouter, deps: [ ApplicationRef, UrlSerializer, ChildrenOutletContexts, Location, Injector, NgModuleFactoryLoader, Compiler, ROUTES, ROUTER_CONFIGURATION, [UrlHandlingStrategy, new Optional()], [RouteReuseStrategy, new Optional()] ] }, ChildrenOutletContexts, { provide: ActivatedRoute, useFactory: rootRoute, deps: [Router] }, { provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader }, RouterPreloader, NoPreloading, PreloadAllModules, { provide: ROUTER_CONFIGURATION, useValue: { enableTracing: false } }, ]; /** * @return {?} */ function routerNgProbeToken() { return new NgProbeToken('Router', Router); } /** * \@usageNotes * * RouterModule can be imported multiple times: once per lazily-loaded bundle. * Since the router deals with a global shared resource--location, we cannot have * more than one router service active. * * That is why there are two ways to create the module: `RouterModule.forRoot` and * `RouterModule.forChild`. * * * `forRoot` creates a module that contains all the directives, the given routes, and the router * service itself. * * `forChild` creates a module that contains all the directives and the given routes, but does not * include the router service. * * When registered at the root, the module should be used as follows * * ``` * \@NgModule({ * imports: [RouterModule.forRoot(ROUTES)] * }) * class MyNgModule {} * ``` * * For submodules and lazy loaded submodules the module should be used as follows: * * ``` * \@NgModule({ * imports: [RouterModule.forChild(ROUTES)] * }) * class MyNgModule {} * ``` * * \@description * * Adds router directives and providers. * * Managing state transitions is one of the hardest parts of building applications. This is * especially true on the web, where you also need to ensure that the state is reflected in the URL. * In addition, we often want to split applications into multiple bundles and load them on demand. * Doing this transparently is not trivial. * * The Angular router solves these problems. Using the router, you can declaratively specify * application states, manage state transitions while taking care of the URL, and load bundles on * demand. * * [Read this developer guide](https://angular.io/docs/ts/latest/guide/router.html) to get an * overview of how the router should be used. * * */ class RouterModule { /** * @param {?} guard * @param {?} router */ constructor(guard, router) { } /** * Creates a module with all the router providers and directives. It also optionally sets up an * application listener to perform an initial navigation. * * Options (see `ExtraOptions`): * * `enableTracing` makes the router log all its internal events to the console. * * `useHash` enables the location strategy that uses the URL fragment instead of the history * API. * * `initialNavigation` disables the initial navigation. * * `errorHandler` provides a custom error handler. * * `preloadingStrategy` configures a preloading strategy (see `PreloadAllModules`). * * `onSameUrlNavigation` configures how the router handles navigation to the current URL. See * `ExtraOptions` for more details. * * `paramsInheritanceStrategy` defines how the router merges params, data and resolved data * from parent to child routes. * @param {?} routes * @param {?=} config * @return {?} */ static forRoot(routes, config) { return { ngModule: RouterModule, providers: [ ROUTER_PROVIDERS, provideRoutes(routes), { provide: ROUTER_FORROOT_GUARD, useFactory: provideForRootGuard, deps: [[Router, new Optional(), new SkipSelf()]] }, { provide: ROUTER_CONFIGURATION, useValue: config ? config : {} }, { provide: LocationStrategy, useFactory: provideLocationStrategy, deps: [ PlatformLocation, [new Inject(APP_BASE_HREF), new Optional()], ROUTER_CONFIGURATION ] }, { provide: PreloadingStrategy, useExisting: config && config.preloadingStrategy ? config.preloadingStrategy : NoPreloading }, { provide: NgProbeToken, multi: true, useFactory: routerNgProbeToken }, provideRouterInitializer(), ], }; } /** * Creates a module with all the router directives and a provider registering routes. * @param {?} routes * @return {?} */ static forChild(routes) { return { ngModule: RouterModule, providers: [provideRoutes(routes)] }; } } RouterModule.decorators = [ { type: NgModule, args: [{ declarations: ROUTER_DIRECTIVES, exports: ROUTER_DIRECTIVES, entryComponents: [EmptyOutletComponent] },] } ]; /** @nocollapse */ RouterModule.ctorParameters = () => [ { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [ROUTER_FORROOT_GUARD,] }] }, { type: Router, decorators: [{ type: Optional }] } ]; /** * @param {?} platformLocationStrategy * @param {?} baseHref * @param {?=} options * @return {?} */ function provideLocationStrategy(platformLocationStrategy, baseHref, options = {}) { return options.useHash ? new HashLocationStrategy(platformLocationStrategy, baseHref) : new PathLocationStrategy(platformLocationStrategy, baseHref); } /** * @param {?} router * @return {?} */ function provideForRootGuard(router) { if (router) { throw new Error(`RouterModule.forRoot() called twice. Lazy loaded modules should use RouterModule.forChild() instead.`); } return 'guarded'; } /** * \@description * * Registers routes. * * ### Example * * ``` * \@NgModule({ * imports: [RouterModule.forChild(ROUTES)], * providers: [provideRoutes(EXTRA_ROUTES)] * }) * class MyNgModule {} * ``` * * * @param {?} routes * @return {?} */ function provideRoutes(routes) { return [ { provide: ANALYZE_FOR_ENTRY_COMPONENTS, multi: true, useValue: routes }, { provide: ROUTES, multi: true, useValue: routes }, ]; } /** * @param {?} ref * @param {?} urlSerializer * @param {?} contexts * @param {?} location * @param {?} injector * @param {?} loader * @param {?} compiler * @param {?} config * @param {?=} opts * @param {?=} urlHandlingStrategy * @param {?=} routeReuseStrategy * @return {?} */ function setupRouter(ref, urlSerializer, contexts, location, injector, loader, compiler, config, opts = {}, urlHandlingStrategy, routeReuseStrategy) { const /** @type {?} */ router = new Router(null, urlSerializer, contexts, location, injector, loader, compiler, flatten(config)); if (urlHandlingStrategy) { router.urlHandlingStrategy = urlHandlingStrategy; } if (routeReuseStrategy) { router.routeReuseStrategy = routeReuseStrategy; } if (opts.errorHandler) { router.errorHandler = opts.errorHandler; } if (opts.malformedUriErrorHandler) { router.malformedUriErrorHandler = opts.malformedUriErrorHandler; } if (opts.enableTracing) { const /** @type {?} */ dom = ɵgetDOM(); router.events.subscribe((e) => { dom.logGroup(`Router Event: ${((/** @type {?} */ (e.constructor))).name}`); dom.log(e.toString()); dom.log(e); dom.logGroupEnd(); }); } if (opts.onSameUrlNavigation) { router.onSameUrlNavigation = opts.onSameUrlNavigation; } if (opts.paramsInheritanceStrategy) { router.paramsInheritanceStrategy = opts.paramsInheritanceStrategy; } return router; } /** * @param {?} router * @return {?} */ function rootRoute(router) { return router.routerState.root; } /** * To initialize the router properly we need to do in two steps: * * We need to start the navigation in a APP_INITIALIZER to block the bootstrap if * a resolver or a guards executes asynchronously. Second, we need to actually run * activation in a BOOTSTRAP_LISTENER. We utilize the afterPreactivation * hook provided by the router to do that. * * The router navigation starts, reaches the point when preactivation is done, and then * pauses. It waits for the hook to be resolved. We then resolve it only in a bootstrap listener. */ class RouterInitializer { /** * @param {?} injector */ constructor(injector) { this.injector = injector; this.initNavigation = false; this.resultOfPreactivationDone = new Subject(); } /** * @return {?} */ appInitializer() { const /** @type {?} */ p = this.injector.get(LOCATION_INITIALIZED, Promise.resolve(null)); return p.then(() => { let /** @type {?} */ resolve = /** @type {?} */ ((null)); const /** @type {?} */ res = new Promise(r => resolve = r); const /** @type {?} */ router = this.injector.get(Router); const /** @type {?} */ opts = this.injector.get(ROUTER_CONFIGURATION); if (this.isLegacyDisabled(opts) || this.isLegacyEnabled(opts)) { resolve(true); } else if (opts.initialNavigation === 'disabled') { router.setUpLocationChangeListener(); resolve(true); } else if (opts.initialNavigation === 'enabled') { router.hooks.afterPreactivation = () => { // only the initial navigation should be delayed if (!this.initNavigation) { this.initNavigation = true; resolve(true); return this.resultOfPreactivationDone; // subsequent navigations should not be delayed } else { return /** @type {?} */ (of(null)); } }; router.initialNavigation(); } else { throw new Error(`Invalid initialNavigation options: '${opts.initialNavigation}'`); } return res; }); } /** * @param {?} bootstrappedComponentRef * @return {?} */ bootstrapListener(bootstrappedComponentRef) { const /** @type {?} */ opts = this.injector.get(ROUTER_CONFIGURATION); const /** @type {?} */ preloader = this.injector.get(RouterPreloader); const /** @type {?} */ router = this.injector.get(Router); const /** @type {?} */ ref = this.injector.get(ApplicationRef); if (bootstrappedComponentRef !== ref.components[0]) { return; } if (this.isLegacyEnabled(opts)) { router.initialNavigation(); } else if (this.isLegacyDisabled(opts)) { router.setUpLocationChangeListener(); } preloader.setUpPreloading(); router.resetRootComponentType(ref.componentTypes[0]); this.resultOfPreactivationDone.next(/** @type {?} */ ((null))); this.resultOfPreactivationDone.complete(); } /** * @param {?} opts * @return {?} */ isLegacyEnabled(opts) { return opts.initialNavigation === 'legacy_enabled' || opts.initialNavigation === true || opts.initialNavigation === undefined; } /** * @param {?} opts * @return {?} */ isLegacyDisabled(opts) { return opts.initialNavigation === 'legacy_disabled' || opts.initialNavigation === false; } } RouterInitializer.decorators = [ { type: Injectable } ]; /** @nocollapse */ RouterInitializer.ctorParameters = () => [ { type: Injector } ]; /** * @param {?} r * @return {?} */ function getAppInitializer(r) { return r.appInitializer.bind(r); } /** * @param {?} r * @return {?} */ function getBootstrapListener(r) { return r.bootstrapListener.bind(r); } /** * A token for the router initializer that will be called after the app is bootstrapped. * * \@experimental */ const /** @type {?} */ ROUTER_INITIALIZER = new InjectionToken('Router Initializer'); /** * @return {?} */ function provideRouterInitializer() { return [ RouterInitializer, { provide: APP_INITIALIZER, multi: true, useFactory: getAppInitializer, deps: [RouterInitializer] }, { provide: ROUTER_INITIALIZER, useFactory: getBootstrapListener, deps: [RouterInitializer] }, { provide: APP_BOOTSTRAP_LISTENER, multi: true, useExisting: ROUTER_INITIALIZER }, ]; } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ VERSION = new Version('6.0.9'); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ // This file only reexports content of the `src` folder. Keep it that way. /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * Generated bundle index. Do not edit. */ export { ROUTER_FORROOT_GUARD as ɵangular_packages_router_router_a, RouterInitializer as ɵangular_packages_router_router_g, getAppInitializer as ɵangular_packages_router_router_h, getBootstrapListener as ɵangular_packages_router_router_i, provideForRootGuard as ɵangular_packages_router_router_d, provideLocationStrategy as ɵangular_packages_router_router_c, provideRouterInitializer as ɵangular_packages_router_router_j, rootRoute as ɵangular_packages_router_router_f, routerNgProbeToken as ɵangular_packages_router_router_b, setupRouter as ɵangular_packages_router_router_e, Tree as ɵangular_packages_router_router_k, TreeNode as ɵangular_packages_router_router_l, RouterLink, RouterLinkWithHref, RouterLinkActive, RouterOutlet, ActivationEnd, ActivationStart, ChildActivationEnd, ChildActivationStart, GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouterEvent, RoutesRecognized, RouteReuseStrategy, Router, ROUTES, ROUTER_CONFIGURATION, ROUTER_INITIALIZER, RouterModule, provideRoutes, ChildrenOutletContexts, OutletContext, NoPreloading, PreloadAllModules, PreloadingStrategy, RouterPreloader, ActivatedRoute, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot, PRIMARY_OUTLET, convertToParamMap, UrlHandlingStrategy, DefaultUrlSerializer, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, VERSION, EmptyOutletComponent as ɵEmptyOutletComponent, ROUTER_PROVIDERS as ɵROUTER_PROVIDERS, flatten as ɵflatten }; //# sourceMappingURL=router.js.map