@loozo/angular-router 0.0.2 → 0.0.3
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 +442 -79
- package/builders.json +2 -2
- package/fesm2022/loozo-angular-router-_core.mjs +348 -589
- package/fesm2022/loozo-angular-router-_core.mjs.map +1 -1
- package/fesm2022/loozo-angular-router-_generated.mjs +492 -617
- 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 +9 -6
- package/node/src/builders/options.js +38 -58
- package/node/src/builders/serve.js +51 -8
- 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/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/generate.d.ts +16 -0
- package/node/src/generation/generate.js +5 -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 +50 -10
- package/node/src/generation/validate.d.ts +12 -0
- package/node/src/generation/validate.js +38 -33
- package/package.json +7 -2
- package/schemas/application.json +743 -8
- package/schemas/serve.json +11 -32
- package/types/loozo-angular-router-_core.d.ts +159 -181
- package/types/loozo-angular-router-_generated.d.ts +131 -109
- 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,533 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Observable,
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import { DestroyRef, Injector, PendingTasks, inject, resourceFromSnapshots, runInInjectionContext, signal } from "@angular/core";
|
|
2
|
+
import { ActivatedRoute, NavigationCancel, NavigationCancellationCode, NavigationEnd, NavigationError, NavigationSkipped, NavigationStart, Router } from "@angular/router";
|
|
3
|
+
import { Observable, from, isObservable } from "rxjs";
|
|
4
|
+
import { codecPresence, 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
12
|
function inputError(source, key, reason, cause) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
return Object.assign(new Error(`Invalid ${source} input ${key}: ${reason}`, { cause }), {
|
|
14
|
+
source,
|
|
15
|
+
key,
|
|
16
|
+
reason
|
|
17
|
+
});
|
|
23
18
|
}
|
|
24
19
|
function validateRaw(source, key, raws, array) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (!array && raws.length > 1) {
|
|
29
|
-
throw inputError(source, key, "repeated");
|
|
30
|
-
}
|
|
31
|
-
if (raws.some((raw) => typeof raw !== "string")) {
|
|
32
|
-
throw inputError(source, key, "invalid", new TypeError("Raw input must be a decoded string"));
|
|
33
|
-
}
|
|
20
|
+
if (!array && raws.length === 0) throw inputError(source, key, "missing");
|
|
21
|
+
if (!array && raws.length > 1) throw inputError(source, key, "repeated");
|
|
22
|
+
if (raws.some((raw) => typeof raw !== "string")) throw inputError(source, key, "invalid", /* @__PURE__ */ new TypeError("Raw input must be a decoded string"));
|
|
34
23
|
}
|
|
35
24
|
function pathJobs(definition, url) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
key: segment.name,
|
|
56
|
-
raws,
|
|
57
|
-
array,
|
|
58
|
-
codec: metadata.localParams[segment.name],
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
return [...local.values()];
|
|
25
|
+
const metadata = routeMetadata(definition);
|
|
26
|
+
const local = /* @__PURE__ */ new Map();
|
|
27
|
+
for (let index = 0; index < metadata.localSegments.length; index += 1) {
|
|
28
|
+
const segment = metadata.localSegments[index];
|
|
29
|
+
if (segment.kind === "static") continue;
|
|
30
|
+
let raws = [];
|
|
31
|
+
const array = segment.kind === "catchall";
|
|
32
|
+
if (array) raws = url.slice(index).map((value) => value.path);
|
|
33
|
+
else if (index < url.length) raws = [url[index].path];
|
|
34
|
+
validateRaw("path", segment.name, raws, array);
|
|
35
|
+
local.set(segment.name, {
|
|
36
|
+
source: "path",
|
|
37
|
+
key: segment.name,
|
|
38
|
+
raws,
|
|
39
|
+
array,
|
|
40
|
+
codec: metadata.localParams[segment.name]
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return [...local.values()];
|
|
62
44
|
}
|
|
63
45
|
function searchJobs(definition, snapshot) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
46
|
+
const metadata = routeMetadata(definition);
|
|
47
|
+
const jobs = [];
|
|
48
|
+
for (const key of Object.keys(metadata.search)) {
|
|
49
|
+
const codec = metadata.search[key];
|
|
50
|
+
const raws = snapshot.queryParamMap.getAll(key);
|
|
51
|
+
if (raws.length === 0 && codecPresence(codec) === "optional") continue;
|
|
52
|
+
validateRaw("search", key, raws, false);
|
|
53
|
+
jobs.push({
|
|
54
|
+
source: "search",
|
|
55
|
+
key,
|
|
56
|
+
raws,
|
|
57
|
+
array: false,
|
|
58
|
+
codec
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return jobs;
|
|
76
62
|
}
|
|
77
63
|
async function runJobs(jobs) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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) });
|
|
64
|
+
const params = Object.create(null);
|
|
65
|
+
const search = Object.create(null);
|
|
66
|
+
const pending = [];
|
|
67
|
+
for (const job of jobs) pending.push((async () => {
|
|
68
|
+
try {
|
|
69
|
+
const elements = [];
|
|
70
|
+
for (const raw of job.raws) elements.push((async () => job.codec.parse(raw))());
|
|
71
|
+
const values = await Promise.all(elements);
|
|
72
|
+
let value = values[0];
|
|
73
|
+
if (job.array) value = Object.freeze(values);
|
|
74
|
+
if (job.source === "path") params[job.key] = value;
|
|
75
|
+
else search[job.key] = value;
|
|
76
|
+
} catch (cause) {
|
|
77
|
+
throw inputError(job.source, job.key, "invalid", cause);
|
|
78
|
+
}
|
|
79
|
+
})());
|
|
80
|
+
await Promise.all(pending);
|
|
81
|
+
return Object.freeze({
|
|
82
|
+
params: Object.freeze(params),
|
|
83
|
+
search: Object.freeze(search)
|
|
84
|
+
});
|
|
108
85
|
}
|
|
109
|
-
const full = new WeakMap();
|
|
110
|
-
const matching = new WeakMap();
|
|
86
|
+
const full = /* @__PURE__ */ new WeakMap();
|
|
87
|
+
const matching = /* @__PURE__ */ new WeakMap();
|
|
111
88
|
function operation(cache, definition, snapshot, collect) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
error = new Error("Route input failure", { cause });
|
|
133
|
-
}
|
|
134
|
-
result.outcome = { error };
|
|
135
|
-
});
|
|
136
|
-
return result;
|
|
89
|
+
let snapshots = cache.get(definition);
|
|
90
|
+
if (!snapshots) {
|
|
91
|
+
snapshots = /* @__PURE__ */ new WeakMap();
|
|
92
|
+
cache.set(definition, snapshots);
|
|
93
|
+
}
|
|
94
|
+
const existing = snapshots.get(snapshot);
|
|
95
|
+
if (existing) return existing;
|
|
96
|
+
const result = {
|
|
97
|
+
promise: Promise.resolve().then(() => runJobs(collect())),
|
|
98
|
+
outcome: void 0
|
|
99
|
+
};
|
|
100
|
+
snapshots.set(snapshot, result);
|
|
101
|
+
result.promise.then((value) => {
|
|
102
|
+
result.outcome = { value };
|
|
103
|
+
}, (cause) => {
|
|
104
|
+
let error = cause;
|
|
105
|
+
if (!(error instanceof Error)) error = new Error("Route input failure", { cause });
|
|
106
|
+
result.outcome = { error };
|
|
107
|
+
});
|
|
108
|
+
return result;
|
|
137
109
|
}
|
|
138
110
|
function fullOperation(set, id, snapshot) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
throw new Error(`Generated route ancestor missing: ${ownerId}`);
|
|
155
|
-
}
|
|
156
|
-
assertIdentity(owner, ownerId);
|
|
157
|
-
jobs.push(...pathJobs(definition, owner.url));
|
|
158
|
-
}
|
|
159
|
-
jobs.push(...searchJobs(binding.definition(), snapshot));
|
|
160
|
-
return jobs;
|
|
161
|
-
});
|
|
111
|
+
assertIdentity(snapshot, id);
|
|
112
|
+
const binding = set.records[id];
|
|
113
|
+
return operation(full, binding.definition(), snapshot, () => {
|
|
114
|
+
const jobs = [];
|
|
115
|
+
for (const ownerId of binding.owners) {
|
|
116
|
+
const definition = set.records[ownerId].definition();
|
|
117
|
+
if (!routeMetadata(definition).localSegments.some((segment) => segment.kind !== "static")) continue;
|
|
118
|
+
const owner = [...snapshot.pathFromRoot].reverse().find((record) => hasIdentity(record, ownerId));
|
|
119
|
+
if (!owner) throw new Error(`Generated route ancestor missing: ${ownerId}`);
|
|
120
|
+
assertIdentity(owner, ownerId);
|
|
121
|
+
jobs.push(...pathJobs(definition, owner.url));
|
|
122
|
+
}
|
|
123
|
+
jobs.push(...searchJobs(binding.definition(), snapshot));
|
|
124
|
+
return jobs;
|
|
125
|
+
});
|
|
162
126
|
}
|
|
163
127
|
function parseInputs(set, id, snapshot) {
|
|
164
|
-
|
|
128
|
+
return fullOperation(set, id, snapshot).promise;
|
|
165
129
|
}
|
|
166
130
|
function matchingInputs(set, id, snapshot) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
...pathJobs(definition, snapshot.url),
|
|
171
|
-
...searchJobs(definition, snapshot),
|
|
172
|
-
]).promise;
|
|
131
|
+
assertIdentity(snapshot, id);
|
|
132
|
+
const definition = set.records[id].definition();
|
|
133
|
+
return operation(matching, definition, snapshot, () => [...pathJobs(definition, snapshot.url), ...searchJobs(definition, snapshot)]).promise;
|
|
173
134
|
}
|
|
174
|
-
|
|
175
135
|
function isPromiseResult(value) {
|
|
176
|
-
|
|
136
|
+
return !!value && typeof value.then === "function";
|
|
177
137
|
}
|
|
178
138
|
function bridge(inputs, callback) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
catch (error) {
|
|
200
|
-
subscriber.error(error);
|
|
201
|
-
}
|
|
202
|
-
}, (error) => subscriber.error(error));
|
|
203
|
-
return () => subscription?.unsubscribe();
|
|
204
|
-
});
|
|
139
|
+
const injector = inject(Injector);
|
|
140
|
+
return new Observable((subscriber) => {
|
|
141
|
+
let subscription;
|
|
142
|
+
inputs().then((value) => {
|
|
143
|
+
if (subscriber.closed) return;
|
|
144
|
+
try {
|
|
145
|
+
const result = runInInjectionContext(injector, () => callback(value));
|
|
146
|
+
if (isObservable(result)) subscription = result.subscribe(subscriber);
|
|
147
|
+
else if (isPromiseResult(result)) subscription = from(Promise.resolve(result)).subscribe(subscriber);
|
|
148
|
+
else {
|
|
149
|
+
subscriber.next(result);
|
|
150
|
+
subscriber.complete();
|
|
151
|
+
}
|
|
152
|
+
} catch (error) {
|
|
153
|
+
subscriber.error(error);
|
|
154
|
+
}
|
|
155
|
+
}, (error) => subscriber.error(error));
|
|
156
|
+
return () => subscription?.unsubscribe();
|
|
157
|
+
});
|
|
205
158
|
}
|
|
206
159
|
function callbacks(set, id) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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;
|
|
160
|
+
const config = routeMetadata(set.records[id].definition()).config;
|
|
161
|
+
const result = {};
|
|
162
|
+
const activate = config.canActivate;
|
|
163
|
+
if (activate) result.canActivate = activate.map((callback) => (snapshot, state) => {
|
|
164
|
+
assertIdentity(snapshot, id);
|
|
165
|
+
return bridge(() => parseInputs(set, id, snapshot), (inputs) => callback(inputs, snapshot, state));
|
|
166
|
+
});
|
|
167
|
+
const children = config.canActivateChild;
|
|
168
|
+
if (children) result.canActivateChild = children.map((callback) => (child, state) => {
|
|
169
|
+
let parent;
|
|
170
|
+
for (let index = child.pathFromRoot.length - 2; index >= 0; index -= 1) {
|
|
171
|
+
const ancestor = child.pathFromRoot[index];
|
|
172
|
+
if (hasIdentity(ancestor, id)) {
|
|
173
|
+
parent = ancestor;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (!parent) throw new Error(`Generated guard ancestor missing: ${id}`);
|
|
178
|
+
assertIdentity(parent, id);
|
|
179
|
+
return bridge(() => parseInputs(set, id, parent), (inputs) => callback(inputs, child, state));
|
|
180
|
+
});
|
|
181
|
+
const matching = config.canMatch;
|
|
182
|
+
if (matching) result.canMatch = matching.map((callback) => (route, segments, snapshot) => {
|
|
183
|
+
assertIdentity(snapshot, id);
|
|
184
|
+
return bridge(() => matchingInputs(set, id, snapshot), (inputs) => callback(inputs, route, segments, snapshot));
|
|
185
|
+
});
|
|
186
|
+
const resolvers = config.resolve;
|
|
187
|
+
if (resolvers) {
|
|
188
|
+
const resolve = Object.create(null);
|
|
189
|
+
for (const key of Reflect.ownKeys(resolvers)) resolve[key] = (snapshot, state) => {
|
|
190
|
+
assertIdentity(snapshot, id);
|
|
191
|
+
return bridge(() => parseInputs(set, id, snapshot), (inputs) => resolvers[key](inputs, snapshot, state));
|
|
192
|
+
};
|
|
193
|
+
result.resolve = resolve;
|
|
194
|
+
}
|
|
195
|
+
return result;
|
|
254
196
|
}
|
|
255
197
|
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
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
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
|
-
};
|
|
198
|
+
return async (snapshot) => {
|
|
199
|
+
const router = inject(Router);
|
|
200
|
+
const source = routeMetadata(definition());
|
|
201
|
+
const config = source.config.redirect;
|
|
202
|
+
const target = routeMetadata(config.to);
|
|
203
|
+
const raw = /* @__PURE__ */ new Map();
|
|
204
|
+
for (let index = 0; index < source.segments.length; index += 1) {
|
|
205
|
+
const segment = source.segments[index];
|
|
206
|
+
if (segment.kind === "scalar") raw.set(segment.name, {
|
|
207
|
+
values: snapshot.url.slice(index, index + 1).map((value) => value.path),
|
|
208
|
+
array: false
|
|
209
|
+
});
|
|
210
|
+
else if (segment.kind === "catchall") raw.set(segment.name, {
|
|
211
|
+
values: snapshot.url.slice(index).map((value) => value.path),
|
|
212
|
+
array: true
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const jobs = [];
|
|
216
|
+
for (const key of new Set(Object.values(config.params))) {
|
|
217
|
+
const input = raw.get(key);
|
|
218
|
+
const raws = input?.values ?? [];
|
|
219
|
+
const array = input?.array ?? false;
|
|
220
|
+
validateRaw("path", key, raws, array);
|
|
221
|
+
jobs.push({
|
|
222
|
+
source: "path",
|
|
223
|
+
key,
|
|
224
|
+
raws,
|
|
225
|
+
array,
|
|
226
|
+
codec: source.params[key]
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
if (config.search.mode === "preserve") for (const key of Object.keys(target.search)) {
|
|
230
|
+
const codec = target.search[key];
|
|
231
|
+
const raws = snapshot.queryParamMap.getAll(key);
|
|
232
|
+
if (raws.length === 0 && codecPresence(codec) === "optional") continue;
|
|
233
|
+
validateRaw("search", key, raws, false);
|
|
234
|
+
jobs.push({
|
|
235
|
+
source: "search",
|
|
236
|
+
key,
|
|
237
|
+
raws,
|
|
238
|
+
array: false,
|
|
239
|
+
codec
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
const logical = await runJobs(jobs);
|
|
243
|
+
const params = Object.create(null);
|
|
244
|
+
for (const [key, sourceKey] of Object.entries(config.params)) params[key] = logical.params[sourceKey];
|
|
245
|
+
const path = createUrlForPath(config.to, params);
|
|
246
|
+
const replacement = Object.create(null);
|
|
247
|
+
if (config.search.mode === "replace") {
|
|
248
|
+
const values = config.search.values;
|
|
249
|
+
for (const key of Object.keys(target.search).sort()) {
|
|
250
|
+
const codec = target.search[key];
|
|
251
|
+
if (codecPresence(codec) === "optional" && (!Object.hasOwn(values, key) || values[key] === void 0)) continue;
|
|
252
|
+
const raw = codec.stringify(values[key]);
|
|
253
|
+
if (typeof raw !== "string") throw new TypeError(`Redirect search codec must stringify to a string: ${key}`);
|
|
254
|
+
replacement[key] = raw;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const tree = router.parseUrl(path);
|
|
258
|
+
if (config.search.mode === "preserve") tree.queryParams = { ...snapshot.queryParams };
|
|
259
|
+
else if (config.search.mode === "replace") tree.queryParams = replacement;
|
|
260
|
+
if (config.fragment.mode === "preserve") tree.fragment = snapshot.fragment;
|
|
261
|
+
else if (config.fragment.mode === "replace") tree.fragment = config.fragment.value;
|
|
262
|
+
return tree;
|
|
263
|
+
};
|
|
336
264
|
}
|
|
337
265
|
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("/")}`;
|
|
266
|
+
const metadata = routeMetadata(definition);
|
|
267
|
+
const parts = [];
|
|
268
|
+
function encode(raw) {
|
|
269
|
+
if (raw === "" || raw === "." || raw === "..") throw new TypeError("Invalid redirect path value");
|
|
270
|
+
return encodeURIComponent(raw).replace(/\(/g, "%28").replace(/\)/g, "%29");
|
|
271
|
+
}
|
|
272
|
+
for (const segment of metadata.segments) if (segment.kind === "static") parts.push(encode(segment.text));
|
|
273
|
+
else if (segment.kind === "scalar") {
|
|
274
|
+
const raw = metadata.params[segment.name].stringify(params[segment.name]);
|
|
275
|
+
if (typeof raw !== "string") throw new TypeError("Redirect codec must stringify to a string");
|
|
276
|
+
parts.push(encode(raw));
|
|
277
|
+
} else {
|
|
278
|
+
const values = params[segment.name];
|
|
279
|
+
if (!Array.isArray(values)) throw new TypeError("Redirect catchall requires an array");
|
|
280
|
+
for (const value of values) {
|
|
281
|
+
const raw = metadata.params[segment.name].stringify(value);
|
|
282
|
+
if (typeof raw !== "string") throw new TypeError("Redirect codec must stringify to a string");
|
|
283
|
+
parts.push(encode(raw));
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return `/${parts.join("/")}`;
|
|
372
287
|
}
|
|
373
|
-
|
|
374
|
-
// Shared parsing has no view/task lifetime. Each handle owns its visibility and relevance.
|
|
375
288
|
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
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
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
|
-
};
|
|
289
|
+
const activated = inject(ActivatedRoute);
|
|
290
|
+
const router = inject(Router);
|
|
291
|
+
const destroy = inject(DestroyRef);
|
|
292
|
+
const tasks = inject(PendingTasks);
|
|
293
|
+
assertIdentity(activated.snapshot, id);
|
|
294
|
+
const paired = signal({
|
|
295
|
+
status: "loading",
|
|
296
|
+
value: void 0
|
|
297
|
+
}, ...ngDevMode ? [{ debugName: "paired" }] : /* istanbul ignore next */ []);
|
|
298
|
+
const data = signal({
|
|
299
|
+
status: "loading",
|
|
300
|
+
value: void 0
|
|
301
|
+
}, ...ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []);
|
|
302
|
+
let survivor;
|
|
303
|
+
let work;
|
|
304
|
+
let commitment = -1;
|
|
305
|
+
let pending;
|
|
306
|
+
let visible = false;
|
|
307
|
+
let destroyed = false;
|
|
308
|
+
let release;
|
|
309
|
+
let acquiring = false;
|
|
310
|
+
function track() {
|
|
311
|
+
if (release || destroyed || acquiring) return;
|
|
312
|
+
acquiring = true;
|
|
313
|
+
const cleanup = tasks.add();
|
|
314
|
+
acquiring = false;
|
|
315
|
+
if (destroyed) {
|
|
316
|
+
cleanup();
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
release = cleanup;
|
|
320
|
+
}
|
|
321
|
+
function untrack() {
|
|
322
|
+
const cleanup = release;
|
|
323
|
+
release = void 0;
|
|
324
|
+
cleanup?.();
|
|
325
|
+
}
|
|
326
|
+
function publish() {
|
|
327
|
+
if (!visible || destroyed || !work) return;
|
|
328
|
+
if (!work.outcome) {
|
|
329
|
+
paired.set({
|
|
330
|
+
status: "loading",
|
|
331
|
+
value: void 0
|
|
332
|
+
});
|
|
333
|
+
track();
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
if ("value" in work.outcome) paired.set({
|
|
337
|
+
status: "resolved",
|
|
338
|
+
value: work.outcome.value
|
|
339
|
+
});
|
|
340
|
+
else paired.set({
|
|
341
|
+
status: "error",
|
|
342
|
+
error: work.outcome.error
|
|
343
|
+
});
|
|
344
|
+
untrack();
|
|
345
|
+
}
|
|
346
|
+
function adopt(snapshot) {
|
|
347
|
+
assertIdentity(snapshot, id);
|
|
348
|
+
if (snapshot === survivor) return;
|
|
349
|
+
survivor = snapshot;
|
|
350
|
+
const joined = fullOperation(set, id, snapshot);
|
|
351
|
+
work = joined;
|
|
352
|
+
if (!joined.outcome) track();
|
|
353
|
+
joined.promise.then(() => {
|
|
354
|
+
if (work === joined) publish();
|
|
355
|
+
}, () => {
|
|
356
|
+
if (work === joined) publish();
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
function reconcile() {
|
|
360
|
+
const successful = router.lastSuccessfulNavigation();
|
|
361
|
+
if (successful && successful.id > commitment) {
|
|
362
|
+
commitment = successful.id;
|
|
363
|
+
adopt(activated.snapshot);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function restore() {
|
|
367
|
+
if (destroyed) return;
|
|
368
|
+
reconcile();
|
|
369
|
+
if (!survivor) adopt(activated.snapshot);
|
|
370
|
+
const local = Object.create(null);
|
|
371
|
+
const resolvers = routeMetadata(set.records[id].definition()).config.resolve ?? {};
|
|
372
|
+
for (const key of Reflect.ownKeys(resolvers)) if (Object.hasOwn(survivor.data, key)) local[key] = survivor.data[key];
|
|
373
|
+
data.set({
|
|
374
|
+
status: "resolved",
|
|
375
|
+
value: Object.freeze(local)
|
|
376
|
+
});
|
|
377
|
+
visible = true;
|
|
378
|
+
publish();
|
|
379
|
+
}
|
|
380
|
+
function idleHandoff() {
|
|
381
|
+
queueMicrotask(() => {
|
|
382
|
+
if (destroyed || visible) return;
|
|
383
|
+
const current = router.currentNavigation();
|
|
384
|
+
const successful = router.lastSuccessfulNavigation();
|
|
385
|
+
if (!current || current.id === successful?.id) {
|
|
386
|
+
pending = void 0;
|
|
387
|
+
restore();
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
function eligible(id) {
|
|
392
|
+
const current = router.currentNavigation();
|
|
393
|
+
const successful = router.lastSuccessfulNavigation();
|
|
394
|
+
if (current && current.id > id && current.id !== successful?.id) return false;
|
|
395
|
+
return pending === void 0 || pending === id;
|
|
396
|
+
}
|
|
397
|
+
const subscription = router.events.subscribe((event) => {
|
|
398
|
+
if (destroyed) return;
|
|
399
|
+
if (event instanceof NavigationStart) {
|
|
400
|
+
pending = event.id;
|
|
401
|
+
visible = false;
|
|
402
|
+
reconcile();
|
|
403
|
+
paired.set({
|
|
404
|
+
status: "loading",
|
|
405
|
+
value: void 0
|
|
406
|
+
});
|
|
407
|
+
data.set({
|
|
408
|
+
status: "loading",
|
|
409
|
+
value: void 0
|
|
410
|
+
});
|
|
411
|
+
} else if (event instanceof NavigationEnd) {
|
|
412
|
+
reconcile();
|
|
413
|
+
if (eligible(event.id)) {
|
|
414
|
+
pending = void 0;
|
|
415
|
+
restore();
|
|
416
|
+
}
|
|
417
|
+
} else if (event instanceof NavigationCancel) {
|
|
418
|
+
reconcile();
|
|
419
|
+
if (event.code === NavigationCancellationCode.Redirect || event.code === NavigationCancellationCode.SupersededByNewNavigation) return;
|
|
420
|
+
if (eligible(event.id)) {
|
|
421
|
+
pending = void 0;
|
|
422
|
+
restore();
|
|
423
|
+
}
|
|
424
|
+
} else if (event instanceof NavigationSkipped) {
|
|
425
|
+
reconcile();
|
|
426
|
+
if (eligible(event.id)) {
|
|
427
|
+
pending = void 0;
|
|
428
|
+
restore();
|
|
429
|
+
}
|
|
430
|
+
} else if (event instanceof NavigationError && eligible(event.id)) {
|
|
431
|
+
reconcile();
|
|
432
|
+
pending = void 0;
|
|
433
|
+
visible = false;
|
|
434
|
+
let error = event.error;
|
|
435
|
+
if (!(error instanceof Error)) error = new Error("Navigation failure", { cause: event.error });
|
|
436
|
+
paired.set({
|
|
437
|
+
status: "error",
|
|
438
|
+
error
|
|
439
|
+
});
|
|
440
|
+
data.set({
|
|
441
|
+
status: "error",
|
|
442
|
+
error
|
|
443
|
+
});
|
|
444
|
+
untrack();
|
|
445
|
+
}
|
|
446
|
+
});
|
|
447
|
+
destroy.onDestroy(() => {
|
|
448
|
+
destroyed = true;
|
|
449
|
+
visible = false;
|
|
450
|
+
subscription.unsubscribe();
|
|
451
|
+
untrack();
|
|
452
|
+
});
|
|
453
|
+
track();
|
|
454
|
+
if (!destroyed) {
|
|
455
|
+
const current = router.currentNavigation();
|
|
456
|
+
const successful = router.lastSuccessfulNavigation();
|
|
457
|
+
if (!current || current.id === successful?.id) restore();
|
|
458
|
+
else {
|
|
459
|
+
pending = current.id;
|
|
460
|
+
idleHandoff();
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
function project(key) {
|
|
464
|
+
const state = paired();
|
|
465
|
+
if (state.status === "error") return state;
|
|
466
|
+
return {
|
|
467
|
+
status: state.status,
|
|
468
|
+
value: state.value?.[key]
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
return {
|
|
472
|
+
params: resourceFromSnapshots(() => project("params")),
|
|
473
|
+
search: resourceFromSnapshots(() => project("search")),
|
|
474
|
+
data: resourceFromSnapshots(() => data())
|
|
475
|
+
};
|
|
586
476
|
}
|
|
587
|
-
|
|
588
|
-
const destinations = new WeakMap();
|
|
477
|
+
const destinations = /* @__PURE__ */ new WeakMap();
|
|
589
478
|
function createDestination(getSet, id) {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
479
|
+
const destination = Object.freeze({});
|
|
480
|
+
destinations.set(destination, {
|
|
481
|
+
getSet,
|
|
482
|
+
id
|
|
483
|
+
});
|
|
484
|
+
return destination;
|
|
593
485
|
}
|
|
594
486
|
function nativeOptions(definition) {
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
487
|
+
const config = routeMetadata(definition).config;
|
|
488
|
+
const options = {};
|
|
489
|
+
for (const key of [
|
|
490
|
+
"providers",
|
|
491
|
+
"title",
|
|
492
|
+
"data",
|
|
493
|
+
"canDeactivate",
|
|
494
|
+
"runGuardsAndResolvers"
|
|
495
|
+
]) if (Object.hasOwn(config, key)) options[key] = config[key];
|
|
496
|
+
return options;
|
|
603
497
|
}
|
|
604
498
|
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
|
-
};
|
|
499
|
+
const router = inject(Router);
|
|
500
|
+
const view = observeRoute(set, id);
|
|
501
|
+
function url(args) {
|
|
502
|
+
if (args.length !== 1 && args.length !== 2) throw new TypeError("Expected values or a selected destination and values");
|
|
503
|
+
let target = id;
|
|
504
|
+
let values = args[0];
|
|
505
|
+
if (args.length === 2) {
|
|
506
|
+
const selector = args[0];
|
|
507
|
+
values = args[1];
|
|
508
|
+
if (typeof selector === "string") {
|
|
509
|
+
if (selector !== ".") {
|
|
510
|
+
if (Object.hasOwn(set.absolute, selector)) target = set.absolute[selector];
|
|
511
|
+
else if (Object.hasOwn(set.relative[id], selector)) target = set.relative[id][selector];
|
|
512
|
+
else throw new TypeError(`Unknown generated selector: ${selector}`);
|
|
513
|
+
}
|
|
514
|
+
} else {
|
|
515
|
+
if (typeof selector !== "object" || selector === null) throw new TypeError("Expected a literal selector or genuine generated destination");
|
|
516
|
+
const destination = destinations.get(selector);
|
|
517
|
+
if (!destination || destination.getSet() !== set || !Object.hasOwn(set.records, destination.id)) throw new TypeError("Expected a destination from the same generated set");
|
|
518
|
+
target = destination.id;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return createUrl(set.destinations[target](), values);
|
|
522
|
+
}
|
|
523
|
+
return {
|
|
524
|
+
params: view.params,
|
|
525
|
+
search: view.search,
|
|
526
|
+
data: view.data,
|
|
527
|
+
link: ((...args) => router.parseUrl(url(args))),
|
|
528
|
+
navigate: ((...args) => router.navigateByUrl(url(args)))
|
|
529
|
+
};
|
|
651
530
|
}
|
|
652
|
-
|
|
653
|
-
/**
|
|
654
|
-
* Generated bundle index. Do not edit.
|
|
655
|
-
*/
|
|
656
|
-
|
|
657
531
|
export { assertIdentity, callbacks, createDestination, injectGeneratedRoute, nativeOptions, parseInputs, redirect };
|
|
658
|
-
|
|
532
|
+
|
|
533
|
+
//# sourceMappingURL=loozo-angular-router-_generated.mjs.map
|