@loozo/angular-router 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +565 -80
- package/builders.json +2 -2
- package/fesm2022/loozo-angular-router-_core.mjs +332 -595
- package/fesm2022/loozo-angular-router-_core.mjs.map +1 -1
- package/fesm2022/loozo-angular-router-_generated.mjs +335 -627
- package/fesm2022/loozo-angular-router-_generated.mjs.map +1 -1
- package/fesm2022/loozo-angular-router.mjs +2 -19
- package/node/_core/src/path.d.ts +17 -0
- package/node/src/builders/application.js +19 -7
- package/node/src/builders/options.js +47 -61
- package/node/src/builders/serve.js +66 -16
- package/node/src/generation/anchor.d.ts +13 -0
- package/node/src/generation/anchor.js +92 -0
- package/node/src/generation/compiler.d.ts +6 -0
- package/node/src/generation/compiler.js +68 -0
- package/node/src/generation/emit.d.ts +3 -0
- package/node/src/generation/emit.js +26 -8
- package/node/src/generation/files.d.ts +26 -0
- package/node/src/generation/files.js +14 -3
- package/node/src/generation/filesystem.d.ts +7 -0
- package/node/src/generation/filesystem.js +261 -69
- package/node/src/generation/generate.d.ts +16 -0
- package/node/src/generation/generate.js +10 -4
- package/node/src/generation/index.d.ts +16 -0
- package/node/src/generation/index.js +15 -0
- package/node/src/generation/overlay.d.ts +3 -0
- package/node/src/generation/selectors.d.ts +2 -0
- package/node/src/generation/sources.d.ts +50 -0
- package/node/src/generation/sources.js +57 -12
- package/node/src/generation/validate.d.ts +12 -0
- package/node/src/generation/validate.js +53 -57
- package/package.json +7 -2
- package/schemas/application.json +764 -20
- package/schemas/serve.json +144 -30
- package/snippets/angular.json +29 -0
- package/snippets/generated/destinations.generated.ts +126 -0
- package/snippets/generated/routes.generated.ts +35 -0
- package/snippets/src/catalog.ts +20 -0
- package/snippets/src/docs-url.ts +8 -0
- package/snippets/src/index.html +11 -0
- package/snippets/src/main.ts +6 -0
- package/snippets/src/product-url.ts +8 -0
- package/snippets/src/routes/products/$productId/page.ts +20 -0
- package/snippets/src/routes/products/$productId/route.generated.ts +24 -0
- package/snippets/src/routes/products/$productId/route.ts +7 -0
- package/snippets/src/routes/reports/$reportId/page.ts +9 -0
- package/snippets/src/routes/reports/$reportId/route.generated.ts +24 -0
- package/snippets/src/routes/reports/$reportId/route.ts +6 -0
- package/snippets/src/routes/teams/$teamId/items/$id/inputs.ts +15 -0
- package/snippets/src/routes/teams/$teamId/items/$id/links.ts +13 -0
- package/snippets/src/routes/teams/$teamId/items/$id/page.ts +9 -0
- package/snippets/src/routes/teams/$teamId/items/$id/route.generated.ts +24 -0
- package/snippets/src/routes/teams/$teamId/items/$id/route.ts +18 -0
- package/snippets/src/routes/teams/$teamId/members/$memberId/page.ts +9 -0
- package/snippets/src/routes/teams/$teamId/members/$memberId/route.generated.ts +24 -0
- package/snippets/src/routes/teams/$teamId/members/$memberId/route.ts +7 -0
- package/snippets/src/routes/teams/$teamId/old-items/$id/route.ts +13 -0
- package/snippets/src/routes/teams/$teamId/route.generated.ts +24 -0
- package/snippets/src/routes/teams/$teamId/route.ts +6 -0
- package/snippets/src/shell.ts +9 -0
- package/snippets/src/slug.ts +14 -0
- package/snippets/tsconfig.app.json +14 -0
- package/snippets/tsconfig.routes.json +5 -0
- package/types/loozo-angular-router-_core.d.ts +262 -242
- package/types/loozo-angular-router-_generated.d.ts +155 -116
- package/types/loozo-angular-router.d.ts +2 -1
- package/.npmignore +0 -3
- package/fesm2022/loozo-angular-router.mjs.map +0 -1
|
@@ -1,658 +1,366 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import { DestroyRef, computed, inject, signal } from "@angular/core";
|
|
2
|
+
import { ActivatedRoute, RedirectCommand, Router, UrlTree } from "@angular/router";
|
|
3
|
+
import { from, isObservable, map, merge } from "rxjs";
|
|
4
|
+
import { codecFallback, createUrl, routeMetadata } from "@loozo/angular-router/_core";
|
|
6
5
|
function hasIdentity(snapshot, id) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Object.hasOwn(data, "__loozoAngularRouterRouteId") &&
|
|
10
|
-
data.__loozoAngularRouterRouteId === id);
|
|
6
|
+
const data = snapshot.routeConfig?.data;
|
|
7
|
+
return !!data && Object.hasOwn(data, "__loozoAngularRouterRouteId") && data.__loozoAngularRouterRouteId === id;
|
|
11
8
|
}
|
|
12
9
|
function assertIdentity(snapshot, id) {
|
|
13
|
-
|
|
14
|
-
throw new Error(`Generated route wiring identity mismatch: ${id}`);
|
|
15
|
-
}
|
|
10
|
+
if (!hasIdentity(snapshot, id)) throw new Error(`Generated route wiring identity mismatch: ${id}`);
|
|
16
11
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
var InputError = class extends Error {
|
|
13
|
+
key;
|
|
14
|
+
reason;
|
|
15
|
+
source = "path";
|
|
16
|
+
constructor(key, reason, cause) {
|
|
17
|
+
super(`Invalid path input ${key}: ${reason}`, { cause });
|
|
18
|
+
this.key = key;
|
|
19
|
+
this.reason = reason;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
function validateRaw(key, raws, array) {
|
|
23
|
+
if (!array && raws.length === 0) throw new InputError(key, "missing");
|
|
24
|
+
if (!array && raws.length > 1) throw new InputError(key, "repeated");
|
|
25
|
+
if (raws.some((raw) => typeof raw !== "string")) throw new InputError(key, "invalid", /* @__PURE__ */ new TypeError("Raw input must be a decoded string"));
|
|
23
26
|
}
|
|
24
|
-
function
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
function parse(codec, raw) {
|
|
28
|
+
let value;
|
|
29
|
+
try {
|
|
30
|
+
value = codec.parse(raw);
|
|
31
|
+
} catch (cause) {
|
|
32
|
+
return { cause };
|
|
33
|
+
}
|
|
34
|
+
if (value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function") {
|
|
35
|
+
Promise.resolve(value).catch(() => void 0);
|
|
36
|
+
throw new TypeError("ParamCodec.parse must return its value synchronously, not a Promise");
|
|
37
|
+
}
|
|
38
|
+
return { value };
|
|
34
39
|
}
|
|
35
40
|
function pathJobs(definition, url) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
source: "path",
|
|
55
|
-
key: segment.name,
|
|
56
|
-
raws,
|
|
57
|
-
array,
|
|
58
|
-
codec: metadata.localParams[segment.name],
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
return [...local.values()];
|
|
62
|
-
}
|
|
63
|
-
function searchJobs(definition, snapshot) {
|
|
64
|
-
const metadata = routeMetadata(definition);
|
|
65
|
-
const jobs = [];
|
|
66
|
-
for (const key of Object.keys(metadata.search)) {
|
|
67
|
-
const codec = metadata.search[key];
|
|
68
|
-
const raws = snapshot.queryParamMap.getAll(key);
|
|
69
|
-
if (raws.length === 0 && codecPresence(codec) === "optional") {
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
validateRaw("search", key, raws, false);
|
|
73
|
-
jobs.push({ source: "search", key, raws, array: false, codec });
|
|
74
|
-
}
|
|
75
|
-
return jobs;
|
|
41
|
+
const metadata = routeMetadata(definition);
|
|
42
|
+
const local = /* @__PURE__ */ new Map();
|
|
43
|
+
for (let index = 0; index < metadata.localSegments.length; index += 1) {
|
|
44
|
+
const segment = metadata.localSegments[index];
|
|
45
|
+
if (segment.kind === "static") continue;
|
|
46
|
+
let raws = [];
|
|
47
|
+
const array = segment.kind === "catchall";
|
|
48
|
+
if (array) raws = url.slice(index).map((value) => value.path);
|
|
49
|
+
else if (index < url.length) raws = [url[index].path];
|
|
50
|
+
validateRaw(segment.name, raws, array);
|
|
51
|
+
local.set(segment.name, {
|
|
52
|
+
key: segment.name,
|
|
53
|
+
raws,
|
|
54
|
+
array,
|
|
55
|
+
codec: metadata.localParams[segment.name]
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return [...local.values()];
|
|
76
59
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
let value = values[0];
|
|
91
|
-
if (job.array) {
|
|
92
|
-
value = Object.freeze(values);
|
|
93
|
-
}
|
|
94
|
-
if (job.source === "path") {
|
|
95
|
-
params[job.key] = value;
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
search[job.key] = value;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
catch (cause) {
|
|
102
|
-
throw inputError(job.source, job.key, "invalid", cause);
|
|
103
|
-
}
|
|
104
|
-
})());
|
|
105
|
-
}
|
|
106
|
-
await Promise.all(pending);
|
|
107
|
-
return Object.freeze({ params: Object.freeze(params), search: Object.freeze(search) });
|
|
60
|
+
function runPathJobs(jobs) {
|
|
61
|
+
const params = Object.create(null);
|
|
62
|
+
for (const job of jobs) {
|
|
63
|
+
const values = [];
|
|
64
|
+
for (const raw of job.raws) {
|
|
65
|
+
const result = parse(job.codec, raw);
|
|
66
|
+
if ("cause" in result) throw new InputError(job.key, "invalid", result.cause);
|
|
67
|
+
values.push(result.value);
|
|
68
|
+
}
|
|
69
|
+
if (job.array) params[job.key] = Object.freeze(values);
|
|
70
|
+
else params[job.key] = values[0];
|
|
71
|
+
}
|
|
72
|
+
return Object.freeze(params);
|
|
108
73
|
}
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
snapshots.set(snapshot, result);
|
|
127
|
-
result.promise.then((value) => {
|
|
128
|
-
result.outcome = { value };
|
|
129
|
-
}, (cause) => {
|
|
130
|
-
let error = cause;
|
|
131
|
-
if (!(error instanceof Error)) {
|
|
132
|
-
error = new Error("Route input failure", { cause });
|
|
133
|
-
}
|
|
134
|
-
result.outcome = { error };
|
|
135
|
-
});
|
|
136
|
-
return result;
|
|
74
|
+
function parseSearch(definition, snapshot) {
|
|
75
|
+
const metadata = routeMetadata(definition);
|
|
76
|
+
const search = Object.create(null);
|
|
77
|
+
for (const key of Object.keys(metadata.search)) {
|
|
78
|
+
const codec = metadata.search[key];
|
|
79
|
+
const raws = snapshot.queryParamMap.getAll(key);
|
|
80
|
+
if (raws.length === 1 && typeof raws[0] === "string") {
|
|
81
|
+
const result = parse(codec, raws[0]);
|
|
82
|
+
if ("value" in result) {
|
|
83
|
+
search[key] = result.value;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const fallback = codecFallback(codec);
|
|
88
|
+
if (fallback) search[key] = fallback.value;
|
|
89
|
+
}
|
|
90
|
+
return Object.freeze(search);
|
|
137
91
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
jobs.push(...searchJobs(binding.definition(), snapshot));
|
|
160
|
-
return jobs;
|
|
161
|
-
});
|
|
92
|
+
const full = /* @__PURE__ */ new WeakMap();
|
|
93
|
+
const paths = /* @__PURE__ */ new WeakMap();
|
|
94
|
+
const matching = /* @__PURE__ */ new WeakMap();
|
|
95
|
+
function memo(cache, definition, snapshot, run) {
|
|
96
|
+
let snapshots = cache.get(definition);
|
|
97
|
+
if (!snapshots) {
|
|
98
|
+
snapshots = /* @__PURE__ */ new WeakMap();
|
|
99
|
+
cache.set(definition, snapshots);
|
|
100
|
+
}
|
|
101
|
+
let outcome = snapshots.get(snapshot);
|
|
102
|
+
if (!outcome) {
|
|
103
|
+
try {
|
|
104
|
+
outcome = { value: run() };
|
|
105
|
+
} catch (error) {
|
|
106
|
+
outcome = { error };
|
|
107
|
+
}
|
|
108
|
+
snapshots.set(snapshot, outcome);
|
|
109
|
+
}
|
|
110
|
+
if ("error" in outcome) throw outcome.error;
|
|
111
|
+
return outcome.value;
|
|
162
112
|
}
|
|
163
113
|
function parseInputs(set, id, snapshot) {
|
|
164
|
-
|
|
114
|
+
assertIdentity(snapshot, id);
|
|
115
|
+
const binding = set.records[id];
|
|
116
|
+
return memo(full, binding.definition(), snapshot, () => {
|
|
117
|
+
const jobs = [];
|
|
118
|
+
for (const ownerId of binding.owners) {
|
|
119
|
+
const definition = set.records[ownerId].definition();
|
|
120
|
+
if (!routeMetadata(definition).localSegments.some((segment) => segment.kind !== "static")) continue;
|
|
121
|
+
const owner = [...snapshot.pathFromRoot].reverse().find((record) => hasIdentity(record, ownerId));
|
|
122
|
+
if (!owner) throw new Error(`Generated route ancestor missing: ${ownerId}`);
|
|
123
|
+
assertIdentity(owner, ownerId);
|
|
124
|
+
jobs.push(...pathJobs(definition, owner.url));
|
|
125
|
+
}
|
|
126
|
+
const params = runPathJobs(jobs);
|
|
127
|
+
return Object.freeze({
|
|
128
|
+
params,
|
|
129
|
+
search: parseSearch(binding.definition(), snapshot)
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function pathInputs(set, id, snapshot) {
|
|
134
|
+
assertIdentity(snapshot, id);
|
|
135
|
+
const definition = set.records[id].definition();
|
|
136
|
+
try {
|
|
137
|
+
return { params: memo(paths, definition, snapshot, () => runPathJobs(pathJobs(definition, snapshot.url))) };
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (error instanceof InputError) return { error };
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
165
142
|
}
|
|
166
143
|
function matchingInputs(set, id, snapshot) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
144
|
+
const definition = set.records[id].definition();
|
|
145
|
+
return memo(matching, definition, snapshot, () => {
|
|
146
|
+
const path = pathInputs(set, id, snapshot);
|
|
147
|
+
if ("error" in path) return;
|
|
148
|
+
return Object.freeze({
|
|
149
|
+
params: path.params,
|
|
150
|
+
search: parseSearch(definition, snapshot)
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function callbacks(set, id) {
|
|
155
|
+
const metadata = routeMetadata(set.records[id].definition());
|
|
156
|
+
const config = metadata.config;
|
|
157
|
+
const result = {};
|
|
158
|
+
const activate = config.canActivate;
|
|
159
|
+
if (activate) result.canActivate = activate.map((callback) => (snapshot, state) => callback(parseInputs(set, id, snapshot), snapshot, state));
|
|
160
|
+
const children = config.canActivateChild;
|
|
161
|
+
if (children) result.canActivateChild = children.map((callback) => (child, state) => {
|
|
162
|
+
let parent;
|
|
163
|
+
for (let index = child.pathFromRoot.length - 2; index >= 0; index -= 1) {
|
|
164
|
+
const ancestor = child.pathFromRoot[index];
|
|
165
|
+
if (hasIdentity(ancestor, id)) {
|
|
166
|
+
parent = ancestor;
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (!parent) throw new Error(`Generated guard ancestor missing: ${id}`);
|
|
171
|
+
return callback(parseInputs(set, id, parent), child, state);
|
|
172
|
+
});
|
|
173
|
+
const matching = config.canMatch;
|
|
174
|
+
const canMatch = [];
|
|
175
|
+
if (metadata.localSegments.some((segment) => segment.kind !== "static") || Object.keys(metadata.search).length > 0) {
|
|
176
|
+
const handler = config.onInvalidParams;
|
|
177
|
+
canMatch.push((route, segments, snapshot) => {
|
|
178
|
+
const path = pathInputs(set, id, snapshot);
|
|
179
|
+
if (!("error" in path)) {
|
|
180
|
+
matchingInputs(set, id, snapshot);
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
if (!handler) return false;
|
|
184
|
+
const decision = handler(path.error, route, segments, snapshot);
|
|
185
|
+
if (isObservable(decision) || isPromiseResult(decision)) return from(decision).pipe(map(invalidParamsResult));
|
|
186
|
+
return invalidParamsResult(decision);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (matching) for (const callback of matching) canMatch.push((route, segments, snapshot) => {
|
|
190
|
+
const inputs = matchingInputs(set, id, snapshot);
|
|
191
|
+
if (inputs === void 0) return false;
|
|
192
|
+
return callback(inputs, route, segments, snapshot);
|
|
193
|
+
});
|
|
194
|
+
if (canMatch.length > 0) result.canMatch = canMatch;
|
|
195
|
+
const resolvers = config.resolve;
|
|
196
|
+
if (resolvers) {
|
|
197
|
+
const resolve = Object.create(null);
|
|
198
|
+
for (const key of Reflect.ownKeys(resolvers)) resolve[key] = (snapshot, state) => resolvers[key](parseInputs(set, id, snapshot), snapshot, state);
|
|
199
|
+
result.resolve = resolve;
|
|
200
|
+
}
|
|
201
|
+
const title = config.title;
|
|
202
|
+
if (typeof title === "function") result.title = (snapshot, state) => title(parseInputs(set, id, snapshot), snapshot, state);
|
|
203
|
+
else if (title !== void 0) result.title = title;
|
|
204
|
+
return result;
|
|
173
205
|
}
|
|
174
|
-
|
|
175
206
|
function isPromiseResult(value) {
|
|
176
|
-
|
|
207
|
+
return !!value && typeof value.then === "function";
|
|
177
208
|
}
|
|
178
|
-
function
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
let subscription;
|
|
182
|
-
inputs().then((value) => {
|
|
183
|
-
if (subscriber.closed) {
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
try {
|
|
187
|
-
const result = runInInjectionContext(injector, () => callback(value));
|
|
188
|
-
if (isObservable(result)) {
|
|
189
|
-
subscription = result.subscribe(subscriber);
|
|
190
|
-
}
|
|
191
|
-
else if (isPromiseResult(result)) {
|
|
192
|
-
subscription = from(Promise.resolve(result)).subscribe(subscriber);
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
subscriber.next(result);
|
|
196
|
-
subscriber.complete();
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
catch (error) {
|
|
200
|
-
subscriber.error(error);
|
|
201
|
-
}
|
|
202
|
-
}, (error) => subscriber.error(error));
|
|
203
|
-
return () => subscription?.unsubscribe();
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
function callbacks(set, id) {
|
|
207
|
-
const config = routeMetadata(set.records[id].definition()).config;
|
|
208
|
-
const result = {};
|
|
209
|
-
const activate = config.canActivate;
|
|
210
|
-
if (activate) {
|
|
211
|
-
result.canActivate = activate.map((callback) => (snapshot, state) => {
|
|
212
|
-
assertIdentity(snapshot, id);
|
|
213
|
-
return bridge(() => parseInputs(set, id, snapshot), (inputs) => callback(inputs, snapshot, state));
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
const children = config.canActivateChild;
|
|
217
|
-
if (children) {
|
|
218
|
-
result.canActivateChild = children.map((callback) => (child, state) => {
|
|
219
|
-
let parent;
|
|
220
|
-
// The native ancestry includes child itself; only proper ancestors can declare this guard.
|
|
221
|
-
for (let index = child.pathFromRoot.length - 2; index >= 0; index -= 1) {
|
|
222
|
-
const ancestor = child.pathFromRoot[index];
|
|
223
|
-
if (hasIdentity(ancestor, id)) {
|
|
224
|
-
parent = ancestor;
|
|
225
|
-
break;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
if (!parent) {
|
|
229
|
-
throw new Error(`Generated guard ancestor missing: ${id}`);
|
|
230
|
-
}
|
|
231
|
-
assertIdentity(parent, id);
|
|
232
|
-
return bridge(() => parseInputs(set, id, parent), (inputs) => callback(inputs, child, state));
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
const matching = config.canMatch;
|
|
236
|
-
if (matching) {
|
|
237
|
-
result.canMatch = matching.map((callback) => (route, segments, snapshot) => {
|
|
238
|
-
assertIdentity(snapshot, id);
|
|
239
|
-
return bridge(() => matchingInputs(set, id, snapshot), (inputs) => callback(inputs, route, segments, snapshot));
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
const resolvers = config.resolve;
|
|
243
|
-
if (resolvers) {
|
|
244
|
-
const resolve = Object.create(null);
|
|
245
|
-
for (const key of Reflect.ownKeys(resolvers)) {
|
|
246
|
-
resolve[key] = (snapshot, state) => {
|
|
247
|
-
assertIdentity(snapshot, id);
|
|
248
|
-
return bridge(() => parseInputs(set, id, snapshot), (inputs) => resolvers[key](inputs, snapshot, state));
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
result.resolve = resolve;
|
|
252
|
-
}
|
|
253
|
-
return result;
|
|
209
|
+
function invalidParamsResult(decision) {
|
|
210
|
+
if (decision === false || decision instanceof UrlTree || decision instanceof RedirectCommand) return decision;
|
|
211
|
+
throw new TypeError("onInvalidParams must return false, a UrlTree or a RedirectCommand");
|
|
254
212
|
}
|
|
255
213
|
function redirect(definition) {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
for (const key of Object.keys(target.search).sort()) {
|
|
308
|
-
const codec = target.search[key];
|
|
309
|
-
if (codecPresence(codec) === "optional" &&
|
|
310
|
-
(!Object.hasOwn(values, key) || values[key] === undefined)) {
|
|
311
|
-
continue;
|
|
312
|
-
}
|
|
313
|
-
const raw = codec.stringify(values[key]);
|
|
314
|
-
if (typeof raw !== "string") {
|
|
315
|
-
throw new TypeError(`Redirect search codec must stringify to a string: ${key}`);
|
|
316
|
-
}
|
|
317
|
-
replacement[key] = raw;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
// No native conversion before demanded codecs and destination stringification succeed.
|
|
321
|
-
const tree = router.parseUrl(path);
|
|
322
|
-
if (config.search.mode === "preserve") {
|
|
323
|
-
tree.queryParams = { ...snapshot.queryParams };
|
|
324
|
-
}
|
|
325
|
-
else if (config.search.mode === "replace") {
|
|
326
|
-
tree.queryParams = replacement;
|
|
327
|
-
}
|
|
328
|
-
if (config.fragment.mode === "preserve") {
|
|
329
|
-
tree.fragment = snapshot.fragment;
|
|
330
|
-
}
|
|
331
|
-
else if (config.fragment.mode === "replace") {
|
|
332
|
-
tree.fragment = config.fragment.value;
|
|
333
|
-
}
|
|
334
|
-
return tree;
|
|
335
|
-
};
|
|
214
|
+
return (snapshot) => {
|
|
215
|
+
const router = inject(Router);
|
|
216
|
+
const source = routeMetadata(definition());
|
|
217
|
+
const config = source.config.redirect;
|
|
218
|
+
const target = routeMetadata(config.to);
|
|
219
|
+
const raw = /* @__PURE__ */ new Map();
|
|
220
|
+
for (let index = 0; index < source.segments.length; index += 1) {
|
|
221
|
+
const segment = source.segments[index];
|
|
222
|
+
if (segment.kind === "scalar") raw.set(segment.name, {
|
|
223
|
+
values: snapshot.url.slice(index, index + 1).map((value) => value.path),
|
|
224
|
+
array: false
|
|
225
|
+
});
|
|
226
|
+
else if (segment.kind === "catchall") raw.set(segment.name, {
|
|
227
|
+
values: snapshot.url.slice(index).map((value) => value.path),
|
|
228
|
+
array: true
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
const jobs = [];
|
|
232
|
+
for (const key of new Set(Object.values(config.params))) {
|
|
233
|
+
const input = raw.get(key);
|
|
234
|
+
const raws = input?.values ?? [];
|
|
235
|
+
const array = input?.array ?? false;
|
|
236
|
+
validateRaw(key, raws, array);
|
|
237
|
+
jobs.push({
|
|
238
|
+
key,
|
|
239
|
+
raws,
|
|
240
|
+
array,
|
|
241
|
+
codec: source.params[key]
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
const logical = runPathJobs(jobs);
|
|
245
|
+
const params = Object.create(null);
|
|
246
|
+
for (const [key, sourceKey] of Object.entries(config.params)) params[key] = logical[sourceKey];
|
|
247
|
+
const path = createUrlForPath(config.to, params);
|
|
248
|
+
const replacement = Object.create(null);
|
|
249
|
+
if (config.search.mode === "replace") {
|
|
250
|
+
const values = config.search.values;
|
|
251
|
+
for (const key of Object.keys(target.search).sort()) {
|
|
252
|
+
if (!Object.hasOwn(values, key) || values[key] === void 0) continue;
|
|
253
|
+
const raw = target.search[key].stringify(values[key]);
|
|
254
|
+
if (typeof raw !== "string") throw new TypeError(`Redirect search codec must stringify to a string: ${key}`);
|
|
255
|
+
replacement[key] = raw;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const tree = router.parseUrl(path);
|
|
259
|
+
if (config.search.mode === "preserve") tree.queryParams = { ...snapshot.queryParams };
|
|
260
|
+
else if (config.search.mode === "replace") tree.queryParams = replacement;
|
|
261
|
+
if (config.fragment.mode === "preserve") tree.fragment = snapshot.fragment;
|
|
262
|
+
else if (config.fragment.mode === "replace") tree.fragment = config.fragment.value;
|
|
263
|
+
return tree;
|
|
264
|
+
};
|
|
336
265
|
}
|
|
337
266
|
function createUrlForPath(definition, params) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
if (!Array.isArray(values)) {
|
|
360
|
-
throw new TypeError("Redirect catchall requires an array");
|
|
361
|
-
}
|
|
362
|
-
for (const value of values) {
|
|
363
|
-
const raw = metadata.params[segment.name].stringify(value);
|
|
364
|
-
if (typeof raw !== "string") {
|
|
365
|
-
throw new TypeError("Redirect codec must stringify to a string");
|
|
366
|
-
}
|
|
367
|
-
parts.push(encode(raw));
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
return `/${parts.join("/")}`;
|
|
267
|
+
const metadata = routeMetadata(definition);
|
|
268
|
+
const parts = [];
|
|
269
|
+
function encode(raw) {
|
|
270
|
+
if (raw === "" || raw === "." || raw === "..") throw new TypeError("Invalid redirect path value");
|
|
271
|
+
return encodeURIComponent(raw).replace(/\(/g, "%28").replace(/\)/g, "%29");
|
|
272
|
+
}
|
|
273
|
+
for (const segment of metadata.segments) if (segment.kind === "static") parts.push(encode(segment.text));
|
|
274
|
+
else if (segment.kind === "scalar") {
|
|
275
|
+
const raw = metadata.params[segment.name].stringify(params[segment.name]);
|
|
276
|
+
if (typeof raw !== "string") throw new TypeError("Redirect codec must stringify to a string");
|
|
277
|
+
parts.push(encode(raw));
|
|
278
|
+
} else {
|
|
279
|
+
const values = params[segment.name];
|
|
280
|
+
if (!Array.isArray(values)) throw new TypeError("Redirect catchall requires an array");
|
|
281
|
+
for (const value of values) {
|
|
282
|
+
const raw = metadata.params[segment.name].stringify(value);
|
|
283
|
+
if (typeof raw !== "string") throw new TypeError("Redirect codec must stringify to a string");
|
|
284
|
+
parts.push(encode(raw));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return `/${parts.join("/")}`;
|
|
372
288
|
}
|
|
373
|
-
|
|
374
|
-
// Shared parsing has no view/task lifetime. Each handle owns its visibility and relevance.
|
|
375
289
|
function observeRoute(set, id) {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
let destroyed = false;
|
|
397
|
-
let release;
|
|
398
|
-
let acquiring = false;
|
|
399
|
-
function track() {
|
|
400
|
-
if (release || destroyed || acquiring) {
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
// Native add synchronously notifies stability observers before returning ownership.
|
|
404
|
-
acquiring = true;
|
|
405
|
-
const cleanup = tasks.add();
|
|
406
|
-
acquiring = false;
|
|
407
|
-
if (destroyed) {
|
|
408
|
-
cleanup();
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
release = cleanup;
|
|
412
|
-
}
|
|
413
|
-
function untrack() {
|
|
414
|
-
const cleanup = release;
|
|
415
|
-
release = undefined;
|
|
416
|
-
cleanup?.();
|
|
417
|
-
}
|
|
418
|
-
function publish() {
|
|
419
|
-
if (!visible || destroyed || !work) {
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
if (!work.outcome) {
|
|
423
|
-
paired.set({ status: "loading", value: undefined });
|
|
424
|
-
track();
|
|
425
|
-
return;
|
|
426
|
-
}
|
|
427
|
-
if ("value" in work.outcome) {
|
|
428
|
-
paired.set({ status: "resolved", value: work.outcome.value });
|
|
429
|
-
}
|
|
430
|
-
else {
|
|
431
|
-
paired.set({ status: "error", error: work.outcome.error });
|
|
432
|
-
}
|
|
433
|
-
// A synchronous paired write always precedes package task removal.
|
|
434
|
-
untrack();
|
|
435
|
-
}
|
|
436
|
-
function adopt(snapshot) {
|
|
437
|
-
assertIdentity(snapshot, id);
|
|
438
|
-
if (snapshot === survivor) {
|
|
439
|
-
return;
|
|
440
|
-
}
|
|
441
|
-
survivor = snapshot;
|
|
442
|
-
const joined = fullOperation(set, id, snapshot);
|
|
443
|
-
work = joined;
|
|
444
|
-
if (!joined.outcome) {
|
|
445
|
-
track();
|
|
446
|
-
}
|
|
447
|
-
joined.promise.then(() => {
|
|
448
|
-
if (work === joined) {
|
|
449
|
-
publish();
|
|
450
|
-
}
|
|
451
|
-
}, () => {
|
|
452
|
-
if (work === joined) {
|
|
453
|
-
publish();
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
function reconcile() {
|
|
458
|
-
const successful = router.lastSuccessfulNavigation();
|
|
459
|
-
if (successful && successful.id > commitment) {
|
|
460
|
-
commitment = successful.id;
|
|
461
|
-
adopt(activated.snapshot);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
function restore() {
|
|
465
|
-
if (destroyed) {
|
|
466
|
-
return;
|
|
467
|
-
}
|
|
468
|
-
reconcile();
|
|
469
|
-
if (!survivor) {
|
|
470
|
-
adopt(activated.snapshot);
|
|
471
|
-
}
|
|
472
|
-
const local = Object.create(null);
|
|
473
|
-
const resolvers = routeMetadata(set.records[id].definition()).config.resolve ?? {};
|
|
474
|
-
for (const key of Reflect.ownKeys(resolvers)) {
|
|
475
|
-
if (Object.hasOwn(survivor.data, key)) {
|
|
476
|
-
local[key] = survivor.data[key];
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
data.set({ status: "resolved", value: Object.freeze(local) });
|
|
480
|
-
visible = true;
|
|
481
|
-
publish();
|
|
482
|
-
}
|
|
483
|
-
function idleHandoff() {
|
|
484
|
-
queueMicrotask(() => {
|
|
485
|
-
if (destroyed || visible) {
|
|
486
|
-
return;
|
|
487
|
-
}
|
|
488
|
-
const current = router.currentNavigation();
|
|
489
|
-
const successful = router.lastSuccessfulNavigation();
|
|
490
|
-
if (!current || current.id === successful?.id) {
|
|
491
|
-
pending = undefined;
|
|
492
|
-
restore();
|
|
493
|
-
}
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
function eligible(id) {
|
|
497
|
-
const current = router.currentNavigation();
|
|
498
|
-
const successful = router.lastSuccessfulNavigation();
|
|
499
|
-
if (current && current.id > id && current.id !== successful?.id) {
|
|
500
|
-
return false;
|
|
501
|
-
}
|
|
502
|
-
return pending === undefined || pending === id;
|
|
503
|
-
}
|
|
504
|
-
// Subscribe before reading native phase: constructors can run inside event delivery.
|
|
505
|
-
const subscription = router.events.subscribe((event) => {
|
|
506
|
-
if (destroyed) {
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
if (event instanceof NavigationStart) {
|
|
510
|
-
pending = event.id;
|
|
511
|
-
visible = false;
|
|
512
|
-
reconcile();
|
|
513
|
-
paired.set({ status: "loading", value: undefined });
|
|
514
|
-
data.set({ status: "loading", value: undefined });
|
|
515
|
-
}
|
|
516
|
-
else if (event instanceof NavigationEnd) {
|
|
517
|
-
// Even an old End may expose a newer true survivor; it cannot settle a newer Start.
|
|
518
|
-
reconcile();
|
|
519
|
-
if (eligible(event.id)) {
|
|
520
|
-
pending = undefined;
|
|
521
|
-
restore();
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
else if (event instanceof NavigationCancel) {
|
|
525
|
-
reconcile();
|
|
526
|
-
if (event.code === NavigationCancellationCode.Redirect ||
|
|
527
|
-
event.code === NavigationCancellationCode.SupersededByNewNavigation) {
|
|
528
|
-
return;
|
|
529
|
-
}
|
|
530
|
-
if (eligible(event.id)) {
|
|
531
|
-
pending = undefined;
|
|
532
|
-
restore();
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
else if (event instanceof NavigationSkipped) {
|
|
536
|
-
reconcile();
|
|
537
|
-
if (eligible(event.id)) {
|
|
538
|
-
pending = undefined;
|
|
539
|
-
restore();
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
else if (event instanceof NavigationError && eligible(event.id)) {
|
|
543
|
-
reconcile();
|
|
544
|
-
pending = undefined;
|
|
545
|
-
visible = false;
|
|
546
|
-
let error = event.error;
|
|
547
|
-
if (!(error instanceof Error)) {
|
|
548
|
-
error = new Error("Navigation failure", { cause: event.error });
|
|
549
|
-
}
|
|
550
|
-
paired.set({ status: "error", error });
|
|
551
|
-
data.set({ status: "error", error });
|
|
552
|
-
untrack();
|
|
553
|
-
}
|
|
554
|
-
});
|
|
555
|
-
destroy.onDestroy(() => {
|
|
556
|
-
destroyed = true;
|
|
557
|
-
visible = false;
|
|
558
|
-
subscription.unsubscribe();
|
|
559
|
-
untrack();
|
|
560
|
-
});
|
|
561
|
-
// Synchronous task handoff prevents whenStable resolving before a missed-terminal microtask.
|
|
562
|
-
track();
|
|
563
|
-
if (!destroyed) {
|
|
564
|
-
const current = router.currentNavigation();
|
|
565
|
-
const successful = router.lastSuccessfulNavigation();
|
|
566
|
-
if (!current || current.id === successful?.id) {
|
|
567
|
-
restore();
|
|
568
|
-
}
|
|
569
|
-
else {
|
|
570
|
-
pending = current.id;
|
|
571
|
-
idleHandoff();
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
function project(key) {
|
|
575
|
-
const state = paired();
|
|
576
|
-
if (state.status === "error") {
|
|
577
|
-
return state;
|
|
578
|
-
}
|
|
579
|
-
return { status: state.status, value: state.value?.[key] };
|
|
580
|
-
}
|
|
581
|
-
return {
|
|
582
|
-
params: resourceFromSnapshots(() => project("params")),
|
|
583
|
-
search: resourceFromSnapshots(() => project("search")),
|
|
584
|
-
data: resourceFromSnapshots(() => data()),
|
|
585
|
-
};
|
|
290
|
+
const activated = inject(ActivatedRoute);
|
|
291
|
+
const router = inject(Router);
|
|
292
|
+
assertIdentity(activated.snapshot, id);
|
|
293
|
+
const snapshot = signal(activated.snapshot, ...ngDevMode ? [{ debugName: "snapshot" }] : /* istanbul ignore next */ []);
|
|
294
|
+
const subscription = merge(activated.queryParams, activated.fragment, activated.params, activated.url, activated.data, router.events).subscribe(() => {
|
|
295
|
+
snapshot.set(activated.snapshot);
|
|
296
|
+
});
|
|
297
|
+
inject(DestroyRef).onDestroy(() => subscription.unsubscribe());
|
|
298
|
+
const inputs = computed(() => parseInputs(set, id, snapshot()), ...ngDevMode ? [{ debugName: "inputs" }] : /* istanbul ignore next */ []);
|
|
299
|
+
const resolvers = routeMetadata(set.records[id].definition()).config.resolve ?? {};
|
|
300
|
+
return {
|
|
301
|
+
params: computed(() => inputs().params),
|
|
302
|
+
search: computed(() => inputs().search),
|
|
303
|
+
data: computed(() => {
|
|
304
|
+
const data = snapshot().data;
|
|
305
|
+
const own = Object.create(null);
|
|
306
|
+
for (const key of Reflect.ownKeys(resolvers)) if (Object.hasOwn(data, key)) own[key] = data[key];
|
|
307
|
+
return Object.freeze(own);
|
|
308
|
+
})
|
|
309
|
+
};
|
|
586
310
|
}
|
|
587
|
-
|
|
588
|
-
const destinations = new WeakMap();
|
|
311
|
+
const destinations = /* @__PURE__ */ new WeakMap();
|
|
589
312
|
function createDestination(getSet, id) {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
313
|
+
const destination = Object.freeze({});
|
|
314
|
+
destinations.set(destination, {
|
|
315
|
+
getSet,
|
|
316
|
+
id
|
|
317
|
+
});
|
|
318
|
+
return destination;
|
|
593
319
|
}
|
|
594
320
|
function nativeOptions(definition) {
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
321
|
+
const config = routeMetadata(definition).config;
|
|
322
|
+
const options = {};
|
|
323
|
+
for (const key of [
|
|
324
|
+
"providers",
|
|
325
|
+
"data",
|
|
326
|
+
"canDeactivate",
|
|
327
|
+
"runGuardsAndResolvers"
|
|
328
|
+
]) if (Object.hasOwn(config, key)) options[key] = config[key];
|
|
329
|
+
return options;
|
|
603
330
|
}
|
|
604
331
|
function injectGeneratedRoute(set, id) {
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
!Object.hasOwn(set.records, destination.id)) {
|
|
637
|
-
throw new TypeError("Expected a destination from the same generated set");
|
|
638
|
-
}
|
|
639
|
-
target = destination.id;
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
return createUrl(set.destinations[target](), values);
|
|
643
|
-
}
|
|
644
|
-
return {
|
|
645
|
-
params: view.params,
|
|
646
|
-
search: view.search,
|
|
647
|
-
data: view.data,
|
|
648
|
-
link: ((...args) => router.parseUrl(url(args))),
|
|
649
|
-
navigate: ((...args) => router.navigateByUrl(url(args))),
|
|
650
|
-
};
|
|
332
|
+
const router = inject(Router);
|
|
333
|
+
const view = observeRoute(set, id);
|
|
334
|
+
function url(args) {
|
|
335
|
+
if (args.length !== 1 && args.length !== 2) throw new TypeError("Expected values or a selected destination and values");
|
|
336
|
+
let target = id;
|
|
337
|
+
let values = args[0];
|
|
338
|
+
if (args.length === 2) {
|
|
339
|
+
const selector = args[0];
|
|
340
|
+
values = args[1];
|
|
341
|
+
if (typeof selector === "string") {
|
|
342
|
+
if (selector !== ".") {
|
|
343
|
+
if (Object.hasOwn(set.absolute, selector)) target = set.absolute[selector];
|
|
344
|
+
else if (Object.hasOwn(set.relative[id], selector)) target = set.relative[id][selector];
|
|
345
|
+
else throw new TypeError(`Unknown generated selector: ${selector}`);
|
|
346
|
+
}
|
|
347
|
+
} else {
|
|
348
|
+
if (typeof selector !== "object" || selector === null) throw new TypeError("Expected a literal selector or genuine generated destination");
|
|
349
|
+
const destination = destinations.get(selector);
|
|
350
|
+
if (!destination || destination.getSet() !== set || !Object.hasOwn(set.records, destination.id)) throw new TypeError("Expected a destination from the same generated set");
|
|
351
|
+
target = destination.id;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return createUrl(set.destinations[target](), values);
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
params: view.params,
|
|
358
|
+
search: view.search,
|
|
359
|
+
data: view.data,
|
|
360
|
+
link: ((...args) => router.parseUrl(url(args))),
|
|
361
|
+
navigate: ((...args) => router.navigateByUrl(url(args)))
|
|
362
|
+
};
|
|
651
363
|
}
|
|
652
|
-
|
|
653
|
-
/**
|
|
654
|
-
* Generated bundle index. Do not edit.
|
|
655
|
-
*/
|
|
656
|
-
|
|
657
364
|
export { assertIdentity, callbacks, createDestination, injectGeneratedRoute, nativeOptions, parseInputs, redirect };
|
|
658
|
-
|
|
365
|
+
|
|
366
|
+
//# sourceMappingURL=loozo-angular-router-_generated.mjs.map
|