@askrjs/askr 0.3.0 → 0.4.0
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/CHANGELOG.md +874 -0
- package/README.md +61 -29
- package/capabilities.json +19 -9
- package/dist/actions/index.js +56 -12
- package/dist/benchmark.js +10 -15
- package/dist/boot/index.d.ts +3 -2
- package/dist/boot/index.js +1 -1
- package/dist/boot-DaoTYoCw.js +3989 -0
- package/dist/browser-activity-CB8e-V4f.js +220 -0
- package/dist/components/index.d.ts +8 -1
- package/dist/components/index.js +1 -43
- package/dist/{aria-hKjThHcp.js → compose-ref-DWzdbxsD.js} +41 -4
- package/dist/control/index.d.ts +2 -0
- package/dist/control/index.js +1 -1
- package/dist/control-nfpT2fbK.js +209 -0
- package/dist/core.d.ts +5 -9
- package/dist/csp-nonce-DwGw1A6Q.js +35 -0
- package/dist/data/index.js +3 -3
- package/dist/{data-2edW0jhF.js → data-BCwClJiF.js} +283 -94
- package/dist/data-runtime-C1bFAlba.js +242 -0
- package/dist/{deferred-CbgNhf67.js → deferred-bEEHHvic.js} +42 -20
- package/dist/domains/actions.d.ts +8 -3
- package/dist/domains/component.d.ts +1 -107
- package/dist/domains/context.d.ts +0 -15
- package/dist/domains/control.d.ts +36 -249
- package/dist/domains/data.d.ts +31 -13
- package/dist/domains/diagnostics.d.ts +1 -2
- package/dist/domains/lifecycle.d.ts +2 -5
- package/dist/domains/refs.d.ts +0 -2
- package/dist/domains/routing.d.ts +43 -8
- package/dist/domains/scheduler.d.ts +1 -76
- package/dist/domains/server.d.ts +5 -2
- package/dist/domains/state.d.ts +2 -5
- package/dist/domains/telemetry.d.ts +0 -2
- package/dist/elements.d.ts +214 -51
- package/dist/error-boundary-Bpwofwps.js +293 -0
- package/dist/foundations/icon/index.d.ts +0 -58
- package/dist/foundations/icon/index.js +2 -2
- package/dist/foundations/index.js +2 -1
- package/dist/foundations/interactions/index.js +1 -1
- package/dist/foundations/state/index.d.ts +3 -3
- package/dist/foundations/state/index.js +5 -3
- package/dist/foundations/structures/index.js +2 -1
- package/dist/foundations/utilities/index.d.ts +2 -0
- package/dist/foundations/utilities/index.js +1 -2
- package/dist/fx/index.d.ts +31 -58
- package/dist/fx/index.js +313 -195
- package/dist/hooks-BimKStr4.js +202 -0
- package/dist/index.d.ts +11 -74
- package/dist/index.js +8 -447
- package/dist/instance-BAnfmXOR.js +988 -0
- package/dist/{interactions-CTeACdT_.js → interactions-D2BoREb-.js} +3 -2
- package/dist/jsx-dev-runtime.d.ts +41 -18
- package/dist/jsx-dev-runtime.js +1 -6
- package/dist/{jsx-runtime-CPJXAOBF.js → jsx-runtime-C4idqHY0.js} +18 -7
- package/dist/jsx-runtime.js +1 -1
- package/dist/jsx.d.ts +61 -37
- package/dist/{manifest-D1P3UNWV.js → manifest-CW9gyNBY.js} +3 -3
- package/dist/{navigate-prC5V8XV.js → navigate-CP_0Zy5U.js} +454 -87
- package/dist/navigation.d.ts +12 -3
- package/dist/peer-types.d.ts +8 -0
- package/dist/portal-DuOKfnLa.js +349 -0
- package/dist/promise-Dz8iIHAm.js +16 -0
- package/dist/query-registry-WMCN0BJL.js +320 -0
- package/dist/readable-DFWOsTac.js +21 -0
- package/dist/{render-context-B7ohlh6t.js → render-context-DGHnEveC.js} +27 -11
- package/dist/render-sync-IC5lMFpq.js +1240 -0
- package/dist/resolution-Cx82-xjW.js +1244 -0
- package/dist/resource-CLjB7RBQ.js +377 -0
- package/dist/resources/index.d.ts +21 -11
- package/dist/resources/index.js +45 -244
- package/dist/router/index.d.ts +14 -5
- package/dist/router/index.js +22 -53
- package/dist/scope-CwpVSHVf.js +55 -0
- package/dist/{shared-kU8yvryp.js → shared-O2ZnmYAf.js} +1 -7
- package/dist/{snapshot-source-An4iKajG.js → snapshot-Cjx4N988.js} +6 -1
- package/dist/ssg/index.d.ts +1 -2
- package/dist/ssg/index.js +5 -13
- package/dist/ssr/index.d.ts +26 -28
- package/dist/ssr/index.js +4 -4
- package/dist/{ssr-CiNm6Vzl.js → ssr-BJ8ug7zH.js} +133 -122
- package/dist/ssr-DoV-vJ-5.js +229 -0
- package/dist/state-DWO1KzkX.js +232 -0
- package/dist/structures-D4dDMqHX.js +231 -0
- package/dist/testing/index.d.ts +8 -4
- package/dist/testing/index.js +29 -34
- package/dist/url-CnbfpX0K.js +185 -0
- package/dist/utilities.d.ts +48 -2
- package/dist/verify-hydration-DpVaDnqz.js +152 -0
- package/package.json +19 -9
- package/dist/access-CEA2pOry.js +0 -1046
- package/dist/activity-oy2YFTFF.js +0 -201
- package/dist/boot-BMBMWUGI.js +0 -1084
- package/dist/capabilities-Bbf0mlp9.js +0 -42
- package/dist/compose-ref-v0qGlHoN.js +0 -26
- package/dist/control-BR_mrX__.js +0 -173
- package/dist/control-C-ApnFs1.js +0 -20
- package/dist/csp-nonce-BfFWcd0w.js +0 -173
- package/dist/data-runtime-CxoY98lX.js +0 -149
- package/dist/default-portal-runtime-DvMvWJVp.js +0 -20
- package/dist/dom-renderer.d.ts +0 -77
- package/dist/domains/renderer.d.ts +0 -127
- package/dist/eager-control.d.ts +0 -8
- package/dist/effect-C3Zsc1k6.js +0 -292
- package/dist/for-state-BDykeOJL.js +0 -1753
- package/dist/instance-VAFYVJOa.js +0 -1027
- package/dist/notify-DxxuDPeY.js +0 -266
- package/dist/portal-w3oQ6oQU.js +0 -29
- package/dist/query-registry-LrYpQsDJ.js +0 -83
- package/dist/render-resolved-BC0W7_5b.js +0 -1123
- package/dist/renderer-CT0HeY58.js +0 -8623
- package/dist/resolution-3DskUkjG.js +0 -577
- package/dist/resource-18-sFRl9.js +0 -344
- package/dist/route-matching-CUzZ31gT.js +0 -551
- package/dist/router-internal-7nuNEHfG.js +0 -36
- package/dist/scope-Cq_iYbTR.js +0 -403
- package/dist/selector-BSPVkjKP.js +0 -311
- package/dist/ssr-EPjwJH5R.js +0 -29
- package/dist/state-BXJfudq1.js +0 -91
- package/dist/structures-CjEzfj4h.js +0 -654
- package/dist/timer-C7uqnJVt.js +0 -85
- package/dist/verify-hydration-ikaxotf7.js +0 -27
- package/dist/vnode-D24p6IW2.js +0 -7
|
@@ -1,577 +0,0 @@
|
|
|
1
|
-
import { P as isPromiseLike, m as defineScope, v as readScope } from "./instance-VAFYVJOa.js";
|
|
2
|
-
import { n as Fragment, t as ELEMENT_TYPE } from "./jsx-DRS-qjiN.js";
|
|
3
|
-
import { S as withPageFramework, b as replacePageRoute, n as getActiveRenderContext } from "./render-context-B7ohlh6t.js";
|
|
4
|
-
import { t as ROUTE_ROOT_COMPONENT } from "./router-internal-7nuNEHfG.js";
|
|
5
|
-
import { c as withTelemetry, t as createQueryPrefetchContext } from "./query-registry-LrYpQsDJ.js";
|
|
6
|
-
import { c as removeRouteBasePath, i as getMatchingRouteRecord, l as buildRouteContext, o as addRouteBasePath, s as normalizeRouteBasePath, u as buildRouteContextBase, y as getActiveRouteAuthOptions } from "./route-matching-CUzZ31gT.js";
|
|
7
|
-
//#region src/common/deferred-value.ts
|
|
8
|
-
const DEFERRED_VALUE = Symbol.for("@askrjs/askr/deferred-value");
|
|
9
|
-
const DEFERRED_BOUNDARY = Symbol.for("@askrjs/askr/deferred-boundary");
|
|
10
|
-
/** Wrap a promise as a {@link Deferred} value that tracks its settled state and result. */
|
|
11
|
-
function defer(promise) {
|
|
12
|
-
let state = "pending";
|
|
13
|
-
let value;
|
|
14
|
-
let error;
|
|
15
|
-
const normalized = Promise.resolve(promise);
|
|
16
|
-
normalized.then((resolved) => {
|
|
17
|
-
state = "fulfilled";
|
|
18
|
-
value = resolved;
|
|
19
|
-
}, (reason) => {
|
|
20
|
-
state = "rejected";
|
|
21
|
-
error = reason;
|
|
22
|
-
});
|
|
23
|
-
return Object.freeze(Object.defineProperties({}, {
|
|
24
|
-
state: {
|
|
25
|
-
enumerable: true,
|
|
26
|
-
get: () => state
|
|
27
|
-
},
|
|
28
|
-
value: {
|
|
29
|
-
enumerable: true,
|
|
30
|
-
get: () => value
|
|
31
|
-
},
|
|
32
|
-
error: {
|
|
33
|
-
enumerable: true,
|
|
34
|
-
get: () => error
|
|
35
|
-
},
|
|
36
|
-
promise: { value: normalized },
|
|
37
|
-
[DEFERRED_VALUE]: { value: true }
|
|
38
|
-
}));
|
|
39
|
-
}
|
|
40
|
-
/** Check whether `value` is a {@link Deferred} produced by {@link defer}. */
|
|
41
|
-
function isDeferred(value) {
|
|
42
|
-
if (!value || typeof value !== "object") return false;
|
|
43
|
-
const marker = Object.getOwnPropertyDescriptor(value, DEFERRED_VALUE);
|
|
44
|
-
return Boolean(marker && "value" in marker && marker.value === true);
|
|
45
|
-
}
|
|
46
|
-
/** @internal Reconstruct settled server data without importing deferred rendering. */
|
|
47
|
-
function reviveDeferredValue(state, value, error) {
|
|
48
|
-
const promise = state === "fulfilled" ? Promise.resolve(value) : Promise.reject(error);
|
|
49
|
-
if (state === "rejected") promise.catch(() => void 0);
|
|
50
|
-
return Object.freeze(Object.defineProperties({}, {
|
|
51
|
-
state: {
|
|
52
|
-
enumerable: true,
|
|
53
|
-
value: state
|
|
54
|
-
},
|
|
55
|
-
value: {
|
|
56
|
-
enumerable: true,
|
|
57
|
-
value
|
|
58
|
-
},
|
|
59
|
-
error: {
|
|
60
|
-
enumerable: true,
|
|
61
|
-
value: error
|
|
62
|
-
},
|
|
63
|
-
promise: { value: promise },
|
|
64
|
-
[DEFERRED_VALUE]: { value: true }
|
|
65
|
-
}));
|
|
66
|
-
}
|
|
67
|
-
//#endregion
|
|
68
|
-
//#region src/router/route-hydration.ts
|
|
69
|
-
function isDeferredHydrationValue(value) {
|
|
70
|
-
return isDeferred(value);
|
|
71
|
-
}
|
|
72
|
-
const omissionGuards = /* @__PURE__ */ new WeakMap();
|
|
73
|
-
function propertyPath(parent, key) {
|
|
74
|
-
if (/^(?:0|[1-9]\d*)$/.test(key)) return `${parent}[${key}]`;
|
|
75
|
-
if (/^[A-Za-z_$][\w$]*$/.test(key)) return `${parent}.${key}`;
|
|
76
|
-
return `${parent}[${JSON.stringify(key)}]`;
|
|
77
|
-
}
|
|
78
|
-
function invalid(route, path, reason) {
|
|
79
|
-
throw new TypeError(`[Askr] Route hydration data for "${route}" at "${path}" is not JSON transport-safe: ${reason}. Return JSON-compatible data or use route(..., { dehydrate(data) { ... } }) to omit server-only values.`);
|
|
80
|
-
}
|
|
81
|
-
function objectLabel(value) {
|
|
82
|
-
if (value instanceof Date) return "Date";
|
|
83
|
-
if (value instanceof Map) return "Map";
|
|
84
|
-
if (value instanceof Set) return "Set";
|
|
85
|
-
const constructor = value.constructor;
|
|
86
|
-
return typeof constructor === "function" && constructor.name ? constructor.name : "class instance";
|
|
87
|
-
}
|
|
88
|
-
/** Validate the exact value that will enter the route hydration envelope. */
|
|
89
|
-
function validateRouteHydrationData(value, route, path = "$", ancestors = /* @__PURE__ */ new Set()) {
|
|
90
|
-
if (value === null || typeof value === "string" || typeof value === "boolean") return;
|
|
91
|
-
if (typeof value === "number") {
|
|
92
|
-
if (!Number.isFinite(value)) invalid(route, path, "non-finite numbers are not supported");
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
if (typeof value === "undefined") invalid(route, path, "undefined is not supported");
|
|
96
|
-
if (typeof value === "bigint") invalid(route, path, "bigint is not supported");
|
|
97
|
-
if (typeof value === "symbol") invalid(route, path, "symbols are not supported");
|
|
98
|
-
if (typeof value === "function") invalid(route, path, "functions are not supported");
|
|
99
|
-
const object = value;
|
|
100
|
-
if (isDeferredHydrationValue(object)) {
|
|
101
|
-
if (object.state === "fulfilled") validateRouteHydrationData(object.value, route, `${path}.value`, ancestors);
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
if (ancestors.has(object)) invalid(route, path, "cyclic references are not supported");
|
|
105
|
-
ancestors.add(object);
|
|
106
|
-
try {
|
|
107
|
-
if (Array.isArray(object)) {
|
|
108
|
-
for (let index = 0; index < object.length; index += 1) if (!Object.prototype.hasOwnProperty.call(object, index)) invalid(route, `${path}[${index}]`, "sparse arrays are not supported");
|
|
109
|
-
for (const key of Reflect.ownKeys(object)) {
|
|
110
|
-
if (key === "length") continue;
|
|
111
|
-
if (typeof key === "symbol") invalid(route, path, "symbol-keyed properties are not supported");
|
|
112
|
-
const descriptor = Object.getOwnPropertyDescriptor(object, key);
|
|
113
|
-
if (!descriptor.enumerable) invalid(route, propertyPath(path, key), "non-enumerable properties are not supported");
|
|
114
|
-
if (!("value" in descriptor)) invalid(route, propertyPath(path, key), "accessors are not supported");
|
|
115
|
-
if (!/^(?:0|[1-9]\d*)$/.test(key) || Number(key) >= object.length) invalid(route, propertyPath(path, key), "named array properties are not supported");
|
|
116
|
-
validateRouteHydrationData(descriptor.value, route, propertyPath(path, key), ancestors);
|
|
117
|
-
}
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
const prototype = Object.getPrototypeOf(object);
|
|
121
|
-
if (prototype !== Object.prototype && prototype !== null) invalid(route, path, `${objectLabel(object)} instances are not supported; use a plain object`);
|
|
122
|
-
for (const key of Reflect.ownKeys(object)) {
|
|
123
|
-
if (typeof key === "symbol") invalid(route, path, "symbol-keyed properties are not supported");
|
|
124
|
-
const descriptor = Object.getOwnPropertyDescriptor(object, key);
|
|
125
|
-
const childPath = propertyPath(path, key);
|
|
126
|
-
if (!descriptor.enumerable) invalid(route, childPath, "non-enumerable properties are not supported");
|
|
127
|
-
if (!("value" in descriptor)) invalid(route, childPath, "accessors are not supported");
|
|
128
|
-
validateRouteHydrationData(descriptor.value, route, childPath, ancestors);
|
|
129
|
-
}
|
|
130
|
-
} finally {
|
|
131
|
-
ancestors.delete(object);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
function omissionMap(complete, selected, ancestors = /* @__PURE__ */ new Set()) {
|
|
135
|
-
if (!complete || typeof complete !== "object" || isDeferredHydrationValue(complete)) return void 0;
|
|
136
|
-
if (ancestors.has(complete)) return void 0;
|
|
137
|
-
ancestors.add(complete);
|
|
138
|
-
const selectedObject = selected && typeof selected === "object" ? selected : void 0;
|
|
139
|
-
const output = Object.create(null);
|
|
140
|
-
try {
|
|
141
|
-
for (const key of Object.keys(complete)) {
|
|
142
|
-
if (!selectedObject || !Object.prototype.hasOwnProperty.call(selectedObject, key)) {
|
|
143
|
-
output[key] = 1;
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
const completeDescriptor = Object.getOwnPropertyDescriptor(complete, key);
|
|
147
|
-
const selectedDescriptor = Object.getOwnPropertyDescriptor(selectedObject, key);
|
|
148
|
-
if (!completeDescriptor || !selectedDescriptor) continue;
|
|
149
|
-
if (!("value" in completeDescriptor) || !("value" in selectedDescriptor)) continue;
|
|
150
|
-
const nested = omissionMap(completeDescriptor.value, selectedDescriptor.value, ancestors);
|
|
151
|
-
if (nested) output[key] = nested;
|
|
152
|
-
}
|
|
153
|
-
} finally {
|
|
154
|
-
ancestors.delete(complete);
|
|
155
|
-
}
|
|
156
|
-
return Object.keys(output).length > 0 ? Object.freeze(output) : void 0;
|
|
157
|
-
}
|
|
158
|
-
function prepareRouteHydrationData(complete, dehydrate, context, route = context.href || context.pathname) {
|
|
159
|
-
const selected = dehydrate ? dehydrate(complete, context) : complete;
|
|
160
|
-
if (isPromiseLike(selected)) throw new TypeError(`[Askr] Route dehydrate() for "${route}" returned a Promise. dehydrate(data, context) must be synchronous.`);
|
|
161
|
-
validateRouteHydrationData(selected, route);
|
|
162
|
-
return {
|
|
163
|
-
data: selected,
|
|
164
|
-
metadata: Object.freeze({
|
|
165
|
-
r: route,
|
|
166
|
-
...dehydrate ? { o: omissionMap(complete, selected) } : {}
|
|
167
|
-
})
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
function readMetadata(framework) {
|
|
171
|
-
const value = framework["rh"];
|
|
172
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
173
|
-
const metadata = value;
|
|
174
|
-
return typeof metadata.r === "string" ? metadata : void 0;
|
|
175
|
-
}
|
|
176
|
-
function omittedRead(route, path) {
|
|
177
|
-
throw new Error(`[Askr] routeData() read "${path}" on the initial hydration of "${route}", but that branch was intentionally omitted by dehydrate(). Keep initial hydrated rendering within the selected data, or wait for a client navigation that reruns the loader with the complete result.`);
|
|
178
|
-
}
|
|
179
|
-
function guardOmissions(value, omissions, route, path = "$") {
|
|
180
|
-
if (!omissions || !value || typeof value !== "object" || isDeferredHydrationValue(value)) return value;
|
|
181
|
-
let guards = omissionGuards.get(value);
|
|
182
|
-
if (!guards) {
|
|
183
|
-
guards = /* @__PURE__ */ new WeakMap();
|
|
184
|
-
omissionGuards.set(value, guards);
|
|
185
|
-
}
|
|
186
|
-
const cached = guards.get(omissions);
|
|
187
|
-
if (cached) return cached;
|
|
188
|
-
const guarded = new Proxy(value, { get(target, property, receiver) {
|
|
189
|
-
if (typeof property === "string") {
|
|
190
|
-
const omitted = omissions[property];
|
|
191
|
-
if (omitted && !Object.prototype.hasOwnProperty.call(target, property)) omittedRead(route, propertyPath(path, property));
|
|
192
|
-
const child = Reflect.get(target, property, receiver);
|
|
193
|
-
return omitted === 1 ? child : guardOmissions(child, omitted, route, propertyPath(path, property));
|
|
194
|
-
}
|
|
195
|
-
return Reflect.get(target, property, receiver);
|
|
196
|
-
} });
|
|
197
|
-
guards.set(omissions, guarded);
|
|
198
|
-
return guarded;
|
|
199
|
-
}
|
|
200
|
-
function guardHydratedRouteData(value, framework) {
|
|
201
|
-
const metadata = readMetadata(framework);
|
|
202
|
-
return metadata ? guardOmissions(value, metadata.o, metadata.r) : value;
|
|
203
|
-
}
|
|
204
|
-
function getRouteHydrationMetadata(framework) {
|
|
205
|
-
return readMetadata(framework);
|
|
206
|
-
}
|
|
207
|
-
/** @internal Remove initial-only omission guards after a client loader reruns. */
|
|
208
|
-
function withoutRouteHydrationMetadata(framework) {
|
|
209
|
-
if (!framework || !("rh" in framework)) return framework;
|
|
210
|
-
const next = { ...framework };
|
|
211
|
-
delete next["rh"];
|
|
212
|
-
return next;
|
|
213
|
-
}
|
|
214
|
-
//#endregion
|
|
215
|
-
//#region src/router/route-data-loader.ts
|
|
216
|
-
/** Thrown when a route's `loader` rejects; wraps the original `cause`. */
|
|
217
|
-
var RouteDataLoadError = class extends Error {
|
|
218
|
-
constructor(route, phase, cause) {
|
|
219
|
-
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
220
|
-
super("[Askr] Route data loader failed for \"" + route + "\" during " + phase + " loading: " + detail);
|
|
221
|
-
this.name = "RouteDataLoadError";
|
|
222
|
-
this.route = route;
|
|
223
|
-
this.phase = phase;
|
|
224
|
-
this.cause = cause;
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
function isAbortError(error) {
|
|
228
|
-
return typeof error === "object" && error !== null && "name" in error && error.name === "AbortError";
|
|
229
|
-
}
|
|
230
|
-
function loadPhase(mode) {
|
|
231
|
-
if (mode === "spa") return "client";
|
|
232
|
-
if (mode === "ssg") return "ssg";
|
|
233
|
-
return "server";
|
|
234
|
-
}
|
|
235
|
-
/** @internal Add route context to failures from lazyRouteData(). */
|
|
236
|
-
function _wrapRouteDataLoadError(error, context) {
|
|
237
|
-
if (error instanceof RouteDataLoadError || isAbortError(error)) throw error;
|
|
238
|
-
throw new RouteDataLoadError(context.href || context.pathname, loadPhase(context.mode), error);
|
|
239
|
-
}
|
|
240
|
-
//#endregion
|
|
241
|
-
//#region src/router/lazy.ts
|
|
242
|
-
const pendingLazy = /* @__PURE__ */ new Set();
|
|
243
|
-
const lazyStates = /* @__PURE__ */ new WeakMap();
|
|
244
|
-
const handlerLazyComponents = /* @__PURE__ */ new WeakMap();
|
|
245
|
-
function startLazyLoad(state) {
|
|
246
|
-
if (state.promise) return state.promise;
|
|
247
|
-
let promise;
|
|
248
|
-
promise = Promise.resolve().then(state.factory).then((mod) => {
|
|
249
|
-
state.resolved = typeof mod === "function" ? mod : mod.default;
|
|
250
|
-
state.loadError = null;
|
|
251
|
-
state.hasLoadError = false;
|
|
252
|
-
}, (err) => {
|
|
253
|
-
state.loadError = err;
|
|
254
|
-
state.hasLoadError = true;
|
|
255
|
-
}).finally(() => {
|
|
256
|
-
if (state.hasLoadError) state.promise = null;
|
|
257
|
-
pendingLazy.delete(promise);
|
|
258
|
-
});
|
|
259
|
-
state.promise = promise;
|
|
260
|
-
pendingLazy.add(promise);
|
|
261
|
-
return promise;
|
|
262
|
-
}
|
|
263
|
-
/** Wrap a dynamic-import factory as a {@link LazyRouteComponent}, loaded on first use. */
|
|
264
|
-
function lazy(factory) {
|
|
265
|
-
const state = {
|
|
266
|
-
factory,
|
|
267
|
-
promise: null,
|
|
268
|
-
resolved: null,
|
|
269
|
-
loadError: null,
|
|
270
|
-
hasLoadError: false
|
|
271
|
-
};
|
|
272
|
-
const component = ((params) => {
|
|
273
|
-
if (state.hasLoadError) throw state.loadError;
|
|
274
|
-
if (!state.resolved) throw new Error("lazy() component used before it was resolved. Matched routes load automatically; call component.preload() for explicit preloading.");
|
|
275
|
-
return state.resolved(params);
|
|
276
|
-
});
|
|
277
|
-
Object.defineProperty(component, "preload", { value: () => startLazyLoad(state) });
|
|
278
|
-
lazyStates.set(component, state);
|
|
279
|
-
return component;
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Create a cached route loader backed by a dynamic import. The module is only
|
|
283
|
-
* requested when the owning route matches, unless preload() is called.
|
|
284
|
-
*/
|
|
285
|
-
function lazyRouteData(factory, select) {
|
|
286
|
-
let imported = null;
|
|
287
|
-
const load = () => {
|
|
288
|
-
if (imported) return imported;
|
|
289
|
-
imported = Promise.resolve().then(factory).catch((error) => {
|
|
290
|
-
imported = null;
|
|
291
|
-
throw error;
|
|
292
|
-
});
|
|
293
|
-
return imported;
|
|
294
|
-
};
|
|
295
|
-
const loader = ((context) => load().then((module) => select ? select(module, context) : module).catch((error) => _wrapRouteDataLoadError(error, context)));
|
|
296
|
-
Object.defineProperty(loader, "preload", { value: () => load().then(() => void 0) });
|
|
297
|
-
return loader;
|
|
298
|
-
}
|
|
299
|
-
function _preloadRouteRecord(record) {
|
|
300
|
-
const imports = [
|
|
301
|
-
record.component,
|
|
302
|
-
...record.pageChain.map((scope) => scope.component),
|
|
303
|
-
...record.layoutChain.map((scope) => scope.component)
|
|
304
|
-
].flatMap((component) => {
|
|
305
|
-
const state = lazyStates.get(component);
|
|
306
|
-
return state ? [startLazyLoad(state)] : [];
|
|
307
|
-
});
|
|
308
|
-
return imports.length > 0 ? Promise.all(imports).then(() => void 0) : null;
|
|
309
|
-
}
|
|
310
|
-
function _associateLazyHandler(handler, components) {
|
|
311
|
-
handlerLazyComponents.set(handler, components);
|
|
312
|
-
}
|
|
313
|
-
function _preloadRouteHandler(handler) {
|
|
314
|
-
const imports = (handlerLazyComponents.get(handler) ?? []).flatMap((component) => {
|
|
315
|
-
const state = lazyStates.get(component);
|
|
316
|
-
return state ? [startLazyLoad(state)] : [];
|
|
317
|
-
});
|
|
318
|
-
return imports.length > 0 ? Promise.all(imports).then(() => void 0) : null;
|
|
319
|
-
}
|
|
320
|
-
//#endregion
|
|
321
|
-
//#region src/router/rendering.ts
|
|
322
|
-
const outletScope = defineScope(null);
|
|
323
|
-
/** Renders the nested route content for the enclosing layout or page scope. */
|
|
324
|
-
function Outlet() {
|
|
325
|
-
return {
|
|
326
|
-
$$typeof: ELEMENT_TYPE,
|
|
327
|
-
type: Fragment,
|
|
328
|
-
props: { children: readScope(outletScope) },
|
|
329
|
-
key: null
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
function applyPageChain(pageChain, params, content, deferComponents = false) {
|
|
333
|
-
let nextContent = content;
|
|
334
|
-
for (let i = pageChain.length - 1; i >= 0; i--) nextContent = outletScope({
|
|
335
|
-
value: nextContent,
|
|
336
|
-
children: deferComponents ? createRouteComponentVNode(pageChain[i].component, params) : pageChain[i].component(params)
|
|
337
|
-
});
|
|
338
|
-
return nextContent;
|
|
339
|
-
}
|
|
340
|
-
function createRouteComponentVNode(component, params, routeRoot = false) {
|
|
341
|
-
return {
|
|
342
|
-
$$typeof: ELEMENT_TYPE,
|
|
343
|
-
type: component,
|
|
344
|
-
props: params,
|
|
345
|
-
key: null,
|
|
346
|
-
...routeRoot ? { [ROUTE_ROOT_COMPONENT]: true } : {}
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
function createRouteHandler(component, pageChain, layoutChain, deferComponents = false) {
|
|
350
|
-
const handler = (params) => {
|
|
351
|
-
let content = deferComponents ? createRouteComponentVNode(component, params, true) : component(params);
|
|
352
|
-
content = applyPageChain(pageChain, params, content, deferComponents);
|
|
353
|
-
for (let i = layoutChain.length - 1; i >= 0; i--) {
|
|
354
|
-
const layout = layoutChain[i].component;
|
|
355
|
-
content = layout({ children: content });
|
|
356
|
-
}
|
|
357
|
-
return content;
|
|
358
|
-
};
|
|
359
|
-
_associateLazyHandler(handler, [
|
|
360
|
-
component,
|
|
361
|
-
...pageChain.map((scope) => scope.component),
|
|
362
|
-
...layoutChain.map((scope) => scope.component)
|
|
363
|
-
]);
|
|
364
|
-
return handler;
|
|
365
|
-
}
|
|
366
|
-
function getRenderHandler(record) {
|
|
367
|
-
return record.renderHandler ?? createRouteHandler(record.component, record.pageChain, record.layoutChain, true);
|
|
368
|
-
}
|
|
369
|
-
let clientAuth = Object.freeze({
|
|
370
|
-
authenticated: false,
|
|
371
|
-
principal: null,
|
|
372
|
-
session: null,
|
|
373
|
-
tenant: null
|
|
374
|
-
});
|
|
375
|
-
/** Return the identity resolved for the route currently being rendered. */
|
|
376
|
-
function currentAuth() {
|
|
377
|
-
return getActiveRenderContext()?.authContext ?? clientAuth;
|
|
378
|
-
}
|
|
379
|
-
/** @internal Updated atomically with route resolution. */
|
|
380
|
-
function setCurrentAuth(context) {
|
|
381
|
-
clientAuth = context;
|
|
382
|
-
const render = getActiveRenderContext();
|
|
383
|
-
if (render) render.authContext = context;
|
|
384
|
-
}
|
|
385
|
-
//#endregion
|
|
386
|
-
//#region src/router/resolution.ts
|
|
387
|
-
const anonymous = () => ({
|
|
388
|
-
authenticated: false,
|
|
389
|
-
principal: null,
|
|
390
|
-
session: null,
|
|
391
|
-
tenant: null
|
|
392
|
-
});
|
|
393
|
-
const routeRenderContexts = /* @__PURE__ */ new WeakMap();
|
|
394
|
-
const routeRenderData = /* @__PURE__ */ new WeakMap();
|
|
395
|
-
function getRouteRenderContext(result) {
|
|
396
|
-
return routeRenderContexts.get(result);
|
|
397
|
-
}
|
|
398
|
-
function getRouteRenderData(result) {
|
|
399
|
-
return routeRenderData.get(result);
|
|
400
|
-
}
|
|
401
|
-
/** Router-owned inspection of the record selected by request resolution. */
|
|
402
|
-
function resolvedRouteHasLoader(result) {
|
|
403
|
-
return typeof result.record?.options?.loader === "function";
|
|
404
|
-
}
|
|
405
|
-
function createRouteRenderResult(record, params, context, handler) {
|
|
406
|
-
const result = {
|
|
407
|
-
kind: "render",
|
|
408
|
-
handler,
|
|
409
|
-
params
|
|
410
|
-
};
|
|
411
|
-
Object.defineProperty(result, "record", {
|
|
412
|
-
value: record,
|
|
413
|
-
enumerable: false
|
|
414
|
-
});
|
|
415
|
-
routeRenderContexts.set(result, context);
|
|
416
|
-
return result;
|
|
417
|
-
}
|
|
418
|
-
function getDefaultRouteMode() {
|
|
419
|
-
return typeof window !== "undefined" ? "spa" : "ssr";
|
|
420
|
-
}
|
|
421
|
-
function withoutInitialRouteHydrationMetadata(envelope) {
|
|
422
|
-
return withPageFramework(envelope, withoutRouteHydrationMetadata(envelope.framework) ?? {});
|
|
423
|
-
}
|
|
424
|
-
/** @internal Bind resolved loader output to one route subtree and its hydration envelope. */
|
|
425
|
-
function bindResolvedRouteData(handler, data, hydration) {
|
|
426
|
-
return (params, context) => {
|
|
427
|
-
const renderContext = getActiveRenderContext();
|
|
428
|
-
if (renderContext) {
|
|
429
|
-
const envelope = replacePageRoute(renderContext.renderData, data);
|
|
430
|
-
renderContext.renderData = hydration ? envelope : withoutInitialRouteHydrationMetadata(envelope);
|
|
431
|
-
const hydrationEnvelope = replacePageRoute(renderContext.hydrationData, hydration?.data ?? data);
|
|
432
|
-
renderContext.hydrationData = hydration ? withPageFramework(hydrationEnvelope, {
|
|
433
|
-
...hydrationEnvelope.framework,
|
|
434
|
-
["rh"]: hydration.metadata
|
|
435
|
-
}) : withoutInitialRouteHydrationMetadata(hydrationEnvelope);
|
|
436
|
-
}
|
|
437
|
-
return handler(params, context);
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
function hasRouteRenderData(result) {
|
|
441
|
-
return routeRenderData.has(result);
|
|
442
|
-
}
|
|
443
|
-
function buildRenderResult(record, params, context, request, telemetry, load) {
|
|
444
|
-
const lazyImport = _preloadRouteRecord(record);
|
|
445
|
-
if (lazyImport) return lazyImport.then(() => buildLoadedRenderResult(record, params, context, request, telemetry, load));
|
|
446
|
-
return buildLoadedRenderResult(record, params, context, request, telemetry, load);
|
|
447
|
-
}
|
|
448
|
-
function buildLoadedRenderResult(record, params, context, request, telemetry, load) {
|
|
449
|
-
const renderHandler = getRenderHandler(record);
|
|
450
|
-
const loader = context.mode !== "ssg" && load ? record.options?.loader : void 0;
|
|
451
|
-
const preload = record.options?.preload;
|
|
452
|
-
const active = getActiveRenderContext();
|
|
453
|
-
const prefetch = active?.queryPrefetch ?? createQueryPrefetchContext({
|
|
454
|
-
mode: context.mode === "ssg" ? "ssr" : context.mode,
|
|
455
|
-
request,
|
|
456
|
-
signal: context.signal,
|
|
457
|
-
runtime: active?.dataRuntime,
|
|
458
|
-
telemetry
|
|
459
|
-
});
|
|
460
|
-
const runPreload = preload ? Promise.resolve(preload({
|
|
461
|
-
...context,
|
|
462
|
-
params,
|
|
463
|
-
request,
|
|
464
|
-
data: prefetch
|
|
465
|
-
})).then(() => void 0) : void 0;
|
|
466
|
-
if (loader) {
|
|
467
|
-
const load = () => withTelemetry(telemetry?.loader, { route: record.path }, () => loader({
|
|
468
|
-
...context,
|
|
469
|
-
params,
|
|
470
|
-
request
|
|
471
|
-
}));
|
|
472
|
-
const loaded = runPreload ? runPreload.then(load) : load();
|
|
473
|
-
const finalize = (data) => {
|
|
474
|
-
const hydration = context.mode === "ssr" ? prepareRouteHydrationData(data, record.options?.dehydrate, {
|
|
475
|
-
...context,
|
|
476
|
-
params,
|
|
477
|
-
request
|
|
478
|
-
}, context.href || context.pathname || record.path) : void 0;
|
|
479
|
-
const result = createRouteRenderResult(record, params, context, bindResolvedRouteData(renderHandler, data, hydration));
|
|
480
|
-
routeRenderData.set(result, data);
|
|
481
|
-
return result;
|
|
482
|
-
};
|
|
483
|
-
return isPromiseLike(loaded) ? Promise.resolve(loaded).then(finalize) : finalize(loaded);
|
|
484
|
-
}
|
|
485
|
-
if (runPreload) return runPreload.then(() => createRouteRenderResult(record, params, context, renderHandler));
|
|
486
|
-
return createRouteRenderResult(record, params, context, renderHandler);
|
|
487
|
-
}
|
|
488
|
-
function runPolicies(policies, context, record, params, request, telemetry, load, start = 0) {
|
|
489
|
-
for (let index = start; index < policies.length; index += 1) {
|
|
490
|
-
const result = policies[index](context);
|
|
491
|
-
if (isPromiseLike(result)) return Promise.resolve(result).then((decision) => decision.kind === "allow" ? runPolicies(policies, context, record, params, request, telemetry, load, index + 1) : decision);
|
|
492
|
-
if (result.kind !== "allow") return result;
|
|
493
|
-
}
|
|
494
|
-
return buildRenderResult(record, params, context, request, telemetry, load);
|
|
495
|
-
}
|
|
496
|
-
function resolvePath(value, fallback, context) {
|
|
497
|
-
return typeof value === "function" ? value(context) : value ?? fallback;
|
|
498
|
-
}
|
|
499
|
-
function appendNext(path, href) {
|
|
500
|
-
const target = new URL(path, "http://localhost");
|
|
501
|
-
target.searchParams.set("next", href);
|
|
502
|
-
return `${target.pathname}${target.search}${target.hash}`;
|
|
503
|
-
}
|
|
504
|
-
function mapAuthDecision(decision, context, options) {
|
|
505
|
-
if (decision.allowed) return { kind: "allow" };
|
|
506
|
-
if (decision.reason === "forbidden") return {
|
|
507
|
-
kind: "deny",
|
|
508
|
-
status: 403
|
|
509
|
-
};
|
|
510
|
-
const target = resolvePath(decision.reason === "unauthenticated" ? options?.loginPath : options?.authenticatedRedirectTo, decision.reason === "unauthenticated" ? "/login" : "/", context);
|
|
511
|
-
const finalize = (path) => ({
|
|
512
|
-
kind: "redirect",
|
|
513
|
-
to: decision.reason === "unauthenticated" ? appendNext(path, context.href) : path,
|
|
514
|
-
replace: decision.reason === "unauthenticated" ? context.mode === "spa" : true
|
|
515
|
-
});
|
|
516
|
-
return isPromiseLike(target) ? Promise.resolve(target).then(finalize) : finalize(target);
|
|
517
|
-
}
|
|
518
|
-
function resolveMatchedRoute(record, params, context, authOptions, request, telemetry, load) {
|
|
519
|
-
const continueResolution = (decision) => {
|
|
520
|
-
if (decision) {
|
|
521
|
-
const access = mapAuthDecision(decision, context, authOptions);
|
|
522
|
-
if (isPromiseLike(access)) return Promise.resolve(access).then((next) => next.kind === "allow" ? runPolicies(record.options.policies ?? [], context, record, params, request, telemetry, load) : next);
|
|
523
|
-
if (access.kind !== "allow") return access;
|
|
524
|
-
}
|
|
525
|
-
return runPolicies(record.options.policies ?? [], context, record, params, request, telemetry, load);
|
|
526
|
-
};
|
|
527
|
-
if (!record.options.auth) return continueResolution();
|
|
528
|
-
const decision = record.options.auth(context.auth);
|
|
529
|
-
return isPromiseLike(decision) ? Promise.resolve(decision).then(continueResolution) : continueResolution(decision);
|
|
530
|
-
}
|
|
531
|
-
/**
|
|
532
|
-
* Callers may omit `signal`, and `RouteRequestOptions.signal` is optional in the
|
|
533
|
-
* published contract. Route context still needs an `AbortSignal`, so this stands
|
|
534
|
-
* in for "this caller supplied no cancellation". It never aborts: a route loader
|
|
535
|
-
* receiving it cannot be cancelled through `context.signal`. Prefer passing a
|
|
536
|
-
* real signal.
|
|
537
|
-
*/
|
|
538
|
-
const NEVER_ABORTED = new AbortController().signal;
|
|
539
|
-
/** Resolve `target` against a route registry, applying auth/policies to produce a render/redirect/deny result. */
|
|
540
|
-
function resolveRouteRequest(target, options) {
|
|
541
|
-
if (!options?.registry) throw new TypeError("resolveRouteRequest requires options.registry.");
|
|
542
|
-
const basePath = normalizeRouteBasePath(options.registry.manifest.basePath);
|
|
543
|
-
const logicalTarget = removeRouteBasePath(target, basePath);
|
|
544
|
-
if (logicalTarget === void 0) return null;
|
|
545
|
-
return withTelemetry(options.telemetry?.routeMatch, {}, () => {
|
|
546
|
-
const records = options.registry.manifest.records;
|
|
547
|
-
const match = getMatchingRouteRecord(logicalTarget, records);
|
|
548
|
-
if (!match) return null;
|
|
549
|
-
const mode = options.mode ?? getDefaultRouteMode();
|
|
550
|
-
const signal = options.signal ?? getActiveRenderContext()?.signal ?? NEVER_ABORTED;
|
|
551
|
-
const authOptions = getActiveRouteAuthOptions(options.auth ?? options.registry.manifest.auth);
|
|
552
|
-
const base = buildRouteContextBase(logicalTarget, match.params, {
|
|
553
|
-
mode,
|
|
554
|
-
signal
|
|
555
|
-
});
|
|
556
|
-
const exposeRedirect = (result) => result?.kind === "redirect" ? {
|
|
557
|
-
...result,
|
|
558
|
-
to: addRouteBasePath(result.to, basePath)
|
|
559
|
-
} : result;
|
|
560
|
-
const finalize = (authContext) => {
|
|
561
|
-
if (!signal.aborted) setCurrentAuth(authContext);
|
|
562
|
-
const result = resolveMatchedRoute(match.record, match.params, buildRouteContext(logicalTarget, match.params, {
|
|
563
|
-
mode,
|
|
564
|
-
signal,
|
|
565
|
-
authContext
|
|
566
|
-
}), authOptions, options.request, options.telemetry, options.load !== false);
|
|
567
|
-
if (!basePath) return result;
|
|
568
|
-
return isPromiseLike(result) ? Promise.resolve(result).then(exposeRedirect) : exposeRedirect(result);
|
|
569
|
-
};
|
|
570
|
-
if (options.authContext) return finalize(options.authContext);
|
|
571
|
-
if (!authOptions?.resolve) return finalize(anonymous());
|
|
572
|
-
const resolved = authOptions.resolve(base);
|
|
573
|
-
return isPromiseLike(resolved) ? Promise.resolve(resolved).then(finalize) : finalize(resolved);
|
|
574
|
-
});
|
|
575
|
-
}
|
|
576
|
-
//#endregion
|
|
577
|
-
export { reviveDeferredValue as C, isDeferred as S, prepareRouteHydrationData as _, resolveRouteRequest as a, DEFERRED_BOUNDARY as b, Outlet as c, _preloadRouteHandler as d, lazy as f, guardHydratedRouteData as g, getRouteHydrationMetadata as h, hasRouteRenderData as i, createRouteHandler as l, RouteDataLoadError as m, getRouteRenderContext as n, resolvedRouteHasLoader as o, lazyRouteData as p, getRouteRenderData as r, currentAuth as s, bindResolvedRouteData as t, getRenderHandler as u, validateRouteHydrationData as v, defer as x, withoutRouteHydrationMetadata as y };
|