You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

4674 lines
160 KiB

/**
* @license Angular v21.1.1
* (c) 2010-2026 Google LLC. https://angular.dev/
* License: MIT
*/
import { DOCUMENT, Location } from '@angular/common';
import * as i0 from '@angular/core';
import { ɵisPromise as _isPromise, computed, ɵRuntimeError as _RuntimeError, Injectable, InjectionToken, EventEmitter, input, inject, ViewContainerRef, ChangeDetectorRef, Directive, Input, Output, reflectComponentType, Component, runInInjectionContext, ɵisInjectable as _isInjectable, ɵisNgModule as _isNgModule, isStandalone, createEnvironmentInjector, Compiler, NgModuleFactory, ɵresolveComponentResources as _resolveComponentResources, afterNextRender, signal, EnvironmentInjector, DestroyRef, untracked, ɵConsole as _Console, ɵPendingTasksInternal as _PendingTasksInternal, ɵINTERNAL_APPLICATION_ERROR_HANDLER as _INTERNAL_APPLICATION_ERROR_HANDLER, ɵformatRuntimeError as _formatRuntimeError } from '@angular/core';
import { isObservable, from, of, BehaviorSubject, combineLatest, EmptyError, Observable, concat, defer, pipe, EMPTY, throwError, Subject, Subscription } from 'rxjs';
import { first, map, switchMap, take, startWith, filter, takeUntil, mergeMap, concatMap, tap, takeLast, catchError, finalize } from 'rxjs/operators';
import * as i1 from '@angular/platform-browser';
const PRIMARY_OUTLET = 'primary';
const RouteTitleKey = /* @__PURE__ */Symbol('RouteTitle');
class ParamsAsMap {
params;
constructor(params) {
this.params = params || {};
}
has(name) {
return Object.prototype.hasOwnProperty.call(this.params, name);
}
get(name) {
if (this.has(name)) {
const v = this.params[name];
return Array.isArray(v) ? v[0] : v;
}
return null;
}
getAll(name) {
if (this.has(name)) {
const v = this.params[name];
return Array.isArray(v) ? v : [v];
}
return [];
}
get keys() {
return Object.keys(this.params);
}
}
function convertToParamMap(params) {
return new ParamsAsMap(params);
}
function matchParts(routeParts, urlSegments, posParams) {
for (let i = 0; i < routeParts.length; i++) {
const part = routeParts[i];
const segment = urlSegments[i];
const isParameter = part[0] === ':';
if (isParameter) {
posParams[part.substring(1)] = segment;
} else if (part !== segment.path) {
return false;
}
}
return true;
}
function defaultUrlMatcher(segments, segmentGroup, route) {
const parts = route.path.split('/');
const wildcardIndex = parts.indexOf('**');
if (wildcardIndex === -1) {
if (parts.length > segments.length) {
return null;
}
if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || parts.length < segments.length)) {
return null;
}
const posParams = {};
const consumed = segments.slice(0, parts.length);
if (!matchParts(parts, consumed, posParams)) {
return null;
}
return {
consumed,
posParams
};
}
if (wildcardIndex !== parts.lastIndexOf('**')) {
return null;
}
const pre = parts.slice(0, wildcardIndex);
const post = parts.slice(wildcardIndex + 1);
if (pre.length + post.length > segments.length) {
return null;
}
if (route.pathMatch === 'full' && segmentGroup.hasChildren() && route.path !== '**') {
return null;
}
const posParams = {};
if (!matchParts(pre, segments.slice(0, pre.length), posParams)) {
return null;
}
if (!matchParts(post, segments.slice(segments.length - post.length), posParams)) {
return null;
}
return {
consumed: segments,
posParams
};
}
function firstValueFrom(source) {
return new Promise((resolve, reject) => {
source.pipe(first()).subscribe({
next: value => resolve(value),
error: err => reject(err)
});
});
}
function shallowEqualArrays(a, b) {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; ++i) {
if (!shallowEqual(a[i], b[i])) return false;
}
return true;
}
function shallowEqual(a, b) {
const k1 = a ? getDataKeys(a) : undefined;
const k2 = b ? getDataKeys(b) : undefined;
if (!k1 || !k2 || k1.length != k2.length) {
return false;
}
let key;
for (let i = 0; i < k1.length; i++) {
key = k1[i];
if (!equalArraysOrString(a[key], b[key])) {
return false;
}
}
return true;
}
function getDataKeys(obj) {
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
}
function equalArraysOrString(a, b) {
if (Array.isArray(a) && Array.isArray(b)) {
if (a.length !== b.length) return false;
const aSorted = [...a].sort();
const bSorted = [...b].sort();
return aSorted.every((val, index) => bSorted[index] === val);
} else {
return a === b;
}
}
function last(a) {
return a.length > 0 ? a[a.length - 1] : null;
}
function wrapIntoObservable(value) {
if (isObservable(value)) {
return value;
}
if (_isPromise(value)) {
return from(Promise.resolve(value));
}
return of(value);
}
function wrapIntoPromise(value) {
if (isObservable(value)) {
return firstValueFrom(value);
}
return Promise.resolve(value);
}
const pathCompareMap = {
'exact': equalSegmentGroups,
'subset': containsSegmentGroup
};
const paramCompareMap = {
'exact': equalParams,
'subset': containsParams,
'ignored': () => true
};
function isActive(url, router, matchOptions) {
const urlTree = url instanceof UrlTree ? url : router.parseUrl(url);
return computed(() => containsTree(router.lastSuccessfulNavigation()?.finalUrl ?? new UrlTree(), urlTree, matchOptions));
}
function containsTree(container, containee, options) {
return pathCompareMap[options.paths](container.root, containee.root, options.matrixParams) && paramCompareMap[options.queryParams](container.queryParams, containee.queryParams) && !(options.fragment === 'exact' && container.fragment !== containee.fragment);
}
function equalParams(container, containee) {
return shallowEqual(container, containee);
}
function equalSegmentGroups(container, containee, matrixParams) {
if (!equalPath(container.segments, containee.segments)) return false;
if (!matrixParamsMatch(container.segments, containee.segments, matrixParams)) {
return false;
}
if (container.numberOfChildren !== containee.numberOfChildren) return false;
for (const c in containee.children) {
if (!container.children[c]) return false;
if (!equalSegmentGroups(container.children[c], containee.children[c], matrixParams)) return false;
}
return true;
}
function containsParams(container, containee) {
return Object.keys(containee).length <= Object.keys(container).length && Object.keys(containee).every(key => equalArraysOrString(container[key], containee[key]));
}
function containsSegmentGroup(container, containee, matrixParams) {
return containsSegmentGroupHelper(container, containee, containee.segments, matrixParams);
}
function containsSegmentGroupHelper(container, containee, containeePaths, matrixParams) {
if (container.segments.length > containeePaths.length) {
const current = container.segments.slice(0, containeePaths.length);
if (!equalPath(current, containeePaths)) return false;
if (containee.hasChildren()) return false;
if (!matrixParamsMatch(current, containeePaths, matrixParams)) return false;
return true;
} else if (container.segments.length === containeePaths.length) {
if (!equalPath(container.segments, containeePaths)) return false;
if (!matrixParamsMatch(container.segments, containeePaths, matrixParams)) return false;
for (const c in containee.children) {
if (!container.children[c]) return false;
if (!containsSegmentGroup(container.children[c], containee.children[c], matrixParams)) {
return false;
}
}
return true;
} else {
const current = containeePaths.slice(0, container.segments.length);
const next = containeePaths.slice(container.segments.length);
if (!equalPath(container.segments, current)) return false;
if (!matrixParamsMatch(container.segments, current, matrixParams)) return false;
if (!container.children[PRIMARY_OUTLET]) return false;
return containsSegmentGroupHelper(container.children[PRIMARY_OUTLET], containee, next, matrixParams);
}
}
function matrixParamsMatch(containerPaths, containeePaths, options) {
return containeePaths.every((containeeSegment, i) => {
return paramCompareMap[options](containerPaths[i].parameters, containeeSegment.parameters);
});
}
class UrlTree {
root;
queryParams;
fragment;
_queryParamMap;
constructor(root = new UrlSegmentGroup([], {}), queryParams = {}, fragment = null) {
this.root = root;
this.queryParams = queryParams;
this.fragment = fragment;
if (typeof ngDevMode === 'undefined' || ngDevMode) {
if (root.segments.length > 0) {
throw new _RuntimeError(4015, 'The root `UrlSegmentGroup` should not contain `segments`. ' + 'Instead, these segments belong in the `children` so they can be associated with a named outlet.');
}
}
}
get queryParamMap() {
this._queryParamMap ??= convertToParamMap(this.queryParams);
return this._queryParamMap;
}
toString() {
return DEFAULT_SERIALIZER.serialize(this);
}
}
class UrlSegmentGroup {
segments;
children;
parent = null;
constructor(segments, children) {
this.segments = segments;
this.children = children;
Object.values(children).forEach(v => v.parent = this);
}
hasChildren() {
return this.numberOfChildren > 0;
}
get numberOfChildren() {
return Object.keys(this.children).length;
}
toString() {
return serializePaths(this);
}
}
class UrlSegment {
path;
parameters;
_parameterMap;
constructor(path, parameters) {
this.path = path;
this.parameters = parameters;
}
get parameterMap() {
this._parameterMap ??= convertToParamMap(this.parameters);
return this._parameterMap;
}
toString() {
return serializePath(this);
}
}
function equalSegments(as, bs) {
return equalPath(as, bs) && as.every((a, i) => shallowEqual(a.parameters, bs[i].parameters));
}
function equalPath(as, bs) {
if (as.length !== bs.length) return false;
return as.every((a, i) => a.path === bs[i].path);
}
function mapChildrenIntoArray(segment, fn) {
let res = [];
Object.entries(segment.children).forEach(([childOutlet, child]) => {
if (childOutlet === PRIMARY_OUTLET) {
res = res.concat(fn(child, childOutlet));
}
});
Object.entries(segment.children).forEach(([childOutlet, child]) => {
if (childOutlet !== PRIMARY_OUTLET) {
res = res.concat(fn(child, childOutlet));
}
});
return res;
}
class UrlSerializer {
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: UrlSerializer,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: UrlSerializer,
providedIn: 'root',
useFactory: () => new DefaultUrlSerializer()
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: UrlSerializer,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
useFactory: () => new DefaultUrlSerializer()
}]
}]
});
class DefaultUrlSerializer {
parse(url) {
const p = new UrlParser(url);
return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment());
}
serialize(tree) {
const segment = `/${serializeSegment(tree.root, true)}`;
const query = serializeQueryParams(tree.queryParams);
const fragment = typeof tree.fragment === `string` ? `#${encodeUriFragment(tree.fragment)}` : '';
return `${segment}${query}${fragment}`;
}
}
const DEFAULT_SERIALIZER = new DefaultUrlSerializer();
function serializePaths(segment) {
return segment.segments.map(p => serializePath(p)).join('/');
}
function serializeSegment(segment, root) {
if (!segment.hasChildren()) {
return serializePaths(segment);
}
if (root) {
const primary = segment.children[PRIMARY_OUTLET] ? serializeSegment(segment.children[PRIMARY_OUTLET], false) : '';
const children = [];
Object.entries(segment.children).forEach(([k, v]) => {
if (k !== PRIMARY_OUTLET) {
children.push(`${k}:${serializeSegment(v, false)}`);
}
});
return children.length > 0 ? `${primary}(${children.join('//')})` : primary;
} else {
const children = mapChildrenIntoArray(segment, (v, k) => {
if (k === PRIMARY_OUTLET) {
return [serializeSegment(segment.children[PRIMARY_OUTLET], false)];
}
return [`${k}:${serializeSegment(v, false)}`];
});
if (Object.keys(segment.children).length === 1 && segment.children[PRIMARY_OUTLET] != null) {
return `${serializePaths(segment)}/${children[0]}`;
}
return `${serializePaths(segment)}/(${children.join('//')})`;
}
}
function encodeUriString(s) {
return encodeURIComponent(s).replace(/%40/g, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',');
}
function encodeUriQuery(s) {
return encodeUriString(s).replace(/%3B/gi, ';');
}
function encodeUriFragment(s) {
return encodeURI(s);
}
function encodeUriSegment(s) {
return encodeUriString(s).replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/%26/gi, '&');
}
function decode(s) {
return decodeURIComponent(s);
}
function decodeQuery(s) {
return decode(s.replace(/\+/g, '%20'));
}
function serializePath(path) {
return `${encodeUriSegment(path.path)}${serializeMatrixParams(path.parameters)}`;
}
function serializeMatrixParams(params) {
return Object.entries(params).map(([key, value]) => `;${encodeUriSegment(key)}=${encodeUriSegment(value)}`).join('');
}
function serializeQueryParams(params) {
const strParams = Object.entries(params).map(([name, value]) => {
return Array.isArray(value) ? value.map(v => `${encodeUriQuery(name)}=${encodeUriQuery(v)}`).join('&') : `${encodeUriQuery(name)}=${encodeUriQuery(value)}`;
}).filter(s => s);
return strParams.length ? `?${strParams.join('&')}` : '';
}
const SEGMENT_RE = /^[^\/()?;#]+/;
function matchSegments(str) {
const match = str.match(SEGMENT_RE);
return match ? match[0] : '';
}
const MATRIX_PARAM_SEGMENT_RE = /^[^\/()?;=#]+/;
function matchMatrixKeySegments(str) {
const match = str.match(MATRIX_PARAM_SEGMENT_RE);
return match ? match[0] : '';
}
const QUERY_PARAM_RE = /^[^=?&#]+/;
function matchQueryParams(str) {
const match = str.match(QUERY_PARAM_RE);
return match ? match[0] : '';
}
const QUERY_PARAM_VALUE_RE = /^[^&#]+/;
function matchUrlQueryParamValue(str) {
const match = str.match(QUERY_PARAM_VALUE_RE);
return match ? match[0] : '';
}
class UrlParser {
url;
remaining;
constructor(url) {
this.url = url;
this.remaining = url;
}
parseRootSegment() {
this.consumeOptional('/');
if (this.remaining === '' || this.peekStartsWith('?') || this.peekStartsWith('#')) {
return new UrlSegmentGroup([], {});
}
return new UrlSegmentGroup([], this.parseChildren());
}
parseQueryParams() {
const params = {};
if (this.consumeOptional('?')) {
do {
this.parseQueryParam(params);
} while (this.consumeOptional('&'));
}
return params;
}
parseFragment() {
return this.consumeOptional('#') ? decodeURIComponent(this.remaining) : null;
}
parseChildren() {
if (this.remaining === '') {
return {};
}
this.consumeOptional('/');
const segments = [];
if (!this.peekStartsWith('(')) {
segments.push(this.parseSegment());
}
while (this.peekStartsWith('/') && !this.peekStartsWith('//') && !this.peekStartsWith('/(')) {
this.capture('/');
segments.push(this.parseSegment());
}
let children = {};
if (this.peekStartsWith('/(')) {
this.capture('/');
children = this.parseParens(true);
}
let 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;
}
parseSegment() {
const path = matchSegments(this.remaining);
if (path === '' && this.peekStartsWith(';')) {
throw new _RuntimeError(4009, (typeof ngDevMode === 'undefined' || ngDevMode) && `Empty path url segment cannot have parameters: '${this.remaining}'.`);
}
this.capture(path);
return new UrlSegment(decode(path), this.parseMatrixParams());
}
parseMatrixParams() {
const params = {};
while (this.consumeOptional(';')) {
this.parseParam(params);
}
return params;
}
parseParam(params) {
const key = matchMatrixKeySegments(this.remaining);
if (!key) {
return;
}
this.capture(key);
let value = '';
if (this.consumeOptional('=')) {
const valueMatch = matchSegments(this.remaining);
if (valueMatch) {
value = valueMatch;
this.capture(value);
}
}
params[decode(key)] = decode(value);
}
parseQueryParam(params) {
const key = matchQueryParams(this.remaining);
if (!key) {
return;
}
this.capture(key);
let value = '';
if (this.consumeOptional('=')) {
const valueMatch = matchUrlQueryParamValue(this.remaining);
if (valueMatch) {
value = valueMatch;
this.capture(value);
}
}
const decodedKey = decodeQuery(key);
const decodedVal = decodeQuery(value);
if (params.hasOwnProperty(decodedKey)) {
let currentVal = params[decodedKey];
if (!Array.isArray(currentVal)) {
currentVal = [currentVal];
params[decodedKey] = currentVal;
}
currentVal.push(decodedVal);
} else {
params[decodedKey] = decodedVal;
}
}
parseParens(allowPrimary) {
const segments = {};
this.capture('(');
while (!this.consumeOptional(')') && this.remaining.length > 0) {
const path = matchSegments(this.remaining);
const next = this.remaining[path.length];
if (next !== '/' && next !== ')' && next !== ';') {
throw new _RuntimeError(4010, (typeof ngDevMode === 'undefined' || ngDevMode) && `Cannot parse url '${this.url}'`);
}
let outletName;
if (path.indexOf(':') > -1) {
outletName = path.slice(0, path.indexOf(':'));
this.capture(outletName);
this.capture(':');
} else if (allowPrimary) {
outletName = PRIMARY_OUTLET;
}
const children = this.parseChildren();
segments[outletName ?? PRIMARY_OUTLET] = Object.keys(children).length === 1 && children[PRIMARY_OUTLET] ? children[PRIMARY_OUTLET] : new UrlSegmentGroup([], children);
this.consumeOptional('//');
}
return segments;
}
peekStartsWith(str) {
return this.remaining.startsWith(str);
}
consumeOptional(str) {
if (this.peekStartsWith(str)) {
this.remaining = this.remaining.substring(str.length);
return true;
}
return false;
}
capture(str) {
if (!this.consumeOptional(str)) {
throw new _RuntimeError(4011, (typeof ngDevMode === 'undefined' || ngDevMode) && `Expected "${str}".`);
}
}
}
function createRoot(rootCandidate) {
return rootCandidate.segments.length > 0 ? new UrlSegmentGroup([], {
[PRIMARY_OUTLET]: rootCandidate
}) : rootCandidate;
}
function squashSegmentGroup(segmentGroup) {
const newChildren = {};
for (const [childOutlet, child] of Object.entries(segmentGroup.children)) {
const childCandidate = squashSegmentGroup(child);
if (childOutlet === PRIMARY_OUTLET && childCandidate.segments.length === 0 && childCandidate.hasChildren()) {
for (const [grandChildOutlet, grandChild] of Object.entries(childCandidate.children)) {
newChildren[grandChildOutlet] = grandChild;
}
} else if (childCandidate.segments.length > 0 || childCandidate.hasChildren()) {
newChildren[childOutlet] = childCandidate;
}
}
const s = new UrlSegmentGroup(segmentGroup.segments, newChildren);
return mergeTrivialChildren(s);
}
function mergeTrivialChildren(s) {
if (s.numberOfChildren === 1 && s.children[PRIMARY_OUTLET]) {
const c = s.children[PRIMARY_OUTLET];
return new UrlSegmentGroup(s.segments.concat(c.segments), c.children);
}
return s;
}
function isUrlTree(v) {
return v instanceof UrlTree;
}
function createUrlTreeFromSnapshot(relativeTo, commands, queryParams = null, fragment = null, urlSerializer = new DefaultUrlSerializer()) {
const relativeToUrlSegmentGroup = createSegmentGroupFromRoute(relativeTo);
return createUrlTreeFromSegmentGroup(relativeToUrlSegmentGroup, commands, queryParams, fragment, urlSerializer);
}
function createSegmentGroupFromRoute(route) {
let targetGroup;
function createSegmentGroupFromRouteRecursive(currentRoute) {
const childOutlets = {};
for (const childSnapshot of currentRoute.children) {
const root = createSegmentGroupFromRouteRecursive(childSnapshot);
childOutlets[childSnapshot.outlet] = root;
}
const segmentGroup = new UrlSegmentGroup(currentRoute.url, childOutlets);
if (currentRoute === route) {
targetGroup = segmentGroup;
}
return segmentGroup;
}
const rootCandidate = createSegmentGroupFromRouteRecursive(route.root);
const rootSegmentGroup = createRoot(rootCandidate);
return targetGroup ?? rootSegmentGroup;
}
function createUrlTreeFromSegmentGroup(relativeTo, commands, queryParams, fragment, urlSerializer) {
let root = relativeTo;
while (root.parent) {
root = root.parent;
}
if (commands.length === 0) {
return tree(root, root, root, queryParams, fragment, urlSerializer);
}
const nav = computeNavigation(commands);
if (nav.toRoot()) {
return tree(root, root, new UrlSegmentGroup([], {}), queryParams, fragment, urlSerializer);
}
const position = findStartingPositionForTargetGroup(nav, root, relativeTo);
const newSegmentGroup = position.processChildren ? updateSegmentGroupChildren(position.segmentGroup, position.index, nav.commands) : updateSegmentGroup(position.segmentGroup, position.index, nav.commands);
return tree(root, position.segmentGroup, newSegmentGroup, queryParams, fragment, urlSerializer);
}
function isMatrixParams(command) {
return typeof command === 'object' && command != null && !command.outlets && !command.segmentPath;
}
function isCommandWithOutlets(command) {
return typeof command === 'object' && command != null && command.outlets;
}
function normalizeQueryParams(k, v, urlSerializer) {
k ||= 'ɵ';
const tree = new UrlTree();
tree.queryParams = {
[k]: v
};
return urlSerializer.parse(urlSerializer.serialize(tree)).queryParams[k];
}
function tree(oldRoot, oldSegmentGroup, newSegmentGroup, queryParams, fragment, urlSerializer) {
const qp = {};
for (const [key, value] of Object.entries(queryParams ?? {})) {
qp[key] = Array.isArray(value) ? value.map(v => normalizeQueryParams(key, v, urlSerializer)) : normalizeQueryParams(key, value, urlSerializer);
}
let rootCandidate;
if (oldRoot === oldSegmentGroup) {
rootCandidate = newSegmentGroup;
} else {
rootCandidate = replaceSegment(oldRoot, oldSegmentGroup, newSegmentGroup);
}
const newRoot = createRoot(squashSegmentGroup(rootCandidate));
return new UrlTree(newRoot, qp, fragment);
}
function replaceSegment(current, oldSegment, newSegment) {
const children = {};
Object.entries(current.children).forEach(([outletName, c]) => {
if (c === oldSegment) {
children[outletName] = newSegment;
} else {
children[outletName] = replaceSegment(c, oldSegment, newSegment);
}
});
return new UrlSegmentGroup(current.segments, children);
}
class Navigation {
isAbsolute;
numberOfDoubleDots;
commands;
constructor(isAbsolute, numberOfDoubleDots, commands) {
this.isAbsolute = isAbsolute;
this.numberOfDoubleDots = numberOfDoubleDots;
this.commands = commands;
if (isAbsolute && commands.length > 0 && isMatrixParams(commands[0])) {
throw new _RuntimeError(4003, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Root segment cannot have matrix parameters');
}
const cmdWithOutlet = commands.find(isCommandWithOutlets);
if (cmdWithOutlet && cmdWithOutlet !== last(commands)) {
throw new _RuntimeError(4004, (typeof ngDevMode === 'undefined' || ngDevMode) && '{outlets:{}} has to be the last command');
}
}
toRoot() {
return this.isAbsolute && this.commands.length === 1 && this.commands[0] == '/';
}
}
function computeNavigation(commands) {
if (typeof commands[0] === 'string' && commands.length === 1 && commands[0] === '/') {
return new Navigation(true, 0, commands);
}
let numberOfDoubleDots = 0;
let isAbsolute = false;
const res = commands.reduce((res, cmd, cmdIdx) => {
if (typeof cmd === 'object' && cmd != null) {
if (cmd.outlets) {
const outlets = {};
Object.entries(cmd.outlets).forEach(([name, commands]) => {
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 === '') {
isAbsolute = true;
} else if (urlPart === '..') {
numberOfDoubleDots++;
} else if (urlPart != '') {
res.push(urlPart);
}
});
return res;
}
return [...res, cmd];
}, []);
return new Navigation(isAbsolute, numberOfDoubleDots, res);
}
class Position {
segmentGroup;
processChildren;
index;
constructor(segmentGroup, processChildren, index) {
this.segmentGroup = segmentGroup;
this.processChildren = processChildren;
this.index = index;
}
}
function findStartingPositionForTargetGroup(nav, root, target) {
if (nav.isAbsolute) {
return new Position(root, true, 0);
}
if (!target) {
return new Position(root, false, NaN);
}
if (target.parent === null) {
return new Position(target, true, 0);
}
const modifier = isMatrixParams(nav.commands[0]) ? 0 : 1;
const index = target.segments.length - 1 + modifier;
return createPositionApplyingDoubleDots(target, index, nav.numberOfDoubleDots);
}
function createPositionApplyingDoubleDots(group, index, numberOfDoubleDots) {
let g = group;
let ci = index;
let dd = numberOfDoubleDots;
while (dd > ci) {
dd -= ci;
g = g.parent;
if (!g) {
throw new _RuntimeError(4005, (typeof ngDevMode === 'undefined' || ngDevMode) && "Invalid number of '../'");
}
ci = g.segments.length;
}
return new Position(g, false, ci - dd);
}
function getOutlets(commands) {
if (isCommandWithOutlets(commands[0])) {
return commands[0].outlets;
}
return {
[PRIMARY_OUTLET]: commands
};
}
function updateSegmentGroup(segmentGroup, startIndex, commands) {
segmentGroup ??= new UrlSegmentGroup([], {});
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
return updateSegmentGroupChildren(segmentGroup, startIndex, commands);
}
const m = prefixedWith(segmentGroup, startIndex, commands);
const slicedCommands = commands.slice(m.commandIndex);
if (m.match && m.pathIndex < segmentGroup.segments.length) {
const 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);
}
}
function updateSegmentGroupChildren(segmentGroup, startIndex, commands) {
if (commands.length === 0) {
return new UrlSegmentGroup(segmentGroup.segments, {});
} else {
const outlets = getOutlets(commands);
const children = {};
if (Object.keys(outlets).some(o => o !== PRIMARY_OUTLET) && segmentGroup.children[PRIMARY_OUTLET] && segmentGroup.numberOfChildren === 1 && segmentGroup.children[PRIMARY_OUTLET].segments.length === 0) {
const childrenOfEmptyChild = updateSegmentGroupChildren(segmentGroup.children[PRIMARY_OUTLET], startIndex, commands);
return new UrlSegmentGroup(segmentGroup.segments, childrenOfEmptyChild.children);
}
Object.entries(outlets).forEach(([outlet, commands]) => {
if (typeof commands === 'string') {
commands = [commands];
}
if (commands !== null) {
children[outlet] = updateSegmentGroup(segmentGroup.children[outlet], startIndex, commands);
}
});
Object.entries(segmentGroup.children).forEach(([childOutlet, child]) => {
if (outlets[childOutlet] === undefined) {
children[childOutlet] = child;
}
});
return new UrlSegmentGroup(segmentGroup.segments, children);
}
}
function prefixedWith(segmentGroup, startIndex, commands) {
let currentCommandIndex = 0;
let currentPathIndex = startIndex;
const noMatch = {
match: false,
pathIndex: 0,
commandIndex: 0
};
while (currentPathIndex < segmentGroup.segments.length) {
if (currentCommandIndex >= commands.length) return noMatch;
const path = segmentGroup.segments[currentPathIndex];
const command = commands[currentCommandIndex];
if (isCommandWithOutlets(command)) {
break;
}
const curr = `${command}`;
const 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
};
}
function createNewSegmentGroup(segmentGroup, startIndex, commands) {
const paths = segmentGroup.segments.slice(0, startIndex);
let i = 0;
while (i < commands.length) {
const command = commands[i];
if (isCommandWithOutlets(command)) {
const children = createNewSegmentChildren(command.outlets);
return new UrlSegmentGroup(paths, children);
}
if (i === 0 && isMatrixParams(commands[0])) {
const p = segmentGroup.segments[startIndex];
paths.push(new UrlSegment(p.path, stringify(commands[0])));
i++;
continue;
}
const curr = isCommandWithOutlets(command) ? command.outlets[PRIMARY_OUTLET] : `${command}`;
const 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, {});
}
function createNewSegmentChildren(outlets) {
const children = {};
Object.entries(outlets).forEach(([outlet, commands]) => {
if (typeof commands === 'string') {
commands = [commands];
}
if (commands !== null) {
children[outlet] = createNewSegmentGroup(new UrlSegmentGroup([], {}), 0, commands);
}
});
return children;
}
function stringify(params) {
const res = {};
Object.entries(params).forEach(([k, v]) => res[k] = `${v}`);
return res;
}
function compare(path, params, segment) {
return path == segment.path && shallowEqual(params, segment.parameters);
}
const IMPERATIVE_NAVIGATION = 'imperative';
var EventType;
(function (EventType) {
EventType[EventType["NavigationStart"] = 0] = "NavigationStart";
EventType[EventType["NavigationEnd"] = 1] = "NavigationEnd";
EventType[EventType["NavigationCancel"] = 2] = "NavigationCancel";
EventType[EventType["NavigationError"] = 3] = "NavigationError";
EventType[EventType["RoutesRecognized"] = 4] = "RoutesRecognized";
EventType[EventType["ResolveStart"] = 5] = "ResolveStart";
EventType[EventType["ResolveEnd"] = 6] = "ResolveEnd";
EventType[EventType["GuardsCheckStart"] = 7] = "GuardsCheckStart";
EventType[EventType["GuardsCheckEnd"] = 8] = "GuardsCheckEnd";
EventType[EventType["RouteConfigLoadStart"] = 9] = "RouteConfigLoadStart";
EventType[EventType["RouteConfigLoadEnd"] = 10] = "RouteConfigLoadEnd";
EventType[EventType["ChildActivationStart"] = 11] = "ChildActivationStart";
EventType[EventType["ChildActivationEnd"] = 12] = "ChildActivationEnd";
EventType[EventType["ActivationStart"] = 13] = "ActivationStart";
EventType[EventType["ActivationEnd"] = 14] = "ActivationEnd";
EventType[EventType["Scroll"] = 15] = "Scroll";
EventType[EventType["NavigationSkipped"] = 16] = "NavigationSkipped";
})(EventType || (EventType = {}));
class RouterEvent {
id;
url;
constructor(id, url) {
this.id = id;
this.url = url;
}
}
class NavigationStart extends RouterEvent {
type = EventType.NavigationStart;
navigationTrigger;
restoredState;
constructor(id, url, navigationTrigger = 'imperative', restoredState = null) {
super(id, url);
this.navigationTrigger = navigationTrigger;
this.restoredState = restoredState;
}
toString() {
return `NavigationStart(id: ${this.id}, url: '${this.url}')`;
}
}
class NavigationEnd extends RouterEvent {
urlAfterRedirects;
type = EventType.NavigationEnd;
constructor(id, url, urlAfterRedirects) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
}
toString() {
return `NavigationEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}')`;
}
}
var NavigationCancellationCode;
(function (NavigationCancellationCode) {
NavigationCancellationCode[NavigationCancellationCode["Redirect"] = 0] = "Redirect";
NavigationCancellationCode[NavigationCancellationCode["SupersededByNewNavigation"] = 1] = "SupersededByNewNavigation";
NavigationCancellationCode[NavigationCancellationCode["NoDataFromResolver"] = 2] = "NoDataFromResolver";
NavigationCancellationCode[NavigationCancellationCode["GuardRejected"] = 3] = "GuardRejected";
NavigationCancellationCode[NavigationCancellationCode["Aborted"] = 4] = "Aborted";
})(NavigationCancellationCode || (NavigationCancellationCode = {}));
var NavigationSkippedCode;
(function (NavigationSkippedCode) {
NavigationSkippedCode[NavigationSkippedCode["IgnoredSameUrlNavigation"] = 0] = "IgnoredSameUrlNavigation";
NavigationSkippedCode[NavigationSkippedCode["IgnoredByUrlHandlingStrategy"] = 1] = "IgnoredByUrlHandlingStrategy";
})(NavigationSkippedCode || (NavigationSkippedCode = {}));
class NavigationCancel extends RouterEvent {
reason;
code;
type = EventType.NavigationCancel;
constructor(id, url, reason, code) {
super(id, url);
this.reason = reason;
this.code = code;
}
toString() {
return `NavigationCancel(id: ${this.id}, url: '${this.url}')`;
}
}
function isRedirectingEvent(event) {
return event instanceof NavigationCancel && (event.code === NavigationCancellationCode.Redirect || event.code === NavigationCancellationCode.SupersededByNewNavigation);
}
class NavigationSkipped extends RouterEvent {
reason;
code;
type = EventType.NavigationSkipped;
constructor(id, url, reason, code) {
super(id, url);
this.reason = reason;
this.code = code;
}
}
class NavigationError extends RouterEvent {
error;
target;
type = EventType.NavigationError;
constructor(id, url, error, target) {
super(id, url);
this.error = error;
this.target = target;
}
toString() {
return `NavigationError(id: ${this.id}, url: '${this.url}', error: ${this.error})`;
}
}
class RoutesRecognized extends RouterEvent {
urlAfterRedirects;
state;
type = EventType.RoutesRecognized;
constructor(id, url, urlAfterRedirects, state) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
}
toString() {
return `RoutesRecognized(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
}
}
class GuardsCheckStart extends RouterEvent {
urlAfterRedirects;
state;
type = EventType.GuardsCheckStart;
constructor(id, url, urlAfterRedirects, state) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
}
toString() {
return `GuardsCheckStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
}
}
class GuardsCheckEnd extends RouterEvent {
urlAfterRedirects;
state;
shouldActivate;
type = EventType.GuardsCheckEnd;
constructor(id, url, urlAfterRedirects, state, shouldActivate) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
this.shouldActivate = shouldActivate;
}
toString() {
return `GuardsCheckEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state}, shouldActivate: ${this.shouldActivate})`;
}
}
class ResolveStart extends RouterEvent {
urlAfterRedirects;
state;
type = EventType.ResolveStart;
constructor(id, url, urlAfterRedirects, state) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
}
toString() {
return `ResolveStart(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
}
}
class ResolveEnd extends RouterEvent {
urlAfterRedirects;
state;
type = EventType.ResolveEnd;
constructor(id, url, urlAfterRedirects, state) {
super(id, url);
this.urlAfterRedirects = urlAfterRedirects;
this.state = state;
}
toString() {
return `ResolveEnd(id: ${this.id}, url: '${this.url}', urlAfterRedirects: '${this.urlAfterRedirects}', state: ${this.state})`;
}
}
class RouteConfigLoadStart {
route;
type = EventType.RouteConfigLoadStart;
constructor(route) {
this.route = route;
}
toString() {
return `RouteConfigLoadStart(path: ${this.route.path})`;
}
}
class RouteConfigLoadEnd {
route;
type = EventType.RouteConfigLoadEnd;
constructor(route) {
this.route = route;
}
toString() {
return `RouteConfigLoadEnd(path: ${this.route.path})`;
}
}
class ChildActivationStart {
snapshot;
type = EventType.ChildActivationStart;
constructor(snapshot) {
this.snapshot = snapshot;
}
toString() {
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
return `ChildActivationStart(path: '${path}')`;
}
}
class ChildActivationEnd {
snapshot;
type = EventType.ChildActivationEnd;
constructor(snapshot) {
this.snapshot = snapshot;
}
toString() {
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
return `ChildActivationEnd(path: '${path}')`;
}
}
class ActivationStart {
snapshot;
type = EventType.ActivationStart;
constructor(snapshot) {
this.snapshot = snapshot;
}
toString() {
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
return `ActivationStart(path: '${path}')`;
}
}
class ActivationEnd {
snapshot;
type = EventType.ActivationEnd;
constructor(snapshot) {
this.snapshot = snapshot;
}
toString() {
const path = this.snapshot.routeConfig && this.snapshot.routeConfig.path || '';
return `ActivationEnd(path: '${path}')`;
}
}
class Scroll {
routerEvent;
position;
anchor;
scrollBehavior;
type = EventType.Scroll;
constructor(routerEvent, position, anchor, scrollBehavior) {
this.routerEvent = routerEvent;
this.position = position;
this.anchor = anchor;
this.scrollBehavior = scrollBehavior;
}
toString() {
const pos = this.position ? `${this.position[0]}, ${this.position[1]}` : null;
return `Scroll(anchor: '${this.anchor}', position: '${pos}')`;
}
}
class BeforeActivateRoutes {}
class RedirectRequest {
url;
navigationBehaviorOptions;
constructor(url, navigationBehaviorOptions) {
this.url = url;
this.navigationBehaviorOptions = navigationBehaviorOptions;
}
}
function isPublicRouterEvent(e) {
return !(e instanceof BeforeActivateRoutes) && !(e instanceof RedirectRequest);
}
function stringifyEvent(routerEvent) {
switch (routerEvent.type) {
case EventType.ActivationEnd:
return `ActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
case EventType.ActivationStart:
return `ActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
case EventType.ChildActivationEnd:
return `ChildActivationEnd(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
case EventType.ChildActivationStart:
return `ChildActivationStart(path: '${routerEvent.snapshot.routeConfig?.path || ''}')`;
case EventType.GuardsCheckEnd:
return `GuardsCheckEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state}, shouldActivate: ${routerEvent.shouldActivate})`;
case EventType.GuardsCheckStart:
return `GuardsCheckStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
case EventType.NavigationCancel:
return `NavigationCancel(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
case EventType.NavigationSkipped:
return `NavigationSkipped(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
case EventType.NavigationEnd:
return `NavigationEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}')`;
case EventType.NavigationError:
return `NavigationError(id: ${routerEvent.id}, url: '${routerEvent.url}', error: ${routerEvent.error})`;
case EventType.NavigationStart:
return `NavigationStart(id: ${routerEvent.id}, url: '${routerEvent.url}')`;
case EventType.ResolveEnd:
return `ResolveEnd(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
case EventType.ResolveStart:
return `ResolveStart(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
case EventType.RouteConfigLoadEnd:
return `RouteConfigLoadEnd(path: ${routerEvent.route.path})`;
case EventType.RouteConfigLoadStart:
return `RouteConfigLoadStart(path: ${routerEvent.route.path})`;
case EventType.RoutesRecognized:
return `RoutesRecognized(id: ${routerEvent.id}, url: '${routerEvent.url}', urlAfterRedirects: '${routerEvent.urlAfterRedirects}', state: ${routerEvent.state})`;
case EventType.Scroll:
const pos = routerEvent.position ? `${routerEvent.position[0]}, ${routerEvent.position[1]}` : null;
return `Scroll(anchor: '${routerEvent.anchor}', position: '${pos}')`;
}
}
class OutletContext {
rootInjector;
outlet = null;
route = null;
children;
attachRef = null;
get injector() {
return this.route?.snapshot._environmentInjector ?? this.rootInjector;
}
constructor(rootInjector) {
this.rootInjector = rootInjector;
this.children = new ChildrenOutletContexts(this.rootInjector);
}
}
class ChildrenOutletContexts {
rootInjector;
contexts = new Map();
constructor(rootInjector) {
this.rootInjector = rootInjector;
}
onChildOutletCreated(childName, outlet) {
const context = this.getOrCreateContext(childName);
context.outlet = outlet;
this.contexts.set(childName, context);
}
onChildOutletDestroyed(childName) {
const context = this.getContext(childName);
if (context) {
context.outlet = null;
context.attachRef = null;
}
}
onOutletDeactivated() {
const contexts = this.contexts;
this.contexts = new Map();
return contexts;
}
onOutletReAttached(contexts) {
this.contexts = contexts;
}
getOrCreateContext(childName) {
let context = this.getContext(childName);
if (!context) {
context = new OutletContext(this.rootInjector);
this.contexts.set(childName, context);
}
return context;
}
getContext(childName) {
return this.contexts.get(childName) || null;
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: ChildrenOutletContexts,
deps: [{
token: i0.EnvironmentInjector
}],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: ChildrenOutletContexts,
providedIn: 'root'
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: ChildrenOutletContexts,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}],
ctorParameters: () => [{
type: i0.EnvironmentInjector
}]
});
class Tree {
_root;
constructor(root) {
this._root = root;
}
get root() {
return this._root.value;
}
parent(t) {
const p = this.pathFromRoot(t);
return p.length > 1 ? p[p.length - 2] : null;
}
children(t) {
const n = findNode(t, this._root);
return n ? n.children.map(t => t.value) : [];
}
firstChild(t) {
const n = findNode(t, this._root);
return n && n.children.length > 0 ? n.children[0].value : null;
}
siblings(t) {
const p = findPath(t, this._root);
if (p.length < 2) return [];
const c = p[p.length - 2].children.map(c => c.value);
return c.filter(cc => cc !== t);
}
pathFromRoot(t) {
return findPath(t, this._root).map(s => s.value);
}
}
function findNode(value, node) {
if (value === node.value) return node;
for (const child of node.children) {
const node = findNode(value, child);
if (node) return node;
}
return null;
}
function findPath(value, node) {
if (value === node.value) return [node];
for (const child of node.children) {
const path = findPath(value, child);
if (path.length) {
path.unshift(node);
return path;
}
}
return [];
}
class TreeNode {
value;
children;
constructor(value, children) {
this.value = value;
this.children = children;
}
toString() {
return `TreeNode(${this.value})`;
}
}
function nodeChildrenAsMap(node) {
const map = {};
if (node) {
node.children.forEach(child => map[child.value.outlet] = child);
}
return map;
}
class RouterState extends Tree {
snapshot;
constructor(root, snapshot) {
super(root);
this.snapshot = snapshot;
setRouterState(this, root);
}
toString() {
return this.snapshot.toString();
}
}
function createEmptyState(rootComponent, injector) {
const snapshot = createEmptyStateSnapshot(rootComponent, injector);
const emptyUrl = new BehaviorSubject([new UrlSegment('', {})]);
const emptyParams = new BehaviorSubject({});
const emptyData = new BehaviorSubject({});
const emptyQueryParams = new BehaviorSubject({});
const fragment = new BehaviorSubject('');
const activated = new ActivatedRoute(emptyUrl, emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, snapshot.root);
activated.snapshot = snapshot.root;
return new RouterState(new TreeNode(activated, []), snapshot);
}
function createEmptyStateSnapshot(rootComponent, injector) {
const emptyParams = {};
const emptyData = {};
const emptyQueryParams = {};
const fragment = '';
const activated = new ActivatedRouteSnapshot([], emptyParams, emptyQueryParams, fragment, emptyData, PRIMARY_OUTLET, rootComponent, null, {}, injector);
return new RouterStateSnapshot('', new TreeNode(activated, []));
}
class ActivatedRoute {
urlSubject;
paramsSubject;
queryParamsSubject;
fragmentSubject;
dataSubject;
outlet;
component;
snapshot;
_futureSnapshot;
_routerState;
_paramMap;
_queryParamMap;
title;
url;
params;
queryParams;
fragment;
data;
constructor(urlSubject, paramsSubject, queryParamsSubject, fragmentSubject, dataSubject, outlet, component, futureSnapshot) {
this.urlSubject = urlSubject;
this.paramsSubject = paramsSubject;
this.queryParamsSubject = queryParamsSubject;
this.fragmentSubject = fragmentSubject;
this.dataSubject = dataSubject;
this.outlet = outlet;
this.component = component;
this._futureSnapshot = futureSnapshot;
this.title = this.dataSubject?.pipe(map(d => d[RouteTitleKey])) ?? of(undefined);
this.url = urlSubject;
this.params = paramsSubject;
this.queryParams = queryParamsSubject;
this.fragment = fragmentSubject;
this.data = dataSubject;
}
get routeConfig() {
return this._futureSnapshot.routeConfig;
}
get root() {
return this._routerState.root;
}
get parent() {
return this._routerState.parent(this);
}
get firstChild() {
return this._routerState.firstChild(this);
}
get children() {
return this._routerState.children(this);
}
get pathFromRoot() {
return this._routerState.pathFromRoot(this);
}
get paramMap() {
this._paramMap ??= this.params.pipe(map(p => convertToParamMap(p)));
return this._paramMap;
}
get queryParamMap() {
this._queryParamMap ??= this.queryParams.pipe(map(p => convertToParamMap(p)));
return this._queryParamMap;
}
toString() {
return this.snapshot ? this.snapshot.toString() : `Future(${this._futureSnapshot})`;
}
}
function getInherited(route, parent, paramsInheritanceStrategy = 'emptyOnly') {
let inherited;
const {
routeConfig
} = route;
if (parent !== null && (paramsInheritanceStrategy === 'always' || routeConfig?.path === '' || !parent.component && !parent.routeConfig?.loadComponent)) {
inherited = {
params: {
...parent.params,
...route.params
},
data: {
...parent.data,
...route.data
},
resolve: {
...route.data,
...parent.data,
...routeConfig?.data,
...route._resolvedData
}
};
} else {
inherited = {
params: {
...route.params
},
data: {
...route.data
},
resolve: {
...route.data,
...(route._resolvedData ?? {})
}
};
}
if (routeConfig && hasStaticTitle(routeConfig)) {
inherited.resolve[RouteTitleKey] = routeConfig.title;
}
return inherited;
}
class ActivatedRouteSnapshot {
url;
params;
queryParams;
fragment;
data;
outlet;
component;
routeConfig;
_resolve;
_resolvedData;
_routerState;
_paramMap;
_queryParamMap;
_environmentInjector;
get title() {
return this.data?.[RouteTitleKey];
}
constructor(url, params, queryParams, fragment, data, outlet, component, routeConfig, resolve, environmentInjector) {
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._resolve = resolve;
this._environmentInjector = environmentInjector;
}
get root() {
return this._routerState.root;
}
get parent() {
return this._routerState.parent(this);
}
get firstChild() {
return this._routerState.firstChild(this);
}
get children() {
return this._routerState.children(this);
}
get pathFromRoot() {
return this._routerState.pathFromRoot(this);
}
get paramMap() {
this._paramMap ??= convertToParamMap(this.params);
return this._paramMap;
}
get queryParamMap() {
this._queryParamMap ??= convertToParamMap(this.queryParams);
return this._queryParamMap;
}
toString() {
const url = this.url.map(segment => segment.toString()).join('/');
const matched = this.routeConfig ? this.routeConfig.path : '';
return `Route(url:'${url}', path:'${matched}')`;
}
}
class RouterStateSnapshot extends Tree {
url;
constructor(url, root) {
super(root);
this.url = url;
setRouterState(this, root);
}
toString() {
return serializeNode(this._root);
}
}
function setRouterState(state, node) {
node.value._routerState = state;
node.children.forEach(c => setRouterState(state, c));
}
function serializeNode(node) {
const c = node.children.length > 0 ? ` { ${node.children.map(serializeNode).join(', ')} } ` : '';
return `${node.value}${c}`;
}
function advanceActivatedRoute(route) {
if (route.snapshot) {
const currentSnapshot = route.snapshot;
const nextSnapshot = route._futureSnapshot;
route.snapshot = nextSnapshot;
if (!shallowEqual(currentSnapshot.queryParams, nextSnapshot.queryParams)) {
route.queryParamsSubject.next(nextSnapshot.queryParams);
}
if (currentSnapshot.fragment !== nextSnapshot.fragment) {
route.fragmentSubject.next(nextSnapshot.fragment);
}
if (!shallowEqual(currentSnapshot.params, nextSnapshot.params)) {
route.paramsSubject.next(nextSnapshot.params);
}
if (!shallowEqualArrays(currentSnapshot.url, nextSnapshot.url)) {
route.urlSubject.next(nextSnapshot.url);
}
if (!shallowEqual(currentSnapshot.data, nextSnapshot.data)) {
route.dataSubject.next(nextSnapshot.data);
}
} else {
route.snapshot = route._futureSnapshot;
route.dataSubject.next(route._futureSnapshot.data);
}
}
function equalParamsAndUrlSegments(a, b) {
const equalUrlParams = shallowEqual(a.params, b.params) && equalSegments(a.url, b.url);
const parentsMismatch = !a.parent !== !b.parent;
return equalUrlParams && !parentsMismatch && (!a.parent || equalParamsAndUrlSegments(a.parent, b.parent));
}
function hasStaticTitle(config) {
return typeof config.title === 'string' || config.title === null;
}
const ROUTER_OUTLET_DATA = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'RouterOutlet data' : '');
class RouterOutlet {
activated = null;
get activatedComponentRef() {
return this.activated;
}
_activatedRoute = null;
name = PRIMARY_OUTLET;
activateEvents = new EventEmitter();
deactivateEvents = new EventEmitter();
attachEvents = new EventEmitter();
detachEvents = new EventEmitter();
routerOutletData = input(...(ngDevMode ? [undefined, {
debugName: "routerOutletData"
}] : []));
parentContexts = inject(ChildrenOutletContexts);
location = inject(ViewContainerRef);
changeDetector = inject(ChangeDetectorRef);
inputBinder = inject(INPUT_BINDER, {
optional: true
});
supportsBindingToComponentInputs = true;
ngOnChanges(changes) {
if (changes['name']) {
const {
firstChange,
previousValue
} = changes['name'];
if (firstChange) {
return;
}
if (this.isTrackedInParentContexts(previousValue)) {
this.deactivate();
this.parentContexts.onChildOutletDestroyed(previousValue);
}
this.initializeOutletWithName();
}
}
ngOnDestroy() {
if (this.isTrackedInParentContexts(this.name)) {
this.parentContexts.onChildOutletDestroyed(this.name);
}
this.inputBinder?.unsubscribeFromRouteData(this);
}
isTrackedInParentContexts(outletName) {
return this.parentContexts.getContext(outletName)?.outlet === this;
}
ngOnInit() {
this.initializeOutletWithName();
}
initializeOutletWithName() {
this.parentContexts.onChildOutletCreated(this.name, this);
if (this.activated) {
return;
}
const context = this.parentContexts.getContext(this.name);
if (context?.route) {
if (context.attachRef) {
this.attach(context.attachRef, context.route);
} else {
this.activateWith(context.route, context.injector);
}
}
}
get isActivated() {
return !!this.activated;
}
get component() {
if (!this.activated) throw new _RuntimeError(4012, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Outlet is not activated');
return this.activated.instance;
}
get activatedRoute() {
if (!this.activated) throw new _RuntimeError(4012, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Outlet is not activated');
return this._activatedRoute;
}
get activatedRouteData() {
if (this._activatedRoute) {
return this._activatedRoute.snapshot.data;
}
return {};
}
detach() {
if (!this.activated) throw new _RuntimeError(4012, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Outlet is not activated');
this.location.detach();
const cmp = this.activated;
this.activated = null;
this._activatedRoute = null;
this.detachEvents.emit(cmp.instance);
return cmp;
}
attach(ref, activatedRoute) {
this.activated = ref;
this._activatedRoute = activatedRoute;
this.location.insert(ref.hostView);
this.inputBinder?.bindActivatedRouteToOutletComponent(this);
this.attachEvents.emit(ref.instance);
}
deactivate() {
if (this.activated) {
const c = this.component;
this.activated.destroy();
this.activated = null;
this._activatedRoute = null;
this.deactivateEvents.emit(c);
}
}
activateWith(activatedRoute, environmentInjector) {
if (this.isActivated) {
throw new _RuntimeError(4013, (typeof ngDevMode === 'undefined' || ngDevMode) && 'Cannot activate an already activated outlet');
}
this._activatedRoute = activatedRoute;
const location = this.location;
const snapshot = activatedRoute.snapshot;
const component = snapshot.component;
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
const injector = new OutletInjector(activatedRoute, childContexts, location.injector, this.routerOutletData);
this.activated = location.createComponent(component, {
index: location.length,
injector,
environmentInjector: environmentInjector
});
this.changeDetector.markForCheck();
this.inputBinder?.bindActivatedRouteToOutletComponent(this);
this.activateEvents.emit(this.activated.instance);
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: RouterOutlet,
deps: [],
target: i0.ɵɵFactoryTarget.Directive
});
static ɵdir = i0.ɵɵngDeclareDirective({
minVersion: "17.1.0",
version: "21.1.1",
type: RouterOutlet,
isStandalone: true,
selector: "router-outlet",
inputs: {
name: {
classPropertyName: "name",
publicName: "name",
isSignal: false,
isRequired: false,
transformFunction: null
},
routerOutletData: {
classPropertyName: "routerOutletData",
publicName: "routerOutletData",
isSignal: true,
isRequired: false,
transformFunction: null
}
},
outputs: {
activateEvents: "activate",
deactivateEvents: "deactivate",
attachEvents: "attach",
detachEvents: "detach"
},
exportAs: ["outlet"],
usesOnChanges: true,
ngImport: i0
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: RouterOutlet,
decorators: [{
type: Directive,
args: [{
selector: 'router-outlet',
exportAs: 'outlet'
}]
}],
propDecorators: {
name: [{
type: Input
}],
activateEvents: [{
type: Output,
args: ['activate']
}],
deactivateEvents: [{
type: Output,
args: ['deactivate']
}],
attachEvents: [{
type: Output,
args: ['attach']
}],
detachEvents: [{
type: Output,
args: ['detach']
}],
routerOutletData: [{
type: i0.Input,
args: [{
isSignal: true,
alias: "routerOutletData",
required: false
}]
}]
}
});
class OutletInjector {
route;
childContexts;
parent;
outletData;
constructor(route, childContexts, parent, outletData) {
this.route = route;
this.childContexts = childContexts;
this.parent = parent;
this.outletData = outletData;
}
get(token, notFoundValue) {
if (token === ActivatedRoute) {
return this.route;
}
if (token === ChildrenOutletContexts) {
return this.childContexts;
}
if (token === ROUTER_OUTLET_DATA) {
return this.outletData;
}
return this.parent.get(token, notFoundValue);
}
}
const INPUT_BINDER = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'Router Input Binder' : '');
class RoutedComponentInputBinder {
outletDataSubscriptions = new Map();
bindActivatedRouteToOutletComponent(outlet) {
this.unsubscribeFromRouteData(outlet);
this.subscribeToRouteData(outlet);
}
unsubscribeFromRouteData(outlet) {
this.outletDataSubscriptions.get(outlet)?.unsubscribe();
this.outletDataSubscriptions.delete(outlet);
}
subscribeToRouteData(outlet) {
const {
activatedRoute
} = outlet;
const dataSubscription = combineLatest([activatedRoute.queryParams, activatedRoute.params, activatedRoute.data]).pipe(switchMap(([queryParams, params, data], index) => {
data = {
...queryParams,
...params,
...data
};
if (index === 0) {
return of(data);
}
return Promise.resolve(data);
})).subscribe(data => {
if (!outlet.isActivated || !outlet.activatedComponentRef || outlet.activatedRoute !== activatedRoute || activatedRoute.component === null) {
this.unsubscribeFromRouteData(outlet);
return;
}
const mirror = reflectComponentType(activatedRoute.component);
if (!mirror) {
this.unsubscribeFromRouteData(outlet);
return;
}
for (const {
templateName
} of mirror.inputs) {
outlet.activatedComponentRef.setInput(templateName, data[templateName]);
}
});
this.outletDataSubscriptions.set(outlet, dataSubscription);
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: RoutedComponentInputBinder,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: RoutedComponentInputBinder
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: RoutedComponentInputBinder,
decorators: [{
type: Injectable
}]
});
class ɵEmptyOutletComponent {
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: ɵEmptyOutletComponent,
deps: [],
target: i0.ɵɵFactoryTarget.Component
});
static ɵcmp = i0.ɵɵngDeclareComponent({
minVersion: "14.0.0",
version: "21.1.1",
type: ɵEmptyOutletComponent,
isStandalone: true,
selector: "ng-component",
exportAs: ["emptyRouterOutlet"],
ngImport: i0,
template: `<router-outlet />`,
isInline: true,
dependencies: [{
kind: "directive",
type: RouterOutlet,
selector: "router-outlet",
inputs: ["name", "routerOutletData"],
outputs: ["activate", "deactivate", "attach", "detach"],
exportAs: ["outlet"]
}]
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: ɵEmptyOutletComponent,
decorators: [{
type: Component,
args: [{
template: `<router-outlet />`,
imports: [RouterOutlet],
exportAs: 'emptyRouterOutlet'
}]
}]
});
function standardizeConfig(r) {
const children = r.children && r.children.map(standardizeConfig);
const c = children ? {
...r,
children
} : {
...r
};
if (!c.component && !c.loadComponent && (children || c.loadChildren) && c.outlet && c.outlet !== PRIMARY_OUTLET) {
c.component = ɵEmptyOutletComponent;
}
return c;
}
function createRouterState(routeReuseStrategy, curr, prevState) {
const root = createNode(routeReuseStrategy, curr._root, prevState ? prevState._root : undefined);
return new RouterState(root, curr);
}
function createNode(routeReuseStrategy, curr, prevState) {
if (prevState && routeReuseStrategy.shouldReuseRoute(curr.value, prevState.value.snapshot)) {
const value = prevState.value;
value._futureSnapshot = curr.value;
const children = createOrReuseChildren(routeReuseStrategy, curr, prevState);
return new TreeNode(value, children);
} else {
if (routeReuseStrategy.shouldAttach(curr.value)) {
const detachedRouteHandle = routeReuseStrategy.retrieve(curr.value);
if (detachedRouteHandle !== null) {
const tree = detachedRouteHandle.route;
tree.value._futureSnapshot = curr.value;
tree.children = curr.children.map(c => createNode(routeReuseStrategy, c));
return tree;
}
}
const value = createActivatedRoute(curr.value);
const children = curr.children.map(c => createNode(routeReuseStrategy, c));
return new TreeNode(value, children);
}
}
function createOrReuseChildren(routeReuseStrategy, curr, prevState) {
return curr.children.map(child => {
for (const p of prevState.children) {
if (routeReuseStrategy.shouldReuseRoute(child.value, p.value.snapshot)) {
return createNode(routeReuseStrategy, child, p);
}
}
return createNode(routeReuseStrategy, child);
});
}
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);
}
class RedirectCommand {
redirectTo;
navigationBehaviorOptions;
constructor(redirectTo, navigationBehaviorOptions) {
this.redirectTo = redirectTo;
this.navigationBehaviorOptions = navigationBehaviorOptions;
}
}
const NAVIGATION_CANCELING_ERROR = 'ngNavigationCancelingError';
function redirectingNavigationError(urlSerializer, redirect) {
const {
redirectTo,
navigationBehaviorOptions
} = isUrlTree(redirect) ? {
redirectTo: redirect,
navigationBehaviorOptions: undefined
} : redirect;
const error = navigationCancelingError(ngDevMode && `Redirecting to "${urlSerializer.serialize(redirectTo)}"`, NavigationCancellationCode.Redirect);
error.url = redirectTo;
error.navigationBehaviorOptions = navigationBehaviorOptions;
return error;
}
function navigationCancelingError(message, code) {
const error = new Error(`NavigationCancelingError: ${message || ''}`);
error[NAVIGATION_CANCELING_ERROR] = true;
error.cancellationCode = code;
return error;
}
function isRedirectingNavigationCancelingError(error) {
return isNavigationCancelingError(error) && isUrlTree(error.url);
}
function isNavigationCancelingError(error) {
return !!error && error[NAVIGATION_CANCELING_ERROR];
}
let warnedAboutUnsupportedInputBinding = false;
class ActivateRoutes {
routeReuseStrategy;
futureState;
currState;
forwardEvent;
inputBindingEnabled;
constructor(routeReuseStrategy, futureState, currState, forwardEvent, inputBindingEnabled) {
this.routeReuseStrategy = routeReuseStrategy;
this.futureState = futureState;
this.currState = currState;
this.forwardEvent = forwardEvent;
this.inputBindingEnabled = inputBindingEnabled;
}
activate(parentContexts) {
const futureRoot = this.futureState._root;
const currRoot = this.currState ? this.currState._root : null;
this.deactivateChildRoutes(futureRoot, currRoot, parentContexts);
advanceActivatedRoute(this.futureState.root);
this.activateChildRoutes(futureRoot, currRoot, parentContexts);
}
deactivateChildRoutes(futureNode, currNode, contexts) {
const children = nodeChildrenAsMap(currNode);
futureNode.children.forEach(futureChild => {
const childOutletName = futureChild.value.outlet;
this.deactivateRoutes(futureChild, children[childOutletName], contexts);
delete children[childOutletName];
});
Object.values(children).forEach(v => {
this.deactivateRouteAndItsChildren(v, contexts);
});
}
deactivateRoutes(futureNode, currNode, parentContext) {
const future = futureNode.value;
const curr = currNode ? currNode.value : null;
if (future === curr) {
if (future.component) {
const context = parentContext.getContext(future.outlet);
if (context) {
this.deactivateChildRoutes(futureNode, currNode, context.children);
}
} else {
this.deactivateChildRoutes(futureNode, currNode, parentContext);
}
} else {
if (curr) {
this.deactivateRouteAndItsChildren(currNode, parentContext);
}
}
}
deactivateRouteAndItsChildren(route, parentContexts) {
if (route.value.component && this.routeReuseStrategy.shouldDetach(route.value.snapshot)) {
this.detachAndStoreRouteSubtree(route, parentContexts);
} else {
this.deactivateRouteAndOutlet(route, parentContexts);
}
}
detachAndStoreRouteSubtree(route, parentContexts) {
const context = parentContexts.getContext(route.value.outlet);
const contexts = context && route.value.component ? context.children : parentContexts;
const children = nodeChildrenAsMap(route);
for (const treeNode of Object.values(children)) {
this.deactivateRouteAndItsChildren(treeNode, contexts);
}
if (context && context.outlet) {
const componentRef = context.outlet.detach();
const contexts = context.children.onOutletDeactivated();
this.routeReuseStrategy.store(route.value.snapshot, {
componentRef,
route,
contexts
});
}
}
deactivateRouteAndOutlet(route, parentContexts) {
const context = parentContexts.getContext(route.value.outlet);
const contexts = context && route.value.component ? context.children : parentContexts;
const children = nodeChildrenAsMap(route);
for (const treeNode of Object.values(children)) {
this.deactivateRouteAndItsChildren(treeNode, contexts);
}
if (context) {
if (context.outlet) {
context.outlet.deactivate();
context.children.onOutletDeactivated();
}
context.attachRef = null;
context.route = null;
}
}
activateChildRoutes(futureNode, currNode, contexts) {
const 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));
}
}
activateRoutes(futureNode, currNode, parentContexts) {
const future = futureNode.value;
const curr = currNode ? currNode.value : null;
advanceActivatedRoute(future);
if (future === curr) {
if (future.component) {
const context = parentContexts.getOrCreateContext(future.outlet);
this.activateChildRoutes(futureNode, currNode, context.children);
} else {
this.activateChildRoutes(futureNode, currNode, parentContexts);
}
} else {
if (future.component) {
const context = parentContexts.getOrCreateContext(future.outlet);
if (this.routeReuseStrategy.shouldAttach(future.snapshot)) {
const stored = 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) {
context.outlet.attach(stored.componentRef, stored.route.value);
}
advanceActivatedRoute(stored.route.value);
this.activateChildRoutes(futureNode, null, context.children);
} else {
context.attachRef = null;
context.route = future;
if (context.outlet) {
context.outlet.activateWith(future, context.injector);
}
this.activateChildRoutes(futureNode, null, context.children);
}
} else {
this.activateChildRoutes(futureNode, null, parentContexts);
}
}
if (typeof ngDevMode === 'undefined' || ngDevMode) {
const context = parentContexts.getOrCreateContext(future.outlet);
const outlet = context.outlet;
if (outlet && this.inputBindingEnabled && !outlet.supportsBindingToComponentInputs && !warnedAboutUnsupportedInputBinding) {
console.warn(`'withComponentInputBinding' feature is enabled but ` + `this application is using an outlet that may not support binding to component inputs.`);
warnedAboutUnsupportedInputBinding = true;
}
}
}
}
class CanActivate {
path;
route;
constructor(path) {
this.path = path;
this.route = this.path[this.path.length - 1];
}
}
class CanDeactivate {
component;
route;
constructor(component, route) {
this.component = component;
this.route = route;
}
}
function getAllRouteGuards(future, curr, parentContexts) {
const futureRoot = future._root;
const currRoot = curr ? curr._root : null;
return getChildRouteGuards(futureRoot, currRoot, parentContexts, [futureRoot.value]);
}
function getCanActivateChild(p) {
const canActivateChild = p.routeConfig ? p.routeConfig.canActivateChild : null;
if (!canActivateChild || canActivateChild.length === 0) return null;
return {
node: p,
guards: canActivateChild
};
}
function getTokenOrFunctionIdentity(tokenOrFunction, injector) {
const NOT_FOUND = Symbol();
const result = injector.get(tokenOrFunction, NOT_FOUND);
if (result === NOT_FOUND) {
if (typeof tokenOrFunction === 'function' && !_isInjectable(tokenOrFunction)) {
return tokenOrFunction;
} else {
return injector.get(tokenOrFunction);
}
}
return result;
}
function getChildRouteGuards(futureNode, currNode, contexts, futurePath, checks = {
canDeactivateChecks: [],
canActivateChecks: []
}) {
const prevChildren = nodeChildrenAsMap(currNode);
futureNode.children.forEach(c => {
getRouteGuards(c, prevChildren[c.value.outlet], contexts, futurePath.concat([c.value]), checks);
delete prevChildren[c.value.outlet];
});
Object.entries(prevChildren).forEach(([k, v]) => deactivateRouteAndItsChildren(v, contexts.getContext(k), checks));
return checks;
}
function getRouteGuards(futureNode, currNode, parentContexts, futurePath, checks = {
canDeactivateChecks: [],
canActivateChecks: []
}) {
const future = futureNode.value;
const curr = currNode ? currNode.value : null;
const context = parentContexts ? parentContexts.getContext(futureNode.value.outlet) : null;
if (curr && future.routeConfig === curr.routeConfig) {
const shouldRun = shouldRunGuardsAndResolvers(curr, future, future.routeConfig.runGuardsAndResolvers);
if (shouldRun) {
checks.canActivateChecks.push(new CanActivate(futurePath));
} else {
future.data = curr.data;
future._resolvedData = curr._resolvedData;
}
if (future.component) {
getChildRouteGuards(futureNode, currNode, context ? context.children : null, futurePath, checks);
} else {
getChildRouteGuards(futureNode, currNode, parentContexts, futurePath, checks);
}
if (shouldRun && context && context.outlet && context.outlet.isActivated) {
checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, curr));
}
} else {
if (curr) {
deactivateRouteAndItsChildren(currNode, context, checks);
}
checks.canActivateChecks.push(new CanActivate(futurePath));
if (future.component) {
getChildRouteGuards(futureNode, null, context ? context.children : null, futurePath, checks);
} else {
getChildRouteGuards(futureNode, null, parentContexts, futurePath, checks);
}
}
return checks;
}
function shouldRunGuardsAndResolvers(curr, future, mode) {
if (typeof mode === 'function') {
return runInInjectionContext(future._environmentInjector, () => mode(curr, future));
}
switch (mode) {
case 'pathParamsChange':
return !equalPath(curr.url, future.url);
case 'pathParamsOrQueryParamsChange':
return !equalPath(curr.url, future.url) || !shallowEqual(curr.queryParams, future.queryParams);
case 'always':
return true;
case 'paramsOrQueryParamsChange':
return !equalParamsAndUrlSegments(curr, future) || !shallowEqual(curr.queryParams, future.queryParams);
case 'paramsChange':
default:
return !equalParamsAndUrlSegments(curr, future);
}
}
function deactivateRouteAndItsChildren(route, context, checks) {
const children = nodeChildrenAsMap(route);
const r = route.value;
Object.entries(children).forEach(([childName, node]) => {
if (!r.component) {
deactivateRouteAndItsChildren(node, context, checks);
} else if (context) {
deactivateRouteAndItsChildren(node, context.children.getContext(childName), checks);
} else {
deactivateRouteAndItsChildren(node, null, checks);
}
});
if (!r.component) {
checks.canDeactivateChecks.push(new CanDeactivate(null, r));
} else if (context && context.outlet && context.outlet.isActivated) {
checks.canDeactivateChecks.push(new CanDeactivate(context.outlet.component, r));
} else {
checks.canDeactivateChecks.push(new CanDeactivate(null, r));
}
}
function isFunction(v) {
return typeof v === 'function';
}
function isBoolean(v) {
return typeof v === 'boolean';
}
function isCanLoad(guard) {
return guard && isFunction(guard.canLoad);
}
function isCanActivate(guard) {
return guard && isFunction(guard.canActivate);
}
function isCanActivateChild(guard) {
return guard && isFunction(guard.canActivateChild);
}
function isCanDeactivate(guard) {
return guard && isFunction(guard.canDeactivate);
}
function isCanMatch(guard) {
return guard && isFunction(guard.canMatch);
}
function isEmptyError(e) {
return e instanceof EmptyError || e?.name === 'EmptyError';
}
const INITIAL_VALUE = /* @__PURE__ */Symbol('INITIAL_VALUE');
function prioritizedGuardValue() {
return switchMap(obs => {
return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE)))).pipe(map(results => {
for (const result of results) {
if (result === true) {
continue;
} else if (result === INITIAL_VALUE) {
return INITIAL_VALUE;
} else if (result === false || isRedirect(result)) {
return result;
}
}
return true;
}), filter(item => item !== INITIAL_VALUE), take(1));
});
}
function isRedirect(val) {
return isUrlTree(val) || val instanceof RedirectCommand;
}
function abortSignalToObservable(signal) {
if (signal.aborted) {
return of(undefined).pipe(take(1));
}
return new Observable(subscriber => {
const handler = () => {
subscriber.next();
subscriber.complete();
};
signal.addEventListener('abort', handler);
return () => signal.removeEventListener('abort', handler);
});
}
function takeUntilAbort(signal) {
return takeUntil(abortSignalToObservable(signal));
}
function checkGuards(forwardEvent) {
return mergeMap(t => {
const {
targetSnapshot,
currentSnapshot,
guards: {
canActivateChecks,
canDeactivateChecks
}
} = t;
if (canDeactivateChecks.length === 0 && canActivateChecks.length === 0) {
return of({
...t,
guardsResult: true
});
}
return runCanDeactivateChecks(canDeactivateChecks, targetSnapshot, currentSnapshot).pipe(mergeMap(canDeactivate => {
return canDeactivate && isBoolean(canDeactivate) ? runCanActivateChecks(targetSnapshot, canActivateChecks, forwardEvent) : of(canDeactivate);
}), map(guardsResult => ({
...t,
guardsResult
})));
});
}
function runCanDeactivateChecks(checks, futureRSS, currRSS) {
return from(checks).pipe(mergeMap(check => runCanDeactivate(check.component, check.route, currRSS, futureRSS)), first(result => {
return result !== true;
}, true));
}
function runCanActivateChecks(futureSnapshot, checks, forwardEvent) {
return from(checks).pipe(concatMap(check => {
return concat(fireChildActivationStart(check.route.parent, forwardEvent), fireActivationStart(check.route, forwardEvent), runCanActivateChild(futureSnapshot, check.path), runCanActivate(futureSnapshot, check.route));
}), first(result => {
return result !== true;
}, true));
}
function fireActivationStart(snapshot, forwardEvent) {
if (snapshot !== null && forwardEvent) {
forwardEvent(new ActivationStart(snapshot));
}
return of(true);
}
function fireChildActivationStart(snapshot, forwardEvent) {
if (snapshot !== null && forwardEvent) {
forwardEvent(new ChildActivationStart(snapshot));
}
return of(true);
}
function runCanActivate(futureRSS, futureARS) {
const canActivate = futureARS.routeConfig ? futureARS.routeConfig.canActivate : null;
if (!canActivate || canActivate.length === 0) return of(true);
const canActivateObservables = canActivate.map(canActivate => {
return defer(() => {
const closestInjector = futureARS._environmentInjector;
const guard = getTokenOrFunctionIdentity(canActivate, closestInjector);
const guardVal = isCanActivate(guard) ? guard.canActivate(futureARS, futureRSS) : runInInjectionContext(closestInjector, () => guard(futureARS, futureRSS));
return wrapIntoObservable(guardVal).pipe(first());
});
});
return of(canActivateObservables).pipe(prioritizedGuardValue());
}
function runCanActivateChild(futureRSS, path) {
const futureARS = path[path.length - 1];
const canActivateChildGuards = path.slice(0, path.length - 1).reverse().map(p => getCanActivateChild(p)).filter(_ => _ !== null);
const canActivateChildGuardsMapped = canActivateChildGuards.map(d => {
return defer(() => {
const guardsMapped = d.guards.map(canActivateChild => {
const closestInjector = d.node._environmentInjector;
const guard = getTokenOrFunctionIdentity(canActivateChild, closestInjector);
const guardVal = isCanActivateChild(guard) ? guard.canActivateChild(futureARS, futureRSS) : runInInjectionContext(closestInjector, () => guard(futureARS, futureRSS));
return wrapIntoObservable(guardVal).pipe(first());
});
return of(guardsMapped).pipe(prioritizedGuardValue());
});
});
return of(canActivateChildGuardsMapped).pipe(prioritizedGuardValue());
}
function runCanDeactivate(component, currARS, currRSS, futureRSS) {
const canDeactivate = currARS && currARS.routeConfig ? currARS.routeConfig.canDeactivate : null;
if (!canDeactivate || canDeactivate.length === 0) return of(true);
const canDeactivateObservables = canDeactivate.map(c => {
const closestInjector = currARS._environmentInjector;
const guard = getTokenOrFunctionIdentity(c, closestInjector);
const guardVal = isCanDeactivate(guard) ? guard.canDeactivate(component, currARS, currRSS, futureRSS) : runInInjectionContext(closestInjector, () => guard(component, currARS, currRSS, futureRSS));
return wrapIntoObservable(guardVal).pipe(first());
});
return of(canDeactivateObservables).pipe(prioritizedGuardValue());
}
function runCanLoadGuards(injector, route, segments, urlSerializer, abortSignal) {
const canLoad = route.canLoad;
if (canLoad === undefined || canLoad.length === 0) {
return of(true);
}
const canLoadObservables = canLoad.map(injectionToken => {
const guard = getTokenOrFunctionIdentity(injectionToken, injector);
const guardVal = isCanLoad(guard) ? guard.canLoad(route, segments) : runInInjectionContext(injector, () => guard(route, segments));
const obs$ = wrapIntoObservable(guardVal);
return abortSignal ? obs$.pipe(takeUntilAbort(abortSignal)) : obs$;
});
return of(canLoadObservables).pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer));
}
function redirectIfUrlTree(urlSerializer) {
return pipe(tap(result => {
if (typeof result === 'boolean') return;
throw redirectingNavigationError(urlSerializer, result);
}), map(result => result === true));
}
function runCanMatchGuards(injector, route, segments, urlSerializer, abortSignal) {
const canMatch = route.canMatch;
if (!canMatch || canMatch.length === 0) return of(true);
const canMatchObservables = canMatch.map(injectionToken => {
const guard = getTokenOrFunctionIdentity(injectionToken, injector);
const guardVal = isCanMatch(guard) ? guard.canMatch(route, segments) : runInInjectionContext(injector, () => guard(route, segments));
return wrapIntoObservable(guardVal).pipe(takeUntilAbort(abortSignal));
});
return of(canMatchObservables).pipe(prioritizedGuardValue(), redirectIfUrlTree(urlSerializer));
}
class NoMatch extends Error {
segmentGroup;
constructor(segmentGroup) {
super();
this.segmentGroup = segmentGroup || null;
Object.setPrototypeOf(this, NoMatch.prototype);
}
}
class AbsoluteRedirect extends Error {
urlTree;
constructor(urlTree) {
super();
this.urlTree = urlTree;
Object.setPrototypeOf(this, AbsoluteRedirect.prototype);
}
}
function namedOutletsRedirect(redirectTo) {
throw new _RuntimeError(4000, (typeof ngDevMode === 'undefined' || ngDevMode) && `Only absolute redirects can have named outlets. redirectTo: '${redirectTo}'`);
}
function canLoadFails(route) {
throw navigationCancelingError((typeof ngDevMode === 'undefined' || ngDevMode) && `Cannot load children because the guard of the route "path: '${route.path}'" returned false`, NavigationCancellationCode.GuardRejected);
}
class ApplyRedirects {
urlSerializer;
urlTree;
constructor(urlSerializer, urlTree) {
this.urlSerializer = urlSerializer;
this.urlTree = urlTree;
}
async lineralizeSegments(route, urlTree) {
let res = [];
let c = urlTree.root;
while (true) {
res = res.concat(c.segments);
if (c.numberOfChildren === 0) {
return res;
}
if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) {
throw namedOutletsRedirect(`${route.redirectTo}`);
}
c = c.children[PRIMARY_OUTLET];
}
}
async applyRedirectCommands(segments, redirectTo, posParams, currentSnapshot, injector) {
const redirect = await getRedirectResult(redirectTo, currentSnapshot, injector);
if (redirect instanceof UrlTree) {
throw new AbsoluteRedirect(redirect);
}
const newTree = this.applyRedirectCreateUrlTree(redirect, this.urlSerializer.parse(redirect), segments, posParams);
if (redirect[0] === '/') {
throw new AbsoluteRedirect(newTree);
}
return newTree;
}
applyRedirectCreateUrlTree(redirectTo, urlTree, segments, posParams) {
const newRoot = this.createSegmentGroup(redirectTo, urlTree.root, segments, posParams);
return new UrlTree(newRoot, this.createQueryParams(urlTree.queryParams, this.urlTree.queryParams), urlTree.fragment);
}
createQueryParams(redirectToParams, actualParams) {
const res = {};
Object.entries(redirectToParams).forEach(([k, v]) => {
const copySourceValue = typeof v === 'string' && v[0] === ':';
if (copySourceValue) {
const sourceName = v.substring(1);
res[k] = actualParams[sourceName];
} else {
res[k] = v;
}
});
return res;
}
createSegmentGroup(redirectTo, group, segments, posParams) {
const updatedSegments = this.createSegments(redirectTo, group.segments, segments, posParams);
let children = {};
Object.entries(group.children).forEach(([name, child]) => {
children[name] = this.createSegmentGroup(redirectTo, child, segments, posParams);
});
return new UrlSegmentGroup(updatedSegments, children);
}
createSegments(redirectTo, redirectToSegments, actualSegments, posParams) {
return redirectToSegments.map(s => s.path[0] === ':' ? this.findPosParam(redirectTo, s, posParams) : this.findOrReturn(s, actualSegments));
}
findPosParam(redirectTo, redirectToUrlSegment, posParams) {
const pos = posParams[redirectToUrlSegment.path.substring(1)];
if (!pos) throw new _RuntimeError(4001, (typeof ngDevMode === 'undefined' || ngDevMode) && `Cannot redirect to '${redirectTo}'. Cannot find '${redirectToUrlSegment.path}'.`);
return pos;
}
findOrReturn(redirectToUrlSegment, actualSegments) {
let idx = 0;
for (const s of actualSegments) {
if (s.path === redirectToUrlSegment.path) {
actualSegments.splice(idx);
return s;
}
idx++;
}
return redirectToUrlSegment;
}
}
function getRedirectResult(redirectTo, currentSnapshot, injector) {
if (typeof redirectTo === 'string') {
return Promise.resolve(redirectTo);
}
const redirectToFn = redirectTo;
const {
queryParams,
fragment,
routeConfig,
url,
outlet,
params,
data,
title,
paramMap,
queryParamMap
} = currentSnapshot;
return firstValueFrom(wrapIntoObservable(runInInjectionContext(injector, () => redirectToFn({
params,
data,
queryParams,
fragment,
routeConfig,
url,
outlet,
title,
paramMap,
queryParamMap
}))));
}
function getOrCreateRouteInjectorIfNeeded(route, currentInjector) {
if (route.providers && !route._injector) {
route._injector = createEnvironmentInjector(route.providers, currentInjector, `Route: ${route.path}`);
}
return route._injector ?? currentInjector;
}
function validateConfig(config, parentPath = '', requireStandaloneComponents = false) {
for (let i = 0; i < config.length; i++) {
const route = config[i];
const fullPath = getFullPath(parentPath, route);
validateNode(route, fullPath, requireStandaloneComponents);
}
}
function assertStandalone(fullPath, component) {
if (component && _isNgModule(component)) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}'. You are using 'loadComponent' with a module, ` + `but it must be used with standalone components. Use 'loadChildren' instead.`);
} else if (component && !isStandalone(component)) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}'. The component must be standalone.`);
}
}
function validateNode(route, fullPath, requireStandaloneComponents) {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
if (!route) {
throw new _RuntimeError(4014, `
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 _RuntimeError(4014, `Invalid configuration of route '${fullPath}': Array cannot be specified`);
}
if (!route.redirectTo && !route.component && !route.loadComponent && !route.children && !route.loadChildren && route.outlet && route.outlet !== PRIMARY_OUTLET) {
throw new _RuntimeError(4014, `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 _RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and children cannot be used together`);
}
if (route.redirectTo && route.loadChildren) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and loadChildren cannot be used together`);
}
if (route.children && route.loadChildren) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': children and loadChildren cannot be used together`);
}
if (route.component && route.loadComponent) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': component and loadComponent cannot be used together`);
}
if (route.redirectTo) {
if (route.component || route.loadComponent) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and component/loadComponent cannot be used together`);
}
if (route.canMatch || route.canActivate) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': redirectTo and ${route.canMatch ? 'canMatch' : 'canActivate'} cannot be used together.` + `Redirects happen before guards are executed.`);
}
}
if (route.path && route.matcher) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}': path and matcher cannot be used together`);
}
if (route.redirectTo === void 0 && !route.component && !route.loadComponent && !route.children && !route.loadChildren) {
throw new _RuntimeError(4014, `Invalid configuration of route '${fullPath}'. One of the following must be provided: component, loadComponent, redirectTo, children or loadChildren`);
}
if (route.path === void 0 && route.matcher === void 0) {
throw new _RuntimeError(4014, `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 _RuntimeError(4014, `Invalid configuration of route '${fullPath}': path cannot start with a slash`);
}
if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) {
const exp = `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`;
throw new _RuntimeError(4014, `Invalid configuration of route '{path: "${fullPath}", redirectTo: "${route.redirectTo}"}': please provide 'pathMatch'. ${exp}`);
}
if (requireStandaloneComponents) {
assertStandalone(fullPath, route.component);
}
}
if (route.children) {
validateConfig(route.children, fullPath, requireStandaloneComponents);
}
}
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}`;
}
}
function getOutlet(route) {
return route.outlet || PRIMARY_OUTLET;
}
function sortByMatchingOutlets(routes, outletName) {
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
return sortedConfig;
}
const noMatch = {
matched: false,
consumedSegments: [],
remainingSegments: [],
parameters: {},
positionalParamSegments: {}
};
function matchWithChecks(segmentGroup, route, segments, injector, urlSerializer, abortSignal) {
const result = match(segmentGroup, route, segments);
if (!result.matched) {
return of(result);
}
injector = getOrCreateRouteInjectorIfNeeded(route, injector);
return runCanMatchGuards(injector, route, segments, urlSerializer, abortSignal).pipe(map(v => v === true ? result : {
...noMatch
}));
}
function match(segmentGroup, route, segments) {
if (route.path === '') {
if (route.pathMatch === 'full' && (segmentGroup.hasChildren() || segments.length > 0)) {
return {
...noMatch
};
}
return {
matched: true,
consumedSegments: [],
remainingSegments: segments,
parameters: {},
positionalParamSegments: {}
};
}
const matcher = route.matcher || defaultUrlMatcher;
const res = matcher(segments, segmentGroup, route);
if (!res) return {
...noMatch
};
const posParams = {};
Object.entries(res.posParams ?? {}).forEach(([k, v]) => {
posParams[k] = v.path;
});
const parameters = res.consumed.length > 0 ? {
...posParams,
...res.consumed[res.consumed.length - 1].parameters
} : posParams;
return {
matched: true,
consumedSegments: res.consumed,
remainingSegments: segments.slice(res.consumed.length),
parameters,
positionalParamSegments: res.posParams ?? {}
};
}
function split(segmentGroup, consumedSegments, slicedSegments, config) {
if (slicedSegments.length > 0 && containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, config)) {
const s = new UrlSegmentGroup(consumedSegments, createChildrenForEmptyPaths(config, new UrlSegmentGroup(slicedSegments, segmentGroup.children)));
return {
segmentGroup: s,
slicedSegments: []
};
}
if (slicedSegments.length === 0 && containsEmptyPathMatches(segmentGroup, slicedSegments, config)) {
const s = new UrlSegmentGroup(segmentGroup.segments, addEmptyPathsToChildrenIfNeeded(segmentGroup, slicedSegments, config, segmentGroup.children));
return {
segmentGroup: s,
slicedSegments
};
}
const s = new UrlSegmentGroup(segmentGroup.segments, segmentGroup.children);
return {
segmentGroup: s,
slicedSegments
};
}
function addEmptyPathsToChildrenIfNeeded(segmentGroup, slicedSegments, routes, children) {
const res = {};
for (const r of routes) {
if (emptyPathMatch(segmentGroup, slicedSegments, r) && !children[getOutlet(r)]) {
const s = new UrlSegmentGroup([], {});
res[getOutlet(r)] = s;
}
}
return {
...children,
...res
};
}
function createChildrenForEmptyPaths(routes, primarySegment) {
const res = {};
res[PRIMARY_OUTLET] = primarySegment;
for (const r of routes) {
if (r.path === '' && getOutlet(r) !== PRIMARY_OUTLET) {
const s = new UrlSegmentGroup([], {});
res[getOutlet(r)] = s;
}
}
return res;
}
function containsEmptyPathMatchesWithNamedOutlets(segmentGroup, slicedSegments, routes) {
return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r) && getOutlet(r) !== PRIMARY_OUTLET);
}
function containsEmptyPathMatches(segmentGroup, slicedSegments, routes) {
return routes.some(r => emptyPathMatch(segmentGroup, slicedSegments, r));
}
function emptyPathMatch(segmentGroup, slicedSegments, r) {
if ((segmentGroup.hasChildren() || slicedSegments.length > 0) && r.pathMatch === 'full') {
return false;
}
return r.path === '';
}
function noLeftoversInUrl(segmentGroup, segments, outlet) {
return segments.length === 0 && !segmentGroup.children[outlet];
}
class NoLeftoversInUrl {}
async function recognize$1(injector, configLoader, rootComponentType, config, urlTree, urlSerializer, paramsInheritanceStrategy = 'emptyOnly', abortSignal) {
return new Recognizer(injector, configLoader, rootComponentType, config, urlTree, paramsInheritanceStrategy, urlSerializer, abortSignal).recognize();
}
const MAX_ALLOWED_REDIRECTS = 31;
class Recognizer {
injector;
configLoader;
rootComponentType;
config;
urlTree;
paramsInheritanceStrategy;
urlSerializer;
abortSignal;
applyRedirects;
absoluteRedirectCount = 0;
allowRedirects = true;
constructor(injector, configLoader, rootComponentType, config, urlTree, paramsInheritanceStrategy, urlSerializer, abortSignal) {
this.injector = injector;
this.configLoader = configLoader;
this.rootComponentType = rootComponentType;
this.config = config;
this.urlTree = urlTree;
this.paramsInheritanceStrategy = paramsInheritanceStrategy;
this.urlSerializer = urlSerializer;
this.abortSignal = abortSignal;
this.applyRedirects = new ApplyRedirects(this.urlSerializer, this.urlTree);
}
noMatchError(e) {
return new _RuntimeError(4002, typeof ngDevMode === 'undefined' || ngDevMode ? `Cannot match any routes. URL Segment: '${e.segmentGroup}'` : `'${e.segmentGroup}'`);
}
async recognize() {
const rootSegmentGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
const {
children,
rootSnapshot
} = await this.match(rootSegmentGroup);
const rootNode = new TreeNode(rootSnapshot, children);
const routeState = new RouterStateSnapshot('', rootNode);
const tree = createUrlTreeFromSnapshot(rootSnapshot, [], this.urlTree.queryParams, this.urlTree.fragment);
tree.queryParams = this.urlTree.queryParams;
routeState.url = this.urlSerializer.serialize(tree);
return {
state: routeState,
tree
};
}
async match(rootSegmentGroup) {
const rootSnapshot = new ActivatedRouteSnapshot([], Object.freeze({}), Object.freeze({
...this.urlTree.queryParams
}), this.urlTree.fragment, Object.freeze({}), PRIMARY_OUTLET, this.rootComponentType, null, {}, this.injector);
try {
const children = await this.processSegmentGroup(this.injector, this.config, rootSegmentGroup, PRIMARY_OUTLET, rootSnapshot);
return {
children,
rootSnapshot
};
} catch (e) {
if (e instanceof AbsoluteRedirect) {
this.urlTree = e.urlTree;
return this.match(e.urlTree.root);
}
if (e instanceof NoMatch) {
throw this.noMatchError(e);
}
throw e;
}
}
async processSegmentGroup(injector, config, segmentGroup, outlet, parentRoute) {
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
return this.processChildren(injector, config, segmentGroup, parentRoute);
}
const child = await this.processSegment(injector, config, segmentGroup, segmentGroup.segments, outlet, true, parentRoute);
return child instanceof TreeNode ? [child] : [];
}
async processChildren(injector, config, segmentGroup, parentRoute) {
const childOutlets = [];
for (const child of Object.keys(segmentGroup.children)) {
if (child === 'primary') {
childOutlets.unshift(child);
} else {
childOutlets.push(child);
}
}
let children = [];
for (const childOutlet of childOutlets) {
const child = segmentGroup.children[childOutlet];
const sortedConfig = sortByMatchingOutlets(config, childOutlet);
const outletChildren = await this.processSegmentGroup(injector, sortedConfig, child, childOutlet, parentRoute);
children.push(...outletChildren);
}
const mergedChildren = mergeEmptyPathMatches(children);
if (typeof ngDevMode === 'undefined' || ngDevMode) {
checkOutletNameUniqueness(mergedChildren);
}
sortActivatedRouteSnapshots(mergedChildren);
return mergedChildren;
}
async processSegment(injector, routes, segmentGroup, segments, outlet, allowRedirects, parentRoute) {
for (const r of routes) {
try {
return await this.processSegmentAgainstRoute(r._injector ?? injector, routes, r, segmentGroup, segments, outlet, allowRedirects, parentRoute);
} catch (e) {
if (e instanceof NoMatch || isEmptyError(e)) {
continue;
}
throw e;
}
}
if (noLeftoversInUrl(segmentGroup, segments, outlet)) {
return new NoLeftoversInUrl();
}
throw new NoMatch(segmentGroup);
}
async processSegmentAgainstRoute(injector, routes, route, rawSegment, segments, outlet, allowRedirects, parentRoute) {
if (getOutlet(route) !== outlet && (outlet === PRIMARY_OUTLET || !emptyPathMatch(rawSegment, segments, route))) {
throw new NoMatch(rawSegment);
}
if (route.redirectTo === undefined) {
return this.matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, parentRoute);
}
if (this.allowRedirects && allowRedirects) {
return this.expandSegmentAgainstRouteUsingRedirect(injector, rawSegment, routes, route, segments, outlet, parentRoute);
}
throw new NoMatch(rawSegment);
}
async expandSegmentAgainstRouteUsingRedirect(injector, segmentGroup, routes, route, segments, outlet, parentRoute) {
const {
matched,
parameters,
consumedSegments,
positionalParamSegments,
remainingSegments
} = match(segmentGroup, route, segments);
if (!matched) throw new NoMatch(segmentGroup);
if (typeof route.redirectTo === 'string' && route.redirectTo[0] === '/') {
this.absoluteRedirectCount++;
if (this.absoluteRedirectCount > MAX_ALLOWED_REDIRECTS) {
if (ngDevMode) {
throw new _RuntimeError(4016, `Detected possible infinite redirect when redirecting from '${this.urlTree}' to '${route.redirectTo}'.\n` + `This is currently a dev mode only error but will become a` + ` call stack size exceeded error in production in a future major version.`);
}
this.allowRedirects = false;
}
}
const currentSnapshot = new ActivatedRouteSnapshot(segments, parameters, Object.freeze({
...this.urlTree.queryParams
}), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getResolve(route), injector);
const inherited = getInherited(currentSnapshot, parentRoute, this.paramsInheritanceStrategy);
currentSnapshot.params = Object.freeze(inherited.params);
currentSnapshot.data = Object.freeze(inherited.data);
if (this.abortSignal.aborted) {
throw new Error(this.abortSignal.reason);
}
const newTree = await this.applyRedirects.applyRedirectCommands(consumedSegments, route.redirectTo, positionalParamSegments, currentSnapshot, injector);
const newSegments = await this.applyRedirects.lineralizeSegments(route, newTree);
return this.processSegment(injector, routes, segmentGroup, newSegments.concat(remainingSegments), outlet, false, parentRoute);
}
async matchSegmentAgainstRoute(injector, rawSegment, route, segments, outlet, parentRoute) {
if (this.abortSignal.aborted) {
throw new Error(this.abortSignal.reason);
}
const result = await firstValueFrom(matchWithChecks(rawSegment, route, segments, injector, this.urlSerializer, this.abortSignal));
if (route.path === '**') {
rawSegment.children = {};
}
if (!result?.matched) {
throw new NoMatch(rawSegment);
}
injector = route._injector ?? injector;
const {
routes: childConfig
} = await this.getChildConfig(injector, route, segments);
const childInjector = route._loadedInjector ?? injector;
const {
parameters,
consumedSegments,
remainingSegments
} = result;
const snapshot = new ActivatedRouteSnapshot(consumedSegments, parameters, Object.freeze({
...this.urlTree.queryParams
}), this.urlTree.fragment, getData(route), getOutlet(route), route.component ?? route._loadedComponent ?? null, route, getResolve(route), injector);
const inherited = getInherited(snapshot, parentRoute, this.paramsInheritanceStrategy);
snapshot.params = Object.freeze(inherited.params);
snapshot.data = Object.freeze(inherited.data);
const {
segmentGroup,
slicedSegments
} = split(rawSegment, consumedSegments, remainingSegments, childConfig);
if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
const children = await this.processChildren(childInjector, childConfig, segmentGroup, snapshot);
return new TreeNode(snapshot, children);
}
if (childConfig.length === 0 && slicedSegments.length === 0) {
return new TreeNode(snapshot, []);
}
const matchedOnOutlet = getOutlet(route) === outlet;
const child = await this.processSegment(childInjector, childConfig, segmentGroup, slicedSegments, matchedOnOutlet ? PRIMARY_OUTLET : outlet, true, snapshot);
return new TreeNode(snapshot, child instanceof TreeNode ? [child] : []);
}
async getChildConfig(injector, route, segments) {
if (route.children) {
return {
routes: route.children,
injector
};
}
if (route.loadChildren) {
if (route._loadedRoutes !== undefined) {
const ngModuleFactory = route._loadedNgModuleFactory;
if (ngModuleFactory && !route._loadedInjector) {
route._loadedInjector = ngModuleFactory.create(injector).injector;
}
return {
routes: route._loadedRoutes,
injector: route._loadedInjector
};
}
if (this.abortSignal.aborted) {
throw new Error(this.abortSignal.reason);
}
const shouldLoadResult = await firstValueFrom(runCanLoadGuards(injector, route, segments, this.urlSerializer, this.abortSignal));
if (shouldLoadResult) {
const cfg = await this.configLoader.loadChildren(injector, route);
route._loadedRoutes = cfg.routes;
route._loadedInjector = cfg.injector;
route._loadedNgModuleFactory = cfg.factory;
return cfg;
}
throw canLoadFails(route);
}
return {
routes: [],
injector
};
}
}
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);
});
}
function hasEmptyPathConfig(node) {
const config = node.value.routeConfig;
return config && config.path === '';
}
function mergeEmptyPathMatches(nodes) {
const result = [];
const mergedNodes = new Set();
for (const node of nodes) {
if (!hasEmptyPathConfig(node)) {
result.push(node);
continue;
}
const duplicateEmptyPathNode = result.find(resultNode => node.value.routeConfig === resultNode.value.routeConfig);
if (duplicateEmptyPathNode !== undefined) {
duplicateEmptyPathNode.children.push(...node.children);
mergedNodes.add(duplicateEmptyPathNode);
} else {
result.push(node);
}
}
for (const mergedNode of mergedNodes) {
const mergedChildren = mergeEmptyPathMatches(mergedNode.children);
result.push(new TreeNode(mergedNode.value, mergedChildren));
}
return result.filter(n => !mergedNodes.has(n));
}
function checkOutletNameUniqueness(nodes) {
const names = {};
nodes.forEach(n => {
const routeWithSameOutletName = names[n.value.outlet];
if (routeWithSameOutletName) {
const p = routeWithSameOutletName.url.map(s => s.toString()).join('/');
const c = n.value.url.map(s => s.toString()).join('/');
throw new _RuntimeError(4006, (typeof ngDevMode === 'undefined' || ngDevMode) && `Two segments cannot have the same outlet name: '${p}' and '${c}'.`);
}
names[n.value.outlet] = n.value;
});
}
function getData(route) {
return route.data || {};
}
function getResolve(route) {
return route.resolve || {};
}
function recognize(injector, configLoader, rootComponentType, config, serializer, paramsInheritanceStrategy, abortSignal) {
return mergeMap(async t => {
const {
state: targetSnapshot,
tree: urlAfterRedirects
} = await recognize$1(injector, configLoader, rootComponentType, config, t.extractedUrl, serializer, paramsInheritanceStrategy, abortSignal);
return {
...t,
targetSnapshot,
urlAfterRedirects
};
});
}
function resolveData(paramsInheritanceStrategy) {
return mergeMap(t => {
const {
targetSnapshot,
guards: {
canActivateChecks
}
} = t;
if (!canActivateChecks.length) {
return of(t);
}
const routesWithResolversToRun = new Set(canActivateChecks.map(check => check.route));
const routesNeedingDataUpdates = new Set();
for (const route of routesWithResolversToRun) {
if (routesNeedingDataUpdates.has(route)) {
continue;
}
for (const newRoute of flattenRouteTree(route)) {
routesNeedingDataUpdates.add(newRoute);
}
}
let routesProcessed = 0;
return from(routesNeedingDataUpdates).pipe(concatMap(route => {
if (routesWithResolversToRun.has(route)) {
return runResolve(route, targetSnapshot, paramsInheritanceStrategy);
} else {
route.data = getInherited(route, route.parent, paramsInheritanceStrategy).resolve;
return of(void 0);
}
}), tap(() => routesProcessed++), takeLast(1), mergeMap(_ => routesProcessed === routesNeedingDataUpdates.size ? of(t) : EMPTY));
});
}
function flattenRouteTree(route) {
const descendants = route.children.map(child => flattenRouteTree(child)).flat();
return [route, ...descendants];
}
function runResolve(futureARS, futureRSS, paramsInheritanceStrategy) {
const config = futureARS.routeConfig;
const resolve = futureARS._resolve;
if (config?.title !== undefined && !hasStaticTitle(config)) {
resolve[RouteTitleKey] = config.title;
}
return defer(() => {
futureARS.data = getInherited(futureARS, futureARS.parent, paramsInheritanceStrategy).resolve;
return resolveNode(resolve, futureARS, futureRSS).pipe(map(resolvedData => {
futureARS._resolvedData = resolvedData;
futureARS.data = {
...futureARS.data,
...resolvedData
};
return null;
}));
});
}
function resolveNode(resolve, futureARS, futureRSS) {
const keys = getDataKeys(resolve);
if (keys.length === 0) {
return of({});
}
const data = {};
return from(keys).pipe(mergeMap(key => getResolver(resolve[key], futureARS, futureRSS).pipe(first(), tap(value => {
if (value instanceof RedirectCommand) {
throw redirectingNavigationError(new DefaultUrlSerializer(), value);
}
data[key] = value;
}))), takeLast(1), map(() => data), catchError(e => isEmptyError(e) ? EMPTY : throwError(e)));
}
function getResolver(injectionToken, futureARS, futureRSS) {
const closestInjector = futureARS._environmentInjector;
const resolver = getTokenOrFunctionIdentity(injectionToken, closestInjector);
const resolverValue = resolver.resolve ? resolver.resolve(futureARS, futureRSS) : runInInjectionContext(closestInjector, () => resolver(futureARS, futureRSS));
return wrapIntoObservable(resolverValue);
}
function switchTap(next) {
return switchMap(v => {
const nextResult = next(v);
if (nextResult) {
return from(nextResult).pipe(map(() => v));
}
return of(v);
});
}
class TitleStrategy {
buildTitle(snapshot) {
let pageTitle;
let route = snapshot.root;
while (route !== undefined) {
pageTitle = this.getResolvedTitleForRoute(route) ?? pageTitle;
route = route.children.find(child => child.outlet === PRIMARY_OUTLET);
}
return pageTitle;
}
getResolvedTitleForRoute(snapshot) {
return snapshot.data[RouteTitleKey];
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: TitleStrategy,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: TitleStrategy,
providedIn: 'root',
useFactory: () => inject(DefaultTitleStrategy)
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: TitleStrategy,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
useFactory: () => inject(DefaultTitleStrategy)
}]
}]
});
class DefaultTitleStrategy extends TitleStrategy {
title;
constructor(title) {
super();
this.title = title;
}
updateTitle(snapshot) {
const title = this.buildTitle(snapshot);
if (title !== undefined) {
this.title.setTitle(title);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: DefaultTitleStrategy,
deps: [{
token: i1.Title
}],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: DefaultTitleStrategy,
providedIn: 'root'
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: DefaultTitleStrategy,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}],
ctorParameters: () => [{
type: i1.Title
}]
});
const ROUTER_CONFIGURATION = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'router config' : '', {
factory: () => ({})
});
const ROUTES = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'ROUTES' : '');
class RouterConfigLoader {
componentLoaders = new WeakMap();
childrenLoaders = new WeakMap();
onLoadStartListener;
onLoadEndListener;
compiler = inject(Compiler);
async loadComponent(injector, route) {
if (this.componentLoaders.get(route)) {
return this.componentLoaders.get(route);
} else if (route._loadedComponent) {
return Promise.resolve(route._loadedComponent);
}
if (this.onLoadStartListener) {
this.onLoadStartListener(route);
}
const loader = (async () => {
try {
const loaded = await wrapIntoPromise(runInInjectionContext(injector, () => route.loadComponent()));
const component = await maybeResolveResources(maybeUnwrapDefaultExport(loaded));
if (this.onLoadEndListener) {
this.onLoadEndListener(route);
}
(typeof ngDevMode === 'undefined' || ngDevMode) && assertStandalone(route.path ?? '', component);
route._loadedComponent = component;
return component;
} finally {
this.componentLoaders.delete(route);
}
})();
this.componentLoaders.set(route, loader);
return loader;
}
loadChildren(parentInjector, route) {
if (this.childrenLoaders.get(route)) {
return this.childrenLoaders.get(route);
} else if (route._loadedRoutes) {
return Promise.resolve({
routes: route._loadedRoutes,
injector: route._loadedInjector
});
}
if (this.onLoadStartListener) {
this.onLoadStartListener(route);
}
const loader = (async () => {
try {
const result = await loadChildren(route, this.compiler, parentInjector, this.onLoadEndListener);
route._loadedRoutes = result.routes;
route._loadedInjector = result.injector;
route._loadedNgModuleFactory = result.factory;
return result;
} finally {
this.childrenLoaders.delete(route);
}
})();
this.childrenLoaders.set(route, loader);
return loader;
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: RouterConfigLoader,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: RouterConfigLoader,
providedIn: 'root'
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: RouterConfigLoader,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}]
});
async function loadChildren(route, compiler, parentInjector, onLoadEndListener) {
const loaded = await wrapIntoPromise(runInInjectionContext(parentInjector, () => route.loadChildren()));
const t = await maybeResolveResources(maybeUnwrapDefaultExport(loaded));
let factoryOrRoutes;
if (t instanceof NgModuleFactory || Array.isArray(t)) {
factoryOrRoutes = t;
} else {
factoryOrRoutes = await compiler.compileModuleAsync(t);
}
if (onLoadEndListener) {
onLoadEndListener(route);
}
let injector;
let rawRoutes;
let requireStandaloneComponents = false;
let factory = undefined;
if (Array.isArray(factoryOrRoutes)) {
rawRoutes = factoryOrRoutes;
requireStandaloneComponents = true;
} else {
injector = factoryOrRoutes.create(parentInjector).injector;
factory = factoryOrRoutes;
rawRoutes = injector.get(ROUTES, [], {
optional: true,
self: true
}).flat();
}
const routes = rawRoutes.map(standardizeConfig);
(typeof ngDevMode === 'undefined' || ngDevMode) && validateConfig(routes, route.path, requireStandaloneComponents);
return {
routes,
injector,
factory
};
}
function isWrappedDefaultExport(value) {
return value && typeof value === 'object' && 'default' in value;
}
function maybeUnwrapDefaultExport(input) {
return isWrappedDefaultExport(input) ? input['default'] : input;
}
async function maybeResolveResources(value) {
if ((typeof ngJitMode === 'undefined' || ngJitMode) && typeof fetch === 'function') {
try {
await _resolveComponentResources(fetch);
} catch (error) {
console.error(error);
}
}
return value;
}
class UrlHandlingStrategy {
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: UrlHandlingStrategy,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: UrlHandlingStrategy,
providedIn: 'root',
useFactory: () => inject(DefaultUrlHandlingStrategy)
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: UrlHandlingStrategy,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
useFactory: () => inject(DefaultUrlHandlingStrategy)
}]
}]
});
class DefaultUrlHandlingStrategy {
shouldProcessUrl(url) {
return true;
}
extract(url) {
return url;
}
merge(newUrlPart, wholeUrl) {
return newUrlPart;
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: DefaultUrlHandlingStrategy,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: DefaultUrlHandlingStrategy,
providedIn: 'root'
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: DefaultUrlHandlingStrategy,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}]
});
const CREATE_VIEW_TRANSITION = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'view transition helper' : '');
const VIEW_TRANSITION_OPTIONS = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'view transition options' : '');
function createViewTransition(injector, from, to) {
const transitionOptions = injector.get(VIEW_TRANSITION_OPTIONS);
const document = injector.get(DOCUMENT);
if (!document.startViewTransition || transitionOptions.skipNextTransition) {
transitionOptions.skipNextTransition = false;
return new Promise(resolve => setTimeout(resolve));
}
let resolveViewTransitionStarted;
const viewTransitionStarted = new Promise(resolve => {
resolveViewTransitionStarted = resolve;
});
const transition = document.startViewTransition(() => {
resolveViewTransitionStarted();
return createRenderPromise(injector);
});
transition.updateCallbackDone.catch(error => {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
console.error(error);
}
});
transition.ready.catch(error => {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
console.error(error);
}
});
transition.finished.catch(error => {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
console.error(error);
}
});
const {
onViewTransitionCreated
} = transitionOptions;
if (onViewTransitionCreated) {
runInInjectionContext(injector, () => onViewTransitionCreated({
transition,
from,
to
}));
}
return viewTransitionStarted;
}
function createRenderPromise(injector) {
return new Promise(resolve => {
afterNextRender({
read: () => setTimeout(resolve)
}, {
injector
});
});
}
const noop = () => {};
const NAVIGATION_ERROR_HANDLER = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'navigation error handler' : '');
class NavigationTransitions {
currentNavigation = signal(null, {
...(ngDevMode ? {
debugName: "currentNavigation"
} : {}),
equal: () => false
});
currentTransition = null;
lastSuccessfulNavigation = signal(null, ...(ngDevMode ? [{
debugName: "lastSuccessfulNavigation"
}] : []));
events = new Subject();
transitionAbortWithErrorSubject = new Subject();
configLoader = inject(RouterConfigLoader);
environmentInjector = inject(EnvironmentInjector);
destroyRef = inject(DestroyRef);
urlSerializer = inject(UrlSerializer);
rootContexts = inject(ChildrenOutletContexts);
location = inject(Location);
inputBindingEnabled = inject(INPUT_BINDER, {
optional: true
}) !== null;
titleStrategy = inject(TitleStrategy);
options = inject(ROUTER_CONFIGURATION, {
optional: true
}) || {};
paramsInheritanceStrategy = this.options.paramsInheritanceStrategy || 'emptyOnly';
urlHandlingStrategy = inject(UrlHandlingStrategy);
createViewTransition = inject(CREATE_VIEW_TRANSITION, {
optional: true
});
navigationErrorHandler = inject(NAVIGATION_ERROR_HANDLER, {
optional: true
});
navigationId = 0;
get hasRequestedNavigation() {
return this.navigationId !== 0;
}
transitions;
afterPreactivation = () => of(void 0);
rootComponentType = null;
destroyed = false;
constructor() {
const onLoadStart = r => this.events.next(new RouteConfigLoadStart(r));
const onLoadEnd = r => this.events.next(new RouteConfigLoadEnd(r));
this.configLoader.onLoadEndListener = onLoadEnd;
this.configLoader.onLoadStartListener = onLoadStart;
this.destroyRef.onDestroy(() => {
this.destroyed = true;
});
}
complete() {
this.transitions?.complete();
}
handleNavigationRequest(request) {
const id = ++this.navigationId;
untracked(() => {
this.transitions?.next({
...request,
extractedUrl: this.urlHandlingStrategy.extract(request.rawUrl),
targetSnapshot: null,
targetRouterState: null,
guards: {
canActivateChecks: [],
canDeactivateChecks: []
},
guardsResult: null,
id
});
});
}
setupNavigations(router) {
this.transitions = new BehaviorSubject(null);
return this.transitions.pipe(filter(t => t !== null), switchMap(overallTransitionState => {
let completedOrAborted = false;
const abortController = new AbortController();
const shouldContinueNavigation = () => {
return !completedOrAborted && this.currentTransition?.id === overallTransitionState.id;
};
return of(overallTransitionState).pipe(switchMap(t => {
if (this.navigationId > overallTransitionState.id) {
const cancellationReason = typeof ngDevMode === 'undefined' || ngDevMode ? `Navigation ID ${overallTransitionState.id} is not equal to the current navigation id ${this.navigationId}` : '';
this.cancelNavigationTransition(overallTransitionState, cancellationReason, NavigationCancellationCode.SupersededByNewNavigation);
return EMPTY;
}
this.currentTransition = overallTransitionState;
const lastSuccessfulNavigation = this.lastSuccessfulNavigation();
this.currentNavigation.set({
id: t.id,
initialUrl: t.rawUrl,
extractedUrl: t.extractedUrl,
targetBrowserUrl: typeof t.extras.browserUrl === 'string' ? this.urlSerializer.parse(t.extras.browserUrl) : t.extras.browserUrl,
trigger: t.source,
extras: t.extras,
previousNavigation: !lastSuccessfulNavigation ? null : {
...lastSuccessfulNavigation,
previousNavigation: null
},
abort: () => abortController.abort()
});
const urlTransition = !router.navigated || this.isUpdatingInternalState() || this.isUpdatedBrowserUrl();
const onSameUrlNavigation = t.extras.onSameUrlNavigation ?? router.onSameUrlNavigation;
if (!urlTransition && onSameUrlNavigation !== 'reload') {
const reason = typeof ngDevMode === 'undefined' || ngDevMode ? `Navigation to ${t.rawUrl} was ignored because it is the same as the current Router URL.` : '';
this.events.next(new NavigationSkipped(t.id, this.urlSerializer.serialize(t.rawUrl), reason, NavigationSkippedCode.IgnoredSameUrlNavigation));
t.resolve(false);
return EMPTY;
}
if (this.urlHandlingStrategy.shouldProcessUrl(t.rawUrl)) {
return of(t).pipe(switchMap(t => {
this.events.next(new NavigationStart(t.id, this.urlSerializer.serialize(t.extractedUrl), t.source, t.restoredState));
if (t.id !== this.navigationId) {
return EMPTY;
}
return Promise.resolve(t);
}), recognize(this.environmentInjector, this.configLoader, this.rootComponentType, router.config, this.urlSerializer, this.paramsInheritanceStrategy, abortController.signal), tap(t => {
overallTransitionState.targetSnapshot = t.targetSnapshot;
overallTransitionState.urlAfterRedirects = t.urlAfterRedirects;
this.currentNavigation.update(nav => {
nav.finalUrl = t.urlAfterRedirects;
return nav;
});
const routesRecognized = new RoutesRecognized(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
this.events.next(routesRecognized);
}));
} else if (urlTransition && this.urlHandlingStrategy.shouldProcessUrl(t.currentRawUrl)) {
const {
id,
extractedUrl,
source,
restoredState,
extras
} = t;
const navStart = new NavigationStart(id, this.urlSerializer.serialize(extractedUrl), source, restoredState);
this.events.next(navStart);
const targetSnapshot = createEmptyState(this.rootComponentType, this.environmentInjector).snapshot;
this.currentTransition = overallTransitionState = {
...t,
targetSnapshot,
urlAfterRedirects: extractedUrl,
extras: {
...extras,
skipLocationChange: false,
replaceUrl: false
}
};
this.currentNavigation.update(nav => {
nav.finalUrl = extractedUrl;
return nav;
});
return of(overallTransitionState);
} else {
const reason = typeof ngDevMode === 'undefined' || ngDevMode ? `Navigation was ignored because the UrlHandlingStrategy` + ` indicated neither the current URL ${t.currentRawUrl} nor target URL ${t.rawUrl} should be processed.` : '';
this.events.next(new NavigationSkipped(t.id, this.urlSerializer.serialize(t.extractedUrl), reason, NavigationSkippedCode.IgnoredByUrlHandlingStrategy));
t.resolve(false);
return EMPTY;
}
}), map(t => {
const guardsStart = new GuardsCheckStart(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
this.events.next(guardsStart);
this.currentTransition = overallTransitionState = {
...t,
guards: getAllRouteGuards(t.targetSnapshot, t.currentSnapshot, this.rootContexts)
};
return overallTransitionState;
}), checkGuards(evt => this.events.next(evt)), switchMap(t => {
overallTransitionState.guardsResult = t.guardsResult;
if (t.guardsResult && typeof t.guardsResult !== 'boolean') {
throw redirectingNavigationError(this.urlSerializer, t.guardsResult);
}
const guardsEnd = new GuardsCheckEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot, !!t.guardsResult);
this.events.next(guardsEnd);
if (!shouldContinueNavigation()) {
return EMPTY;
}
if (!t.guardsResult) {
this.cancelNavigationTransition(t, '', NavigationCancellationCode.GuardRejected);
return EMPTY;
}
if (t.guards.canActivateChecks.length === 0) {
return of(t);
}
const resolveStart = new ResolveStart(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
this.events.next(resolveStart);
if (!shouldContinueNavigation()) {
return EMPTY;
}
let dataResolved = false;
return of(t).pipe(resolveData(this.paramsInheritanceStrategy), tap({
next: () => {
dataResolved = true;
const resolveEnd = new ResolveEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects), t.targetSnapshot);
this.events.next(resolveEnd);
},
complete: () => {
if (!dataResolved) {
this.cancelNavigationTransition(t, typeof ngDevMode === 'undefined' || ngDevMode ? `At least one route resolver didn't emit any value.` : '', NavigationCancellationCode.NoDataFromResolver);
}
}
}));
}), switchTap(t => {
const loadComponents = route => {
const loaders = [];
if (route.routeConfig?._loadedComponent) {
route.component = route.routeConfig?._loadedComponent;
} else if (route.routeConfig?.loadComponent) {
const injector = route._environmentInjector;
loaders.push(this.configLoader.loadComponent(injector, route.routeConfig).then(loadedComponent => {
route.component = loadedComponent;
}));
}
for (const child of route.children) {
loaders.push(...loadComponents(child));
}
return loaders;
};
const loaders = loadComponents(t.targetSnapshot.root);
return loaders.length === 0 ? of(t) : from(Promise.all(loaders).then(() => t));
}), switchTap(() => this.afterPreactivation()), switchMap(() => {
const {
currentSnapshot,
targetSnapshot
} = overallTransitionState;
const viewTransitionStarted = this.createViewTransition?.(this.environmentInjector, currentSnapshot.root, targetSnapshot.root);
return viewTransitionStarted ? from(viewTransitionStarted).pipe(map(() => overallTransitionState)) : of(overallTransitionState);
}), take(1), map(t => {
const targetRouterState = createRouterState(router.routeReuseStrategy, t.targetSnapshot, t.currentRouterState);
this.currentTransition = overallTransitionState = t = {
...t,
targetRouterState
};
this.currentNavigation.update(nav => {
nav.targetRouterState = targetRouterState;
return nav;
});
this.events.next(new BeforeActivateRoutes());
if (!shouldContinueNavigation()) {
return;
}
new ActivateRoutes(router.routeReuseStrategy, overallTransitionState.targetRouterState, overallTransitionState.currentRouterState, evt => this.events.next(evt), this.inputBindingEnabled).activate(this.rootContexts);
if (!shouldContinueNavigation()) {
return;
}
completedOrAborted = true;
this.currentNavigation.update(nav => {
nav.abort = noop;
return nav;
});
this.lastSuccessfulNavigation.set(untracked(this.currentNavigation));
this.events.next(new NavigationEnd(t.id, this.urlSerializer.serialize(t.extractedUrl), this.urlSerializer.serialize(t.urlAfterRedirects)));
this.titleStrategy?.updateTitle(t.targetRouterState.snapshot);
t.resolve(true);
}), takeUntil(abortSignalToObservable(abortController.signal).pipe(filter(() => !completedOrAborted && !overallTransitionState.targetRouterState), tap(() => {
this.cancelNavigationTransition(overallTransitionState, abortController.signal.reason + '', NavigationCancellationCode.Aborted);
}))), tap({
complete: () => {
completedOrAborted = true;
}
}), takeUntil(this.transitionAbortWithErrorSubject.pipe(tap(err => {
throw err;
}))), finalize(() => {
abortController.abort();
if (!completedOrAborted) {
const cancelationReason = typeof ngDevMode === 'undefined' || ngDevMode ? `Navigation ID ${overallTransitionState.id} is not equal to the current navigation id ${this.navigationId}` : '';
this.cancelNavigationTransition(overallTransitionState, cancelationReason, NavigationCancellationCode.SupersededByNewNavigation);
}
if (this.currentTransition?.id === overallTransitionState.id) {
this.currentNavigation.set(null);
this.currentTransition = null;
}
}), catchError(e => {
completedOrAborted = true;
if (this.destroyed) {
overallTransitionState.resolve(false);
return EMPTY;
}
if (isNavigationCancelingError(e)) {
this.events.next(new NavigationCancel(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e.message, e.cancellationCode));
if (!isRedirectingNavigationCancelingError(e)) {
overallTransitionState.resolve(false);
} else {
this.events.next(new RedirectRequest(e.url, e.navigationBehaviorOptions));
}
} else {
const navigationError = new NavigationError(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), e, overallTransitionState.targetSnapshot ?? undefined);
try {
const navigationErrorHandlerResult = runInInjectionContext(this.environmentInjector, () => this.navigationErrorHandler?.(navigationError));
if (navigationErrorHandlerResult instanceof RedirectCommand) {
const {
message,
cancellationCode
} = redirectingNavigationError(this.urlSerializer, navigationErrorHandlerResult);
this.events.next(new NavigationCancel(overallTransitionState.id, this.urlSerializer.serialize(overallTransitionState.extractedUrl), message, cancellationCode));
this.events.next(new RedirectRequest(navigationErrorHandlerResult.redirectTo, navigationErrorHandlerResult.navigationBehaviorOptions));
} else {
this.events.next(navigationError);
throw e;
}
} catch (ee) {
if (this.options.resolveNavigationPromiseOnError) {
overallTransitionState.resolve(false);
} else {
overallTransitionState.reject(ee);
}
}
}
return EMPTY;
}));
}));
}
cancelNavigationTransition(t, reason, code) {
const navCancel = new NavigationCancel(t.id, this.urlSerializer.serialize(t.extractedUrl), reason, code);
this.events.next(navCancel);
t.resolve(false);
}
isUpdatingInternalState() {
return this.currentTransition?.extractedUrl.toString() !== this.currentTransition?.currentUrlTree.toString();
}
isUpdatedBrowserUrl() {
const currentBrowserUrl = this.urlHandlingStrategy.extract(this.urlSerializer.parse(this.location.path(true)));
const currentNavigation = untracked(this.currentNavigation);
const targetBrowserUrl = currentNavigation?.targetBrowserUrl ?? currentNavigation?.extractedUrl;
return currentBrowserUrl.toString() !== targetBrowserUrl?.toString() && !currentNavigation?.extras.skipLocationChange;
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: NavigationTransitions,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: NavigationTransitions,
providedIn: 'root'
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: NavigationTransitions,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}],
ctorParameters: () => []
});
function isBrowserTriggeredNavigation(source) {
return source !== IMPERATIVE_NAVIGATION;
}
const ROUTE_INJECTOR_CLEANUP = new InjectionToken(typeof ngDevMode === 'undefined' || ngDevMode ? 'RouteInjectorCleanup' : '');
function routeInjectorCleanup(routeReuseStrategy, routerState, config) {
const activeRoutes = new Set();
if (routerState.snapshot.root) {
collectDescendants(routerState.snapshot.root, activeRoutes);
}
const storedHandles = routeReuseStrategy.retrieveStoredRouteHandles?.() || [];
for (const handle of storedHandles) {
const internalHandle = handle;
if (internalHandle?.route?.value?.snapshot) {
for (const snapshot of internalHandle.route.value.snapshot.pathFromRoot) {
if (snapshot.routeConfig) {
activeRoutes.add(snapshot.routeConfig);
}
}
}
}
destroyUnusedInjectors(config, activeRoutes, routeReuseStrategy, false);
}
function collectDescendants(snapshot, activeRoutes) {
if (snapshot.routeConfig) {
activeRoutes.add(snapshot.routeConfig);
}
for (const child of snapshot.children) {
collectDescendants(child, activeRoutes);
}
}
function destroyUnusedInjectors(routes, activeRoutes, strategy, inheritedForceDestroy) {
for (const route of routes) {
const shouldDestroyCurrentRoute = inheritedForceDestroy || !!((route._injector || route._loadedInjector) && !activeRoutes.has(route) && (strategy.shouldDestroyInjector?.(route) ?? false));
if (route.children) {
destroyUnusedInjectors(route.children, activeRoutes, strategy, shouldDestroyCurrentRoute);
}
if (route.loadChildren && route._loadedRoutes) {
destroyUnusedInjectors(route._loadedRoutes, activeRoutes, strategy, shouldDestroyCurrentRoute);
}
if (shouldDestroyCurrentRoute) {
if (route._injector) {
route._injector.destroy();
route._injector = undefined;
}
if (route._loadedInjector) {
route._loadedInjector.destroy();
route._loadedInjector = undefined;
}
}
}
}
function destroyDetachedRouteHandle(handle) {
const internalHandle = handle;
if (internalHandle && internalHandle.componentRef) {
internalHandle.componentRef.destroy();
}
}
class RouteReuseStrategy {
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: RouteReuseStrategy,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: RouteReuseStrategy,
providedIn: 'root',
useFactory: () => inject(DefaultRouteReuseStrategy)
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: RouteReuseStrategy,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
useFactory: () => inject(DefaultRouteReuseStrategy)
}]
}]
});
class BaseRouteReuseStrategy {
shouldDetach(route) {
return false;
}
store(route, detachedTree) {}
shouldAttach(route) {
return false;
}
retrieve(route) {
return null;
}
shouldReuseRoute(future, curr) {
return future.routeConfig === curr.routeConfig;
}
shouldDestroyInjector(route) {
return true;
}
}
class DefaultRouteReuseStrategy extends BaseRouteReuseStrategy {
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: DefaultRouteReuseStrategy,
deps: null,
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: DefaultRouteReuseStrategy,
providedIn: 'root'
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: DefaultRouteReuseStrategy,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}]
});
class StateManager {
urlSerializer = inject(UrlSerializer);
options = inject(ROUTER_CONFIGURATION, {
optional: true
}) || {};
canceledNavigationResolution = this.options.canceledNavigationResolution || 'replace';
location = inject(Location);
urlHandlingStrategy = inject(UrlHandlingStrategy);
urlUpdateStrategy = this.options.urlUpdateStrategy || 'deferred';
currentUrlTree = new UrlTree();
getCurrentUrlTree() {
return this.currentUrlTree;
}
rawUrlTree = this.currentUrlTree;
getRawUrlTree() {
return this.rawUrlTree;
}
createBrowserPath({
finalUrl,
initialUrl,
targetBrowserUrl
}) {
const rawUrl = finalUrl !== undefined ? this.urlHandlingStrategy.merge(finalUrl, initialUrl) : initialUrl;
const url = targetBrowserUrl ?? rawUrl;
const path = url instanceof UrlTree ? this.urlSerializer.serialize(url) : url;
return path;
}
commitTransition({
targetRouterState,
finalUrl,
initialUrl
}) {
if (finalUrl && targetRouterState) {
this.currentUrlTree = finalUrl;
this.rawUrlTree = this.urlHandlingStrategy.merge(finalUrl, initialUrl);
this.routerState = targetRouterState;
} else {
this.rawUrlTree = initialUrl;
}
}
routerState = createEmptyState(null, inject(EnvironmentInjector));
getRouterState() {
return this.routerState;
}
_stateMemento = this.createStateMemento();
get stateMemento() {
return this._stateMemento;
}
updateStateMemento() {
this._stateMemento = this.createStateMemento();
}
createStateMemento() {
return {
rawUrlTree: this.rawUrlTree,
currentUrlTree: this.currentUrlTree,
routerState: this.routerState
};
}
restoredState() {
return this.location.getState();
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: StateManager,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: StateManager,
providedIn: 'root',
useFactory: () => inject(HistoryStateManager)
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: StateManager,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
useFactory: () => inject(HistoryStateManager)
}]
}]
});
class HistoryStateManager extends StateManager {
currentPageId = 0;
lastSuccessfulId = -1;
get browserPageId() {
if (this.canceledNavigationResolution !== 'computed') {
return this.currentPageId;
}
return this.restoredState()?.ɵrouterPageId ?? this.currentPageId;
}
registerNonRouterCurrentEntryChangeListener(listener) {
return this.location.subscribe(event => {
if (event['type'] === 'popstate') {
setTimeout(() => {
listener(event['url'], event.state, 'popstate');
});
}
});
}
handleRouterEvent(e, currentTransition) {
if (e instanceof NavigationStart) {
this.updateStateMemento();
} else if (e instanceof NavigationSkipped) {
this.commitTransition(currentTransition);
} else if (e instanceof RoutesRecognized) {
if (this.urlUpdateStrategy === 'eager') {
if (!currentTransition.extras.skipLocationChange) {
this.setBrowserUrl(this.createBrowserPath(currentTransition), currentTransition);
}
}
} else if (e instanceof BeforeActivateRoutes) {
this.commitTransition(currentTransition);
if (this.urlUpdateStrategy === 'deferred' && !currentTransition.extras.skipLocationChange) {
this.setBrowserUrl(this.createBrowserPath(currentTransition), currentTransition);
}
} else if (e instanceof NavigationCancel && !isRedirectingEvent(e)) {
this.restoreHistory(currentTransition);
} else if (e instanceof NavigationError) {
this.restoreHistory(currentTransition, true);
} else if (e instanceof NavigationEnd) {
this.lastSuccessfulId = e.id;
this.currentPageId = this.browserPageId;
}
}
setBrowserUrl(path, {
extras,
id
}) {
const {
replaceUrl,
state
} = extras;
if (this.location.isCurrentPathEqualTo(path) || !!replaceUrl) {
const currentBrowserPageId = this.browserPageId;
const newState = {
...state,
...this.generateNgRouterState(id, currentBrowserPageId)
};
this.location.replaceState(path, '', newState);
} else {
const newState = {
...state,
...this.generateNgRouterState(id, this.browserPageId + 1)
};
this.location.go(path, '', newState);
}
}
restoreHistory(navigation, restoringFromCaughtError = false) {
if (this.canceledNavigationResolution === 'computed') {
const currentBrowserPageId = this.browserPageId;
const targetPagePosition = this.currentPageId - currentBrowserPageId;
if (targetPagePosition !== 0) {
this.location.historyGo(targetPagePosition);
} else if (this.getCurrentUrlTree() === navigation.finalUrl && targetPagePosition === 0) {
this.resetInternalState(navigation);
this.resetUrlToCurrentUrlTree();
} else ;
} else if (this.canceledNavigationResolution === 'replace') {
if (restoringFromCaughtError) {
this.resetInternalState(navigation);
}
this.resetUrlToCurrentUrlTree();
}
}
resetInternalState({
finalUrl
}) {
this.routerState = this.stateMemento.routerState;
this.currentUrlTree = this.stateMemento.currentUrlTree;
this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, finalUrl ?? this.rawUrlTree);
}
resetUrlToCurrentUrlTree() {
this.location.replaceState(this.urlSerializer.serialize(this.getRawUrlTree()), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
}
generateNgRouterState(navigationId, routerPageId) {
if (this.canceledNavigationResolution === 'computed') {
return {
navigationId,
ɵrouterPageId: routerPageId
};
}
return {
navigationId
};
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: HistoryStateManager,
deps: null,
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: HistoryStateManager,
providedIn: 'root'
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: HistoryStateManager,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}]
});
function afterNextNavigation(router, action) {
router.events.pipe(filter(e => e instanceof NavigationEnd || e instanceof NavigationCancel || e instanceof NavigationError || e instanceof NavigationSkipped), map(e => {
if (e instanceof NavigationEnd || e instanceof NavigationSkipped) {
return 0;
}
const redirecting = e instanceof NavigationCancel ? e.code === NavigationCancellationCode.Redirect || e.code === NavigationCancellationCode.SupersededByNewNavigation : false;
return redirecting ? 2 : 1;
}), filter(result => result !== 2), take(1)).subscribe(() => {
action();
});
}
const exactMatchOptions = {
paths: 'exact',
fragment: 'ignored',
matrixParams: 'ignored',
queryParams: 'exact'
};
const subsetMatchOptions = {
paths: 'subset',
fragment: 'ignored',
matrixParams: 'ignored',
queryParams: 'subset'
};
class Router {
get currentUrlTree() {
return this.stateManager.getCurrentUrlTree();
}
get rawUrlTree() {
return this.stateManager.getRawUrlTree();
}
disposed = false;
nonRouterCurrentEntryChangeSubscription;
console = inject(_Console);
stateManager = inject(StateManager);
options = inject(ROUTER_CONFIGURATION, {
optional: true
}) || {};
pendingTasks = inject(_PendingTasksInternal);
urlUpdateStrategy = this.options.urlUpdateStrategy || 'deferred';
navigationTransitions = inject(NavigationTransitions);
urlSerializer = inject(UrlSerializer);
location = inject(Location);
urlHandlingStrategy = inject(UrlHandlingStrategy);
injector = inject(EnvironmentInjector);
_events = new Subject();
get events() {
return this._events;
}
get routerState() {
return this.stateManager.getRouterState();
}
navigated = false;
routeReuseStrategy = inject(RouteReuseStrategy);
injectorCleanup = inject(ROUTE_INJECTOR_CLEANUP, {
optional: true
});
onSameUrlNavigation = this.options.onSameUrlNavigation || 'ignore';
config = inject(ROUTES, {
optional: true
})?.flat() ?? [];
componentInputBindingEnabled = !!inject(INPUT_BINDER, {
optional: true
});
currentNavigation = this.navigationTransitions.currentNavigation.asReadonly();
constructor() {
this.resetConfig(this.config);
this.navigationTransitions.setupNavigations(this).subscribe({
error: e => {}
});
this.subscribeToNavigationEvents();
}
eventsSubscription = new Subscription();
subscribeToNavigationEvents() {
const subscription = this.navigationTransitions.events.subscribe(e => {
try {
const currentTransition = this.navigationTransitions.currentTransition;
const currentNavigation = untracked(this.navigationTransitions.currentNavigation);
if (currentTransition !== null && currentNavigation !== null) {
this.stateManager.handleRouterEvent(e, currentNavigation);
if (e instanceof NavigationCancel && e.code !== NavigationCancellationCode.Redirect && e.code !== NavigationCancellationCode.SupersededByNewNavigation) {
this.navigated = true;
} else if (e instanceof NavigationEnd) {
this.navigated = true;
this.injectorCleanup?.(this.routeReuseStrategy, this.routerState, this.config);
} else if (e instanceof RedirectRequest) {
const opts = e.navigationBehaviorOptions;
const mergedTree = this.urlHandlingStrategy.merge(e.url, currentTransition.currentRawUrl);
const extras = {
scroll: currentTransition.extras.scroll,
browserUrl: currentTransition.extras.browserUrl,
info: currentTransition.extras.info,
skipLocationChange: currentTransition.extras.skipLocationChange,
replaceUrl: currentTransition.extras.replaceUrl || this.urlUpdateStrategy === 'eager' || isBrowserTriggeredNavigation(currentTransition.source),
...opts
};
this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras, {
resolve: currentTransition.resolve,
reject: currentTransition.reject,
promise: currentTransition.promise
});
}
}
if (isPublicRouterEvent(e)) {
this._events.next(e);
}
} catch (e) {
this.navigationTransitions.transitionAbortWithErrorSubject.next(e);
}
});
this.eventsSubscription.add(subscription);
}
resetRootComponentType(rootComponentType) {
this.routerState.root.component = rootComponentType;
this.navigationTransitions.rootComponentType = rootComponentType;
}
initialNavigation() {
this.setUpLocationChangeListener();
if (!this.navigationTransitions.hasRequestedNavigation) {
this.navigateToSyncWithBrowser(this.location.path(true), IMPERATIVE_NAVIGATION, this.stateManager.restoredState());
}
}
setUpLocationChangeListener() {
this.nonRouterCurrentEntryChangeSubscription ??= this.stateManager.registerNonRouterCurrentEntryChangeListener((url, state, source) => {
this.navigateToSyncWithBrowser(url, source, state);
});
}
navigateToSyncWithBrowser(url, source, state) {
const extras = {
replaceUrl: true
};
const restoredState = state?.navigationId ? state : null;
if (state) {
const stateCopy = {
...state
};
delete stateCopy.navigationId;
delete stateCopy.ɵrouterPageId;
if (Object.keys(stateCopy).length !== 0) {
extras.state = stateCopy;
}
}
const urlTree = this.parseUrl(url);
this.scheduleNavigation(urlTree, source, restoredState, extras).catch(e => {
if (this.disposed) {
return;
}
this.injector.get(_INTERNAL_APPLICATION_ERROR_HANDLER)(e);
});
}
get url() {
return this.serializeUrl(this.currentUrlTree);
}
getCurrentNavigation() {
return untracked(this.navigationTransitions.currentNavigation);
}
get lastSuccessfulNavigation() {
return this.navigationTransitions.lastSuccessfulNavigation;
}
resetConfig(config) {
(typeof ngDevMode === 'undefined' || ngDevMode) && validateConfig(config);
this.config = config.map(standardizeConfig);
this.navigated = false;
}
ngOnDestroy() {
this.dispose();
}
dispose() {
this._events.unsubscribe();
this.navigationTransitions.complete();
this.nonRouterCurrentEntryChangeSubscription?.unsubscribe();
this.nonRouterCurrentEntryChangeSubscription = undefined;
this.disposed = true;
this.eventsSubscription.unsubscribe();
}
createUrlTree(commands, navigationExtras = {}) {
const {
relativeTo,
queryParams,
fragment,
queryParamsHandling,
preserveFragment
} = navigationExtras;
const f = preserveFragment ? this.currentUrlTree.fragment : fragment;
let q = null;
switch (queryParamsHandling ?? this.options.defaultQueryParamsHandling) {
case 'merge':
q = {
...this.currentUrlTree.queryParams,
...queryParams
};
break;
case 'preserve':
q = this.currentUrlTree.queryParams;
break;
default:
q = queryParams || null;
}
if (q !== null) {
q = this.removeEmptyProps(q);
}
let relativeToUrlSegmentGroup;
try {
const relativeToSnapshot = relativeTo ? relativeTo.snapshot : this.routerState.snapshot.root;
relativeToUrlSegmentGroup = createSegmentGroupFromRoute(relativeToSnapshot);
} catch (e) {
if (typeof commands[0] !== 'string' || commands[0][0] !== '/') {
commands = [];
}
relativeToUrlSegmentGroup = this.currentUrlTree.root;
}
return createUrlTreeFromSegmentGroup(relativeToUrlSegmentGroup, commands, q, f ?? null, this.urlSerializer);
}
navigateByUrl(url, extras = {
skipLocationChange: false
}) {
const urlTree = isUrlTree(url) ? url : this.parseUrl(url);
const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
return this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras);
}
navigate(commands, extras = {
skipLocationChange: false
}) {
validateCommands(commands);
return this.navigateByUrl(this.createUrlTree(commands, extras), extras);
}
serializeUrl(url) {
return this.urlSerializer.serialize(url);
}
parseUrl(url) {
try {
return this.urlSerializer.parse(url);
} catch (e) {
this.console.warn(_formatRuntimeError(4018, ngDevMode && `Error parsing URL ${url}. Falling back to '/' instead. \n` + e));
return this.urlSerializer.parse('/');
}
}
isActive(url, matchOptions) {
let options;
if (matchOptions === true) {
options = {
...exactMatchOptions
};
} else if (matchOptions === false) {
options = {
...subsetMatchOptions
};
} else {
options = matchOptions;
}
if (isUrlTree(url)) {
return containsTree(this.currentUrlTree, url, options);
}
const urlTree = this.parseUrl(url);
return containsTree(this.currentUrlTree, urlTree, options);
}
removeEmptyProps(params) {
return Object.entries(params).reduce((result, [key, value]) => {
if (value !== null && value !== undefined) {
result[key] = value;
}
return result;
}, {});
}
scheduleNavigation(rawUrl, source, restoredState, extras, priorPromise) {
if (this.disposed) {
return Promise.resolve(false);
}
let resolve;
let reject;
let promise;
if (priorPromise) {
resolve = priorPromise.resolve;
reject = priorPromise.reject;
promise = priorPromise.promise;
} else {
promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
}
const taskId = this.pendingTasks.add();
afterNextNavigation(this, () => {
queueMicrotask(() => this.pendingTasks.remove(taskId));
});
this.navigationTransitions.handleNavigationRequest({
source,
restoredState,
currentUrlTree: this.currentUrlTree,
currentRawUrl: this.currentUrlTree,
rawUrl,
extras,
resolve: resolve,
reject: reject,
promise,
currentSnapshot: this.routerState.snapshot,
currentRouterState: this.routerState
});
return promise.catch(e => {
return Promise.reject(e);
});
}
static ɵfac = i0.ɵɵngDeclareFactory({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: Router,
deps: [],
target: i0.ɵɵFactoryTarget.Injectable
});
static ɵprov = i0.ɵɵngDeclareInjectable({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: Router,
providedIn: 'root'
});
}
i0.ɵɵngDeclareClassMetadata({
minVersion: "12.0.0",
version: "21.1.1",
ngImport: i0,
type: Router,
decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}],
ctorParameters: () => []
});
function validateCommands(commands) {
for (let i = 0; i < commands.length; i++) {
const cmd = commands[i];
if (cmd == null) {
throw new _RuntimeError(4008, (typeof ngDevMode === 'undefined' || ngDevMode) && `The requested path contains ${cmd} segment at index ${i}`);
}
}
}
export { ActivatedRoute, ActivatedRouteSnapshot, ActivationEnd, ActivationStart, BaseRouteReuseStrategy, BeforeActivateRoutes, CREATE_VIEW_TRANSITION, ChildActivationEnd, ChildActivationStart, ChildrenOutletContexts, DefaultTitleStrategy, DefaultUrlSerializer, EventType, GuardsCheckEnd, GuardsCheckStart, IMPERATIVE_NAVIGATION, INPUT_BINDER, NAVIGATION_ERROR_HANDLER, NavigationCancel, NavigationCancellationCode, NavigationEnd, NavigationError, NavigationSkipped, NavigationSkippedCode, NavigationStart, NavigationTransitions, OutletContext, PRIMARY_OUTLET, ROUTER_CONFIGURATION, ROUTER_OUTLET_DATA, ROUTES, ROUTE_INJECTOR_CLEANUP, RedirectCommand, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouteReuseStrategy, RoutedComponentInputBinder, Router, RouterConfigLoader, RouterEvent, RouterOutlet, RouterState, RouterStateSnapshot, RoutesRecognized, Scroll, StateManager, TitleStrategy, UrlHandlingStrategy, UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree, VIEW_TRANSITION_OPTIONS, afterNextNavigation, convertToParamMap, createUrlTreeFromSnapshot, createViewTransition, defaultUrlMatcher, destroyDetachedRouteHandle, exactMatchOptions, isActive, isRedirectingEvent, isUrlTree, loadChildren, routeInjectorCleanup, stringifyEvent, subsetMatchOptions, ɵEmptyOutletComponent };
//# sourceMappingURL=_router-chunk.mjs.map