@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.
Files changed (123) hide show
  1. package/CHANGELOG.md +874 -0
  2. package/README.md +61 -29
  3. package/capabilities.json +19 -9
  4. package/dist/actions/index.js +56 -12
  5. package/dist/benchmark.js +10 -15
  6. package/dist/boot/index.d.ts +3 -2
  7. package/dist/boot/index.js +1 -1
  8. package/dist/boot-DaoTYoCw.js +3989 -0
  9. package/dist/browser-activity-CB8e-V4f.js +220 -0
  10. package/dist/components/index.d.ts +8 -1
  11. package/dist/components/index.js +1 -43
  12. package/dist/{aria-hKjThHcp.js → compose-ref-DWzdbxsD.js} +41 -4
  13. package/dist/control/index.d.ts +2 -0
  14. package/dist/control/index.js +1 -1
  15. package/dist/control-nfpT2fbK.js +209 -0
  16. package/dist/core.d.ts +5 -9
  17. package/dist/csp-nonce-DwGw1A6Q.js +35 -0
  18. package/dist/data/index.js +3 -3
  19. package/dist/{data-2edW0jhF.js → data-BCwClJiF.js} +283 -94
  20. package/dist/data-runtime-C1bFAlba.js +242 -0
  21. package/dist/{deferred-CbgNhf67.js → deferred-bEEHHvic.js} +42 -20
  22. package/dist/domains/actions.d.ts +8 -3
  23. package/dist/domains/component.d.ts +1 -107
  24. package/dist/domains/context.d.ts +0 -15
  25. package/dist/domains/control.d.ts +36 -249
  26. package/dist/domains/data.d.ts +31 -13
  27. package/dist/domains/diagnostics.d.ts +1 -2
  28. package/dist/domains/lifecycle.d.ts +2 -5
  29. package/dist/domains/refs.d.ts +0 -2
  30. package/dist/domains/routing.d.ts +43 -8
  31. package/dist/domains/scheduler.d.ts +1 -76
  32. package/dist/domains/server.d.ts +5 -2
  33. package/dist/domains/state.d.ts +2 -5
  34. package/dist/domains/telemetry.d.ts +0 -2
  35. package/dist/elements.d.ts +214 -51
  36. package/dist/error-boundary-Bpwofwps.js +293 -0
  37. package/dist/foundations/icon/index.d.ts +0 -58
  38. package/dist/foundations/icon/index.js +2 -2
  39. package/dist/foundations/index.js +2 -1
  40. package/dist/foundations/interactions/index.js +1 -1
  41. package/dist/foundations/state/index.d.ts +3 -3
  42. package/dist/foundations/state/index.js +5 -3
  43. package/dist/foundations/structures/index.js +2 -1
  44. package/dist/foundations/utilities/index.d.ts +2 -0
  45. package/dist/foundations/utilities/index.js +1 -2
  46. package/dist/fx/index.d.ts +31 -58
  47. package/dist/fx/index.js +313 -195
  48. package/dist/hooks-BimKStr4.js +202 -0
  49. package/dist/index.d.ts +11 -74
  50. package/dist/index.js +8 -447
  51. package/dist/instance-BAnfmXOR.js +988 -0
  52. package/dist/{interactions-CTeACdT_.js → interactions-D2BoREb-.js} +3 -2
  53. package/dist/jsx-dev-runtime.d.ts +41 -18
  54. package/dist/jsx-dev-runtime.js +1 -6
  55. package/dist/{jsx-runtime-CPJXAOBF.js → jsx-runtime-C4idqHY0.js} +18 -7
  56. package/dist/jsx-runtime.js +1 -1
  57. package/dist/jsx.d.ts +61 -37
  58. package/dist/{manifest-D1P3UNWV.js → manifest-CW9gyNBY.js} +3 -3
  59. package/dist/{navigate-prC5V8XV.js → navigate-CP_0Zy5U.js} +454 -87
  60. package/dist/navigation.d.ts +12 -3
  61. package/dist/peer-types.d.ts +8 -0
  62. package/dist/portal-DuOKfnLa.js +349 -0
  63. package/dist/promise-Dz8iIHAm.js +16 -0
  64. package/dist/query-registry-WMCN0BJL.js +320 -0
  65. package/dist/readable-DFWOsTac.js +21 -0
  66. package/dist/{render-context-B7ohlh6t.js → render-context-DGHnEveC.js} +27 -11
  67. package/dist/render-sync-IC5lMFpq.js +1240 -0
  68. package/dist/resolution-Cx82-xjW.js +1244 -0
  69. package/dist/resource-CLjB7RBQ.js +377 -0
  70. package/dist/resources/index.d.ts +21 -11
  71. package/dist/resources/index.js +45 -244
  72. package/dist/router/index.d.ts +14 -5
  73. package/dist/router/index.js +22 -53
  74. package/dist/scope-CwpVSHVf.js +55 -0
  75. package/dist/{shared-kU8yvryp.js → shared-O2ZnmYAf.js} +1 -7
  76. package/dist/{snapshot-source-An4iKajG.js → snapshot-Cjx4N988.js} +6 -1
  77. package/dist/ssg/index.d.ts +1 -2
  78. package/dist/ssg/index.js +5 -13
  79. package/dist/ssr/index.d.ts +26 -28
  80. package/dist/ssr/index.js +4 -4
  81. package/dist/{ssr-CiNm6Vzl.js → ssr-BJ8ug7zH.js} +133 -122
  82. package/dist/ssr-DoV-vJ-5.js +229 -0
  83. package/dist/state-DWO1KzkX.js +232 -0
  84. package/dist/structures-D4dDMqHX.js +231 -0
  85. package/dist/testing/index.d.ts +8 -4
  86. package/dist/testing/index.js +29 -34
  87. package/dist/url-CnbfpX0K.js +185 -0
  88. package/dist/utilities.d.ts +48 -2
  89. package/dist/verify-hydration-DpVaDnqz.js +152 -0
  90. package/package.json +19 -9
  91. package/dist/access-CEA2pOry.js +0 -1046
  92. package/dist/activity-oy2YFTFF.js +0 -201
  93. package/dist/boot-BMBMWUGI.js +0 -1084
  94. package/dist/capabilities-Bbf0mlp9.js +0 -42
  95. package/dist/compose-ref-v0qGlHoN.js +0 -26
  96. package/dist/control-BR_mrX__.js +0 -173
  97. package/dist/control-C-ApnFs1.js +0 -20
  98. package/dist/csp-nonce-BfFWcd0w.js +0 -173
  99. package/dist/data-runtime-CxoY98lX.js +0 -149
  100. package/dist/default-portal-runtime-DvMvWJVp.js +0 -20
  101. package/dist/dom-renderer.d.ts +0 -77
  102. package/dist/domains/renderer.d.ts +0 -127
  103. package/dist/eager-control.d.ts +0 -8
  104. package/dist/effect-C3Zsc1k6.js +0 -292
  105. package/dist/for-state-BDykeOJL.js +0 -1753
  106. package/dist/instance-VAFYVJOa.js +0 -1027
  107. package/dist/notify-DxxuDPeY.js +0 -266
  108. package/dist/portal-w3oQ6oQU.js +0 -29
  109. package/dist/query-registry-LrYpQsDJ.js +0 -83
  110. package/dist/render-resolved-BC0W7_5b.js +0 -1123
  111. package/dist/renderer-CT0HeY58.js +0 -8623
  112. package/dist/resolution-3DskUkjG.js +0 -577
  113. package/dist/resource-18-sFRl9.js +0 -344
  114. package/dist/route-matching-CUzZ31gT.js +0 -551
  115. package/dist/router-internal-7nuNEHfG.js +0 -36
  116. package/dist/scope-Cq_iYbTR.js +0 -403
  117. package/dist/selector-BSPVkjKP.js +0 -311
  118. package/dist/ssr-EPjwJH5R.js +0 -29
  119. package/dist/state-BXJfudq1.js +0 -91
  120. package/dist/structures-CjEzfj4h.js +0 -654
  121. package/dist/timer-C7uqnJVt.js +0 -85
  122. package/dist/verify-hydration-ikaxotf7.js +0 -27
  123. package/dist/vnode-D24p6IW2.js +0 -7
@@ -1,551 +0,0 @@
1
- import { d as getCurrentAppRenderRuntime } from "./scope-Cq_iYbTR.js";
2
- import { n as getActiveRenderContext } from "./render-context-B7ohlh6t.js";
3
- //#region src/router/match.ts
4
- function splitPathSegments(path) {
5
- const normalized = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
6
- if (!normalized || normalized === "/") return [];
7
- const withoutLeadingSlash = normalized.startsWith("/") ? normalized.slice(1) : normalized;
8
- return withoutLeadingSlash.length === 0 ? [] : withoutLeadingSlash.split("/");
9
- }
10
- function normalizeRouteSegmentName(value) {
11
- return value.trim();
12
- }
13
- /**
14
- * Parse a route template path into typed segments.
15
- *
16
- * @example
17
- * parseSegments('/users/{id}') // [{kind:'static',value:'users'},{kind:'param',value:'id'}]
18
- * parseSegments('/*') // [{kind:'catchall',value:'*'}]
19
- * parseSegments('/posts/*') // [{kind:'static',value:'posts'},{kind:'wildcard',value:'*'}]
20
- * parseSegments('/files/{*path}') // [{kind:'static',value:'files'},{kind:'splat',value:'path'}]
21
- */
22
- function parseSegments(path) {
23
- const parts = (path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path).split("/").filter(Boolean);
24
- if (parts.length === 1 && parts[0] === "*") return [{
25
- kind: "catchall",
26
- value: "*"
27
- }];
28
- return parts.map((segment) => {
29
- if (segment.startsWith("{") && segment.endsWith("}")) {
30
- const value = normalizeRouteSegmentName(segment.slice(1, -1));
31
- if (value.startsWith("*")) return {
32
- kind: "splat",
33
- value: normalizeRouteSegmentName(value.slice(1))
34
- };
35
- return {
36
- kind: "param",
37
- value
38
- };
39
- }
40
- if (segment === "*") return {
41
- kind: "wildcard",
42
- value: "*"
43
- };
44
- return {
45
- kind: "static",
46
- value: segment
47
- };
48
- });
49
- }
50
- /**
51
- * Compute a numeric specificity rank from a parsed segment list.
52
- *
53
- * Scoring: static = 3, param = 2, wildcard = 1, catchall = 0.
54
- * Higher rank wins when multiple routes match the same path.
55
- */
56
- function computeRank(segments) {
57
- if (segments.length === 1 && segments[0].kind === "catchall") return -1;
58
- let score = 0;
59
- for (const seg of segments) if (seg.kind === "static") score += 3;
60
- else if (seg.kind === "param") score += 2;
61
- else if (seg.kind === "wildcard") score += 1;
62
- else if (seg.kind === "splat") score -= .5;
63
- return score;
64
- }
65
- /** Reused frozen empty params object — returned for purely-static (no-capture) routes. */
66
- const emptyParams = Object.freeze(Object.create(null));
67
- Object.freeze({
68
- matched: false,
69
- params: emptyParams
70
- });
71
- function decodeRouteParam(part) {
72
- if (!part.includes("%")) return part;
73
- try {
74
- return decodeURIComponent(part);
75
- } catch {
76
- return part;
77
- }
78
- }
79
- /**
80
- * Match pre-split URL parts against pre-parsed route segments.
81
- *
82
- * This is the hot-path matcher used by `resolveRoute` and
83
- * `resolveRouteFromRoutes`. Callers split the URL path **once** and reuse
84
- * `urlParts` across all route comparisons in a single resolution call.
85
- *
86
- * - Returns a params object (possibly the shared `{}`) on match.
87
- * - Returns `null` on no match.
88
- * - Params are allocated lazily — purely-static routes return the frozen
89
- * empty sentinel without any heap allocation.
90
- */
91
- function matchSegments(urlParts, segments) {
92
- if (segments.length === 1 && segments[0].kind === "catchall") return { "*": urlParts.length === 0 ? "/" : urlParts.length === 1 ? urlParts[0] : "/" + urlParts.join("/") };
93
- const splatIndex = segments.findIndex((segment) => segment.kind === "splat");
94
- if (splatIndex !== -1) {
95
- if (splatIndex !== segments.length - 1) return null;
96
- if (urlParts.length < splatIndex) return null;
97
- } else if (urlParts.length !== segments.length) return null;
98
- let params = null;
99
- const normalizeCapturedSplatParts = (parts) => {
100
- let start = 0;
101
- while (start < parts.length && parts[start] === "") start += 1;
102
- return start === 0 ? parts : parts.slice(start);
103
- };
104
- for (let i = 0; i < segments.length; i++) {
105
- const seg = segments[i];
106
- const part = urlParts[i];
107
- if (seg.kind === "static") {
108
- if (seg.value !== part) return null;
109
- } else if (seg.kind === "splat") {
110
- if (params === null) params = {};
111
- params[seg.value] = normalizeCapturedSplatParts(urlParts.slice(i).map(decodeRouteParam)).join("/");
112
- return params;
113
- } else {
114
- if (params === null) params = {};
115
- if (seg.kind === "param") params[seg.value] = decodeRouteParam(part);
116
- else params["*"] = part;
117
- }
118
- }
119
- return params ?? emptyParams;
120
- }
121
- //#endregion
122
- //#region src/router/store.ts
123
- function createRouteTable() {
124
- return {
125
- routes: [],
126
- records: [],
127
- namespaces: /* @__PURE__ */ new Set(),
128
- routesByDepth: /* @__PURE__ */ new Map(),
129
- registrationScopeStack: [],
130
- registrationLocked: false,
131
- defaultRouteAuthOptions: void 0,
132
- activeClientRouteAuthOptions: void 0,
133
- defaultRouteBasePath: ""
134
- };
135
- }
136
- let activeTable = createRouteTable();
137
- /** Run `fn` with `table` as the registration target, then restore the previous one. */
138
- function withRouteTable(table, fn) {
139
- const previous = activeTable;
140
- activeTable = table;
141
- try {
142
- return fn();
143
- } finally {
144
- activeTable = previous;
145
- }
146
- }
147
- function getDepth(path) {
148
- const normalized = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
149
- return normalized === "/" ? 0 : normalized.split("/").filter(Boolean).length;
150
- }
151
- function getRouteRecords() {
152
- return activeTable.records;
153
- }
154
- function isRouteStoreRoutes(routeList) {
155
- return routeList === activeTable.routes;
156
- }
157
- function insertRecordSorted(record) {
158
- let lo = 0;
159
- let hi = activeTable.records.length;
160
- while (lo < hi) {
161
- const mid = lo + hi >>> 1;
162
- if (activeTable.records[mid].rank >= record.rank) lo = mid + 1;
163
- else hi = mid;
164
- }
165
- activeTable.records.splice(lo, 0, record);
166
- }
167
- function addRouteToStores(routeObj) {
168
- activeTable.routes.push(routeObj);
169
- const depth = getDepth(routeObj.path);
170
- let depthRoutes = activeTable.routesByDepth.get(depth);
171
- if (!depthRoutes) {
172
- depthRoutes = [];
173
- activeTable.routesByDepth.set(depth, depthRoutes);
174
- }
175
- depthRoutes.push(routeObj);
176
- if (routeObj.namespace) activeTable.namespaces.add(routeObj.namespace);
177
- }
178
- function getActiveRoutes() {
179
- return getActiveRenderContext()?.routes ?? getCurrentAppRenderRuntime()?.routeRegistry?.routes ?? activeTable.routes;
180
- }
181
- function getActiveRouteAuthOptions(override) {
182
- if (override !== void 0) return override;
183
- const renderContext = getActiveRenderContext();
184
- if (renderContext) return renderContext.routeAuth;
185
- const appRuntime = getCurrentAppRenderRuntime();
186
- if (appRuntime) return appRuntime.routeAuth;
187
- return activeTable.activeClientRouteAuthOptions ?? activeTable.defaultRouteAuthOptions;
188
- }
189
- function _setActiveRouteAuthOptions(auth) {
190
- activeTable.activeClientRouteAuthOptions = auth;
191
- }
192
- function getDefaultRouteAuthOptions() {
193
- return activeTable.defaultRouteAuthOptions;
194
- }
195
- function setDefaultRouteAuthOptions(auth) {
196
- activeTable.defaultRouteAuthOptions = auth;
197
- }
198
- function getDefaultRouteBasePath() {
199
- return activeTable.defaultRouteBasePath;
200
- }
201
- function setDefaultRouteBasePath(basePath) {
202
- activeTable.defaultRouteBasePath = basePath;
203
- }
204
- function getActiveRouteBasePath() {
205
- const renderContext = getActiveRenderContext();
206
- if (renderContext?.basePath !== void 0) return renderContext.basePath;
207
- const appRegistry = getCurrentAppRenderRuntime()?.routeRegistry;
208
- if (appRegistry) return appRegistry.manifest.basePath ?? "";
209
- return activeTable.defaultRouteBasePath;
210
- }
211
- function getCurrentLayoutChain() {
212
- const layoutChain = [];
213
- for (const scope of activeTable.registrationScopeStack) if (scope.layout) layoutChain.push({ component: scope.layout });
214
- return layoutChain;
215
- }
216
- function getCurrentPageChain() {
217
- const pageChain = [];
218
- for (const scope of activeTable.registrationScopeStack) if (scope.page) pageChain.push({ component: scope.page });
219
- return pageChain;
220
- }
221
- function hasActivePageScope() {
222
- return activeTable.registrationScopeStack.some((scope) => !!scope.page);
223
- }
224
- function getCurrentPageScope() {
225
- for (let index = activeTable.registrationScopeStack.length - 1; index >= 0; index -= 1) {
226
- const scope = activeTable.registrationScopeStack[index];
227
- if (scope.kind === "page") return scope;
228
- }
229
- return null;
230
- }
231
- function getCurrentScopeKind() {
232
- return activeTable.registrationScopeStack[activeTable.registrationScopeStack.length - 1]?.kind ?? null;
233
- }
234
- function getCurrentPathPrefix() {
235
- return activeTable.registrationScopeStack[activeTable.registrationScopeStack.length - 1]?.pathPrefix ?? "";
236
- }
237
- function getCurrentInheritedPolicies() {
238
- const policies = [];
239
- for (const scope of activeTable.registrationScopeStack) if (scope.policies.length > 0) policies.push(...scope.policies);
240
- return policies;
241
- }
242
- function getCurrentInheritedAuthRequirements() {
243
- return activeTable.registrationScopeStack.flatMap((scope) => scope.auth ? [scope.auth] : []);
244
- }
245
- function getCurrentInheritedMeta() {
246
- return activeTable.registrationScopeStack.flatMap((scope) => scope.meta ? [scope.meta] : []);
247
- }
248
- function pushRegistrationScope(scope, fn) {
249
- activeTable.registrationScopeStack.push(scope);
250
- try {
251
- fn();
252
- } finally {
253
- activeTable.registrationScopeStack.pop();
254
- }
255
- }
256
- function lockRouteRegistration() {
257
- activeTable.registrationLocked = true;
258
- }
259
- function assertRouteRegistrationUnlocked() {
260
- if (activeTable.registrationLocked) throw new Error("Route registration is locked after app startup. Register routes at module load time before calling createSPA or createSSR.");
261
- }
262
- function getRouteList() {
263
- return [...activeTable.routes];
264
- }
265
- function hasRegisteredRoutes() {
266
- return activeTable.routes.length > 0 || activeTable.records.length > 0;
267
- }
268
- function clearRouteState() {
269
- activeTable.routes.length = 0;
270
- activeTable.records.length = 0;
271
- activeTable.namespaces.clear();
272
- activeTable.routesByDepth.clear();
273
- activeTable.registrationScopeStack.length = 0;
274
- activeTable.registrationLocked = false;
275
- activeTable.defaultRouteAuthOptions = void 0;
276
- activeTable.activeClientRouteAuthOptions = void 0;
277
- activeTable.defaultRouteBasePath = "";
278
- }
279
- //#endregion
280
- //#region src/router/route-context.ts
281
- function parseLocation(url) {
282
- try {
283
- const parsedUrl = new URL(url, "http://localhost");
284
- return {
285
- pathname: parsedUrl.pathname,
286
- search: parsedUrl.search,
287
- hash: parsedUrl.hash
288
- };
289
- } catch {
290
- return {
291
- pathname: "/",
292
- search: "",
293
- hash: ""
294
- };
295
- }
296
- }
297
- function deepFreeze(obj) {
298
- if (obj && typeof obj === "object" && !Object.isFrozen(obj)) {
299
- Object.freeze(obj);
300
- for (const key of Object.keys(obj)) {
301
- const value = obj[key];
302
- if (value && typeof value === "object") deepFreeze(value);
303
- }
304
- }
305
- return obj;
306
- }
307
- function makeQuery(search) {
308
- const searchParams = new URLSearchParams(search || "");
309
- const mapping = /* @__PURE__ */ new Map();
310
- for (const [key, value] of searchParams.entries()) {
311
- const existing = mapping.get(key);
312
- if (existing) existing.push(value);
313
- else mapping.set(key, [value]);
314
- }
315
- return deepFreeze({
316
- get(key) {
317
- const values = mapping.get(key);
318
- return values ? values[0] : null;
319
- },
320
- getAll(key) {
321
- const values = mapping.get(key);
322
- return values ? [...values] : [];
323
- },
324
- has(key) {
325
- return mapping.has(key);
326
- },
327
- toJSON() {
328
- const output = {};
329
- for (const [key, values] of mapping.entries()) output[key] = values.length > 1 ? [...values] : values[0];
330
- return output;
331
- }
332
- });
333
- }
334
- function buildRouteContextBase(target, params, options) {
335
- const parsed = parseLocation(target);
336
- const href = `${parsed.pathname}${parsed.search}${parsed.hash}`;
337
- return {
338
- mode: options.mode,
339
- params,
340
- pathname: parsed.pathname,
341
- search: parsed.search,
342
- hash: parsed.hash,
343
- href,
344
- signal: options.signal
345
- };
346
- }
347
- function buildRouteContext(target, params, options) {
348
- return {
349
- ...buildRouteContextBase(target, params, options),
350
- auth: options.authContext
351
- };
352
- }
353
- //#endregion
354
- //#region src/router/base-path.ts
355
- /** Normalize the public mount point used by one route registry. */
356
- function normalizeRouteBasePath(value) {
357
- if (value === void 0 || value === "" || value === "/") return "";
358
- if (!value.startsWith("/") || /\/{2,}/.test(value) || value.includes("?") || value.includes("#") || value.includes("\\")) throw new TypeError(`Route basePath must be an absolute pathname without a query or hash. Received: ${JSON.stringify(value)}`);
359
- const normalized = value.endsWith("/") ? value.slice(0, -1) : value;
360
- if (normalized.split("/").some((segment) => segment === "." || segment === "..")) throw new TypeError("Route basePath must not contain dot segments.");
361
- return normalized;
362
- }
363
- function parsedTarget(target) {
364
- return new URL(target, "http://askr.invalid");
365
- }
366
- /** Add a registry mount point to one logical root-relative route target. */
367
- function addRouteBasePath(target, basePath) {
368
- if (!basePath || !target.startsWith("/") || target.startsWith("//")) return target;
369
- const parsed = parsedTarget(target);
370
- if (parsed.origin !== "http://askr.invalid" || parsed.pathname === basePath || parsed.pathname.startsWith(`${basePath}/`)) return target;
371
- return `${basePath}${parsed.pathname}${parsed.search}${parsed.hash}`;
372
- }
373
- /** Remove a registry mount point and retain query/hash for logical matching. */
374
- function removeRouteBasePath(target, basePath) {
375
- const parsed = parsedTarget(target);
376
- if (!basePath) return `${parsed.pathname}${parsed.search}${parsed.hash}`;
377
- if (parsed.pathname === basePath || parsed.pathname === `${basePath}/`) return `/${parsed.search}${parsed.hash}`;
378
- if (!parsed.pathname.startsWith(`${basePath}/`)) return void 0;
379
- return `${parsed.pathname.slice(basePath.length)}${parsed.search}${parsed.hash}`;
380
- }
381
- //#endregion
382
- //#region src/router/route-matching.ts
383
- const routeSegsCache = /* @__PURE__ */ new WeakMap();
384
- const routeRankCache = /* @__PURE__ */ new WeakMap();
385
- const sortedListCache = /* @__PURE__ */ new WeakMap();
386
- function cachedSegs(route) {
387
- let segments = routeSegsCache.get(route);
388
- if (!segments) {
389
- segments = parseSegments(route.path);
390
- routeSegsCache.set(route, segments);
391
- }
392
- return segments;
393
- }
394
- function cachedRank(route) {
395
- let rank = routeRankCache.get(route);
396
- if (rank === void 0) {
397
- rank = computeRank(cachedSegs(route));
398
- routeRankCache.set(route, rank);
399
- }
400
- return rank;
401
- }
402
- function cachedSortedList(routeList) {
403
- let sorted = sortedListCache.get(routeList);
404
- if (!sorted) {
405
- sorted = [...routeList].sort((a, b) => cachedRank(b) - cachedRank(a));
406
- sortedListCache.set(routeList, sorted);
407
- }
408
- return sorted;
409
- }
410
- function matchFallbackPrefix(pathname, fallbackPrefix) {
411
- const normalizedPath = pathname.endsWith("/") && pathname !== "/" ? pathname.slice(0, -1) : pathname;
412
- const normalizedPrefix = fallbackPrefix.endsWith("/") && fallbackPrefix !== "/" ? fallbackPrefix.slice(0, -1) : fallbackPrefix;
413
- if (normalizedPrefix === "/") {
414
- const urlParts = splitPathSegments(normalizedPath);
415
- return { "*": urlParts.length === 0 ? "/" : urlParts.length === 1 ? urlParts[0] : "/" + urlParts.join("/") };
416
- }
417
- if (normalizedPath !== normalizedPrefix && !normalizedPath.startsWith(`${normalizedPrefix}/`)) return null;
418
- const remainderParts = splitPathSegments(normalizedPath === normalizedPrefix ? "/" : normalizedPath.slice(normalizedPrefix.length));
419
- return { "*": remainderParts.length === 0 ? "/" : remainderParts.length === 1 ? remainderParts[0] : "/" + remainderParts.join("/") };
420
- }
421
- function findBestResolvedRouteFromRoutes(pathname, routeList) {
422
- const normalized = pathname.endsWith("/") && pathname !== "/" ? pathname.slice(0, -1) : pathname;
423
- const urlParts = splitPathSegments(normalized);
424
- const sorted = cachedSortedList(routeList);
425
- let bestRoute = null;
426
- let bestParams = {};
427
- let bestRank = -Infinity;
428
- for (const route of sorted) {
429
- if (route.fallbackPrefix) continue;
430
- const rank = cachedRank(route);
431
- if (rank < bestRank) break;
432
- if (bestRoute !== null && rank === bestRank) continue;
433
- const params = matchSegments(urlParts, cachedSegs(route));
434
- if (params !== null) {
435
- bestRoute = route;
436
- bestParams = params;
437
- bestRank = rank;
438
- }
439
- }
440
- if (bestRoute !== null) return {
441
- route: bestRoute,
442
- params: bestParams
443
- };
444
- let bestFallback = null;
445
- let bestFallbackParams = null;
446
- let bestPrefixLength = -1;
447
- for (const route of routeList) {
448
- const internalRoute = route;
449
- if (!internalRoute.fallbackPrefix) continue;
450
- const params = matchFallbackPrefix(normalized, internalRoute.fallbackPrefix);
451
- if (params === null) continue;
452
- if (internalRoute.fallbackPrefix.length > bestPrefixLength) {
453
- bestFallback = internalRoute;
454
- bestFallbackParams = params;
455
- bestPrefixLength = internalRoute.fallbackPrefix.length;
456
- }
457
- }
458
- return bestFallback && bestFallbackParams ? {
459
- route: bestFallback,
460
- params: bestFallbackParams
461
- } : null;
462
- }
463
- function findBestScopedFallbackRecord(pathname, routeRecords) {
464
- let bestRecord = null;
465
- let bestParams = null;
466
- let bestPrefixLength = -1;
467
- for (const routeRecord of routeRecords) {
468
- const record = routeRecord;
469
- if (!record.fallbackPrefix) continue;
470
- const params = matchFallbackPrefix(pathname, record.fallbackPrefix);
471
- if (params === null) continue;
472
- if (record.fallbackPrefix.length > bestPrefixLength) {
473
- bestRecord = record;
474
- bestParams = params;
475
- bestPrefixLength = record.fallbackPrefix.length;
476
- }
477
- }
478
- return bestRecord && bestParams ? {
479
- record: bestRecord,
480
- params: bestParams
481
- } : null;
482
- }
483
- function getMatchingRouteRecord(target, routeRecords) {
484
- const location = parseLocation(target);
485
- const normalized = location.pathname.endsWith("/") && location.pathname !== "/" ? location.pathname.slice(0, -1) : location.pathname;
486
- const urlParts = splitPathSegments(normalized);
487
- for (const record of routeRecords) {
488
- if (record.fallbackPrefix) continue;
489
- const params = matchSegments(urlParts, record.segments);
490
- if (params !== null) return {
491
- record,
492
- params
493
- };
494
- }
495
- return findBestScopedFallbackRecord(normalized, routeRecords);
496
- }
497
- function computeMatchesFromRoutes(pathname, routesList) {
498
- const bestMatch = isRouteStoreRoutes(routesList) ? getMatchingRouteRecord(pathname, getRouteRecords()) : findBestResolvedRouteFromRoutes(pathname, routesList);
499
- if (!bestMatch) return [];
500
- return [{
501
- path: "route" in bestMatch ? bestMatch.route.path : bestMatch.record.path,
502
- params: deepFreeze({ ...bestMatch.params }),
503
- name: "route" in bestMatch ? bestMatch.route.name : void 0,
504
- namespace: "route" in bestMatch ? bestMatch.route.namespace : bestMatch.record.options.namespace
505
- }];
506
- }
507
- function computeMatchesFromRouteRecords(pathname, routeRecords) {
508
- const bestMatch = getMatchingRouteRecord(pathname, routeRecords);
509
- if (!bestMatch) return [];
510
- return [{
511
- path: bestMatch.record.path,
512
- params: deepFreeze({ ...bestMatch.params }),
513
- namespace: bestMatch.record.options.namespace
514
- }];
515
- }
516
- function computeRouteActivityMatches(pathname, options) {
517
- const logicalPath = removeRouteBasePath(pathname, normalizeRouteBasePath(options.registry.manifest.basePath));
518
- if (logicalPath === void 0) return [];
519
- return computeMatchesFromRouteRecords(logicalPath, options.registry.manifest.records);
520
- }
521
- function resolveRoute(pathname) {
522
- const normalized = pathname.endsWith("/") && pathname !== "/" ? pathname.slice(0, -1) : pathname;
523
- const urlParts = splitPathSegments(normalized);
524
- const records = getRouteRecords();
525
- for (const record of records) {
526
- if (record.fallbackPrefix) continue;
527
- const params = matchSegments(urlParts, record.segments);
528
- if (params !== null) return {
529
- handler: record.handler,
530
- params
531
- };
532
- }
533
- const fallbackMatch = findBestScopedFallbackRecord(normalized, records);
534
- return fallbackMatch ? {
535
- handler: fallbackMatch.record.handler,
536
- params: fallbackMatch.params
537
- } : null;
538
- }
539
- function resolveRouteFromRoutes(pathname, routeList) {
540
- if (isRouteStoreRoutes(routeList)) return resolveRoute(pathname);
541
- const match = findBestResolvedRouteFromRoutes(pathname, routeList);
542
- return match ? {
543
- handler: match.route.handler,
544
- params: match.params
545
- } : null;
546
- }
547
- function _resolveRouteMatchFromRoutes(pathname, routeList) {
548
- return findBestResolvedRouteFromRoutes(pathname, routeList);
549
- }
550
- //#endregion
551
- export { getDefaultRouteAuthOptions as A, setDefaultRouteBasePath as B, getCurrentInheritedMeta as C, getCurrentPageScope as D, getCurrentPageChain as E, hasRegisteredRoutes as F, computeRank as H, insertRecordSorted as I, lockRouteRegistration as L, getRouteList as M, getRouteRecords as N, getCurrentPathPrefix as O, hasActivePageScope as P, pushRegistrationScope as R, getCurrentInheritedAuthRequirements as S, getCurrentLayoutChain as T, normalizeRouteSegmentName as U, withRouteTable as V, parseSegments as W, clearRouteState as _, resolveRouteFromRoutes as a, getActiveRouteBasePath as b, removeRouteBasePath as c, deepFreeze as d, makeQuery as f, assertRouteRegistrationUnlocked as g, addRouteToStores as h, getMatchingRouteRecord as i, getDefaultRouteBasePath as j, getCurrentScopeKind as k, buildRouteContext as l, _setActiveRouteAuthOptions as m, computeMatchesFromRoutes as n, addRouteBasePath as o, parseLocation as p, computeRouteActivityMatches as r, normalizeRouteBasePath as s, _resolveRouteMatchFromRoutes as t, buildRouteContextBase as u, createRouteTable as v, getCurrentInheritedPolicies as w, getActiveRoutes as x, getActiveRouteAuthOptions as y, setDefaultRouteAuthOptions as z };
@@ -1,36 +0,0 @@
1
- //#region src/common/url.ts
2
- const SAFE_URL_SCHEMES = /* @__PURE__ */ new Set([
3
- "http",
4
- "https",
5
- "mailto",
6
- "sms",
7
- "tel"
8
- ]);
9
- const URL_SCHEME_RE = /^([a-z][a-z0-9+.-]*):/i;
10
- function isSafeHref(value) {
11
- const compact = value.trim().replace(/[\u0000-\u0020\u007f-\u009f]/g, "");
12
- const scheme = URL_SCHEME_RE.exec(compact)?.[1]?.toLowerCase();
13
- return scheme === void 0 || SAFE_URL_SCHEMES.has(scheme);
14
- }
15
- /**
16
- * Attribute names (lowercased) that can carry a browser-navigable/executable
17
- * URL and must be checked against isSafeHref. Shared between the client
18
- * renderer (renderer/attributes.ts) and SSR (ssr/attrs.ts) so their unsafe-
19
- * URL handling can't drift. Deliberately excludes `src`: it covers a much
20
- * wider range of legitimate non-navigable values (data: image URIs, blob:
21
- * URLs, etc.) where the same scheme allowlist would be overly aggressive.
22
- */
23
- const UNSAFE_URL_SCHEME_ATTRIBUTES = /* @__PURE__ */ new Set([
24
- "href",
25
- "formaction",
26
- "action",
27
- "xlink:href"
28
- ]);
29
- function isUnsafeUrlAttribute(key, value) {
30
- return UNSAFE_URL_SCHEME_ATTRIBUTES.has(key.toLowerCase()) && !isSafeHref(String(value));
31
- }
32
- //#endregion
33
- //#region src/common/router-internal.ts
34
- const ROUTE_ROOT_COMPONENT = Symbol.for("askr.route-root-component");
35
- //#endregion
36
- export { isSafeHref as n, isUnsafeUrlAttribute as r, ROUTE_ROOT_COMPONENT as t };