@askrjs/askr 0.0.83 → 0.0.85

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 (64) hide show
  1. package/dist/{access-ePqdQqkV.js → access-Dpfoi4cA.js} +7 -1
  2. package/dist/actions/index.d.ts +1 -1
  3. package/dist/actions/index.js +1 -1
  4. package/dist/{activity-CXEaU-Al.d.ts → activity-B1I5HJQI.d.ts} +1 -1
  5. package/dist/{activity-CnSRFO3d.js → activity-Jd9CgEa3.js} +52 -15
  6. package/dist/{authoring-DbGEgg40.js → authoring-DdQ3pHqt.js} +6 -3
  7. package/dist/benchmark.js +8 -8
  8. package/dist/boot/index.d.ts +3 -3
  9. package/dist/boot/index.js +1 -1
  10. package/dist/{boot-uK1hzONI.js → boot-DWe880Et.js} +16 -15
  11. package/dist/{cleanup-CEF-cX49.js → cleanup-c837KVij.js} +17 -7
  12. package/dist/{component-cleanup-oWN45rfa.js → component-cleanup-BUfUleGZ.js} +2 -2
  13. package/dist/{component-internal-DsM75Gl1.js → component-internal-DcrLymUJ.js} +9 -6
  14. package/dist/components/index.d.ts +1 -1
  15. package/dist/components/index.js +1 -1
  16. package/dist/control/index.d.ts +1 -1
  17. package/dist/control/index.js +1 -1
  18. package/dist/{control-Cix3yjVf.d.ts → control-DhUZU4_V.d.ts} +2 -1
  19. package/dist/{control-C0X1zgrM.js → control-oLADku43.js} +4 -4
  20. package/dist/{csp-nonce-DDt0UNdt.js → csp-nonce-Bc52OIVc.js} +19 -2
  21. package/dist/data/index.js +1 -1
  22. package/dist/{data-G0hURNm_.js → data-Dkqb8_QP.js} +3 -3
  23. package/dist/{deferred-rdHAgyKe.js → deferred-vUOy-awa.js} +198 -16
  24. package/dist/{effect-2IIWvUjG.js → effect-lnxQIpJG.js} +2 -2
  25. package/dist/{fastlane-CkBXZ_3K.js → fastlane-CrfB3QG0.js} +2 -2
  26. package/dist/{for-internal-DRbV0h1d.js → for-internal-B_mnQhan.js} +55 -22
  27. package/dist/foundations/index.d.ts +1 -1
  28. package/dist/foundations/index.js +2 -2
  29. package/dist/foundations/state/index.d.ts +1 -1
  30. package/dist/foundations/state/index.js +1 -1
  31. package/dist/foundations/structures/index.d.ts +2 -2
  32. package/dist/foundations/structures/index.js +3 -3
  33. package/dist/fx/index.js +1 -1
  34. package/dist/{index-Vs1EeWEr.d.ts → index-Bkh9S9-t.d.ts} +6 -2
  35. package/dist/{index-TlEvex-C.d.ts → index-pIgGaXvS.d.ts} +21 -4
  36. package/dist/{index-ho0Htetw.d.ts → index-r-nt13FE.d.ts} +1 -1
  37. package/dist/index.d.ts +3 -3
  38. package/dist/index.js +10 -10
  39. package/dist/{lifecycle-batch-CwHCDseR.js → lifecycle-batch-Dfpid9-A.js} +45 -24
  40. package/dist/{lifecycle-operations-BJfxWUJr.js → lifecycle-operations-BrYrBsXY.js} +1 -1
  41. package/dist/{navigate-DfY1BUYc.d.ts → navigate-NyIjQUwI.d.ts} +1 -1
  42. package/dist/{navigate-Crvd5gUG.js → navigate-b4GGxO_l.js} +15 -14
  43. package/dist/{portal-BZ_rN17v.js → portal-BVWjAhNQ.js} +5 -5
  44. package/dist/{readable-B3VIOfd7.js → readable-B5NtV7V0.js} +3 -3
  45. package/dist/{renderer-VSw0KKDG.js → renderer-CZzNtoj2.js} +3355 -2813
  46. package/dist/resources/index.d.ts +2 -2
  47. package/dist/resources/index.js +5 -5
  48. package/dist/{route-matching-BUwz4kfl.js → route-matching-DHduNiGk.js} +49 -6
  49. package/dist/router/index.d.ts +7 -7
  50. package/dist/router/index.js +9 -7
  51. package/dist/{selector-DVwvof1M.js → selector-Ck_Pp9av.js} +2 -2
  52. package/dist/ssg/index.d.ts +10 -4
  53. package/dist/ssg/index.js +30 -15
  54. package/dist/ssr/index.d.ts +7 -3
  55. package/dist/ssr/index.js +1 -1
  56. package/dist/{ssr-C_Ql5_Kg.js → ssr-CpiBHMNv.js} +40 -26
  57. package/dist/ssr-DSHd_Q9K.js +25 -0
  58. package/dist/{state-BCl9DeiN.js → state-DCjONcHK.js} +4 -3
  59. package/dist/{structures-D3vO-WMN.js → structures-DSLF_iis.js} +4 -2
  60. package/dist/testing/index.d.ts +2 -2
  61. package/dist/testing/index.js +3 -3
  62. package/dist/{verify-hydration-CNLXUcuR.js → verify-hydration-C3QBBQqR.js} +2 -2
  63. package/package.json +3 -3
  64. package/dist/ssr-CbQO5xd3.js +0 -12
@@ -1,5 +1,5 @@
1
- import { ut as getSignal } from "../index-TlEvex-C.js";
2
- import { i as onRouteChange, n as RouteChangeOptions, t as RouteChangeCleanup } from "../activity-CXEaU-Al.js";
1
+ import { ut as getSignal } from "../index-pIgGaXvS.js";
2
+ import { i as onRouteChange, n as RouteChangeOptions, t as RouteChangeCleanup } from "../activity-B1I5HJQI.js";
3
3
  //#region src/runtime/resource-operation.d.ts
4
4
  interface ResourceResult<T> {
5
5
  value: T | null;
@@ -1,9 +1,9 @@
1
- import { t as enqueueRuntimeLane } from "../access-ePqdQqkV.js";
2
- import { a as registerCommitOperation } from "../component-internal-DsM75Gl1.js";
1
+ import { t as enqueueRuntimeLane } from "../access-Dpfoi4cA.js";
3
2
  import { f as getCurrentComponentInstance, g as getSignal, i as claimHookIndex } from "../component-scope-DzJEbYGE.js";
4
- import { z as resource } from "../route-matching-BUwz4kfl.js";
5
- import { a as task, i as routeActive, n as documentVisible, o as timer, r as on, s as windowFocused, t as capture } from "../lifecycle-operations-BJfxWUJr.js";
6
- import { n as onRouteChange } from "../activity-CnSRFO3d.js";
3
+ import { a as registerCommitOperation } from "../component-internal-DcrLymUJ.js";
4
+ import { G as resource } from "../route-matching-DHduNiGk.js";
5
+ import { a as task, i as routeActive, n as documentVisible, o as timer, r as on, s as windowFocused, t as capture } from "../lifecycle-operations-BrYrBsXY.js";
6
+ import { n as onRouteChange } from "../activity-Jd9CgEa3.js";
7
7
  //#region src/runtime/stream-operation.ts
8
8
  function toError(value) {
9
9
  return value instanceof Error ? value : new Error(String(value));
@@ -1,10 +1,10 @@
1
- import { t as enqueueRuntimeLane, v as logger } from "./access-ePqdQqkV.js";
2
- import { c as registerCommitOperationForInstance, d as getCurrentContextFrame, v as withAsyncResourceContext } from "./component-internal-DsM75Gl1.js";
1
+ import { t as enqueueRuntimeLane, v as logger } from "./access-Dpfoi4cA.js";
3
2
  import { f as getCurrentComponentInstance } from "./component-scope-DzJEbYGE.js";
4
- import { p as isPromiseLike } from "./lifecycle-batch-CwHCDseR.js";
3
+ import { c as registerCommitOperationForInstance, d as getCurrentContextFrame, v as withAsyncResourceContext } from "./component-internal-DcrLymUJ.js";
4
+ import { p as isPromiseLike } from "./lifecycle-batch-Dfpid9-A.js";
5
5
  import { t as brandSnapshotSource } from "./snapshot-source-BB42xgwb.js";
6
6
  import { d as SSRDataMissingError, i as getNextRenderKey, n as getActiveRenderContext, r as getCurrentRenderData, u as throwSSRDataMissing } from "./render-context-D-DFk2WN.js";
7
- import { t as state } from "./state-BCl9DeiN.js";
7
+ import { t as state } from "./state-DCjONcHK.js";
8
8
  //#region src/runtime/resource-cell.ts
9
9
  /**
10
10
  * Pure, component-agnostic ResourceCell state machine.
@@ -401,6 +401,7 @@ const registrationScopeStack = [];
401
401
  let registrationLocked = false;
402
402
  let defaultRouteAuthOptions;
403
403
  let activeClientRouteAuthOptions;
404
+ let defaultRouteBasePath = "";
404
405
  function getDepth(path) {
405
406
  const normalized = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
406
407
  return normalized === "/" ? 0 : normalized.split("/").filter(Boolean).length;
@@ -448,6 +449,15 @@ function getDefaultRouteAuthOptions() {
448
449
  function setDefaultRouteAuthOptions(auth) {
449
450
  defaultRouteAuthOptions = auth;
450
451
  }
452
+ function getDefaultRouteBasePath() {
453
+ return defaultRouteBasePath;
454
+ }
455
+ function setDefaultRouteBasePath(basePath) {
456
+ defaultRouteBasePath = basePath;
457
+ }
458
+ function getActiveRouteBasePath() {
459
+ return getActiveRenderContext()?.basePath ?? defaultRouteBasePath;
460
+ }
451
461
  function getCurrentLayoutChain() {
452
462
  const layoutChain = [];
453
463
  for (const scope of registrationScopeStack) if (scope.layout) layoutChain.push({ component: scope.layout });
@@ -514,6 +524,7 @@ function clearRouteState() {
514
524
  registrationLocked = false;
515
525
  defaultRouteAuthOptions = void 0;
516
526
  activeClientRouteAuthOptions = void 0;
527
+ defaultRouteBasePath = "";
517
528
  }
518
529
  function snapshotRouteState() {
519
530
  return {
@@ -523,6 +534,7 @@ function snapshotRouteState() {
523
534
  registrationLocked,
524
535
  defaultRouteAuthOptions,
525
536
  activeClientRouteAuthOptions,
537
+ defaultRouteBasePath,
526
538
  routesByDepth: [...routesByDepth.entries()].map(([depth, depthRoutes]) => [depth, [...depthRoutes]]),
527
539
  registrationScopeStack: [...registrationScopeStack]
528
540
  };
@@ -541,6 +553,7 @@ function restoreRouteState(snapshot) {
541
553
  registrationLocked = snapshot.registrationLocked;
542
554
  defaultRouteAuthOptions = snapshot.defaultRouteAuthOptions;
543
555
  activeClientRouteAuthOptions = snapshot.activeClientRouteAuthOptions;
556
+ defaultRouteBasePath = snapshot.defaultRouteBasePath;
544
557
  }
545
558
  //#endregion
546
559
  //#region src/router/route-context.ts
@@ -617,6 +630,34 @@ function buildRouteContext(target, params, options) {
617
630
  };
618
631
  }
619
632
  //#endregion
633
+ //#region src/router/base-path.ts
634
+ /** Normalize the public mount point used by one route registry. */
635
+ function normalizeRouteBasePath(value) {
636
+ if (value === void 0 || value === "" || value === "/") return "";
637
+ 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)}`);
638
+ const normalized = value.endsWith("/") ? value.slice(0, -1) : value;
639
+ if (normalized.split("/").some((segment) => segment === "." || segment === "..")) throw new TypeError("Route basePath must not contain dot segments.");
640
+ return normalized;
641
+ }
642
+ function parsedTarget(target) {
643
+ return new URL(target, "http://askr.invalid");
644
+ }
645
+ /** Add a registry mount point to one logical root-relative route target. */
646
+ function addRouteBasePath(target, basePath) {
647
+ if (!basePath || !target.startsWith("/") || target.startsWith("//")) return target;
648
+ const parsed = parsedTarget(target);
649
+ if (parsed.origin !== "http://askr.invalid" || parsed.pathname === basePath || parsed.pathname.startsWith(`${basePath}/`)) return target;
650
+ return `${basePath}${parsed.pathname}${parsed.search}${parsed.hash}`;
651
+ }
652
+ /** Remove a registry mount point and retain query/hash for logical matching. */
653
+ function removeRouteBasePath(target, basePath) {
654
+ const parsed = parsedTarget(target);
655
+ if (!basePath) return `${parsed.pathname}${parsed.search}${parsed.hash}`;
656
+ if (parsed.pathname === basePath || parsed.pathname === `${basePath}/`) return `/${parsed.search}${parsed.hash}`;
657
+ if (!parsed.pathname.startsWith(`${basePath}/`)) return void 0;
658
+ return `${parsed.pathname.slice(basePath.length)}${parsed.search}${parsed.hash}`;
659
+ }
660
+ //#endregion
620
661
  //#region src/router/route-matching.ts
621
662
  const routeSegsCache = /* @__PURE__ */ new WeakMap();
622
663
  const routeRankCache = /* @__PURE__ */ new WeakMap();
@@ -752,7 +793,9 @@ function computeMatchesFromRouteRecords(pathname, routeRecords) {
752
793
  }];
753
794
  }
754
795
  function computeRouteActivityMatches(pathname, options) {
755
- return computeMatchesFromRouteRecords(pathname, options.registry.manifest.records);
796
+ const logicalPath = removeRouteBasePath(pathname, normalizeRouteBasePath(options.registry.manifest.basePath));
797
+ if (logicalPath === void 0) return [];
798
+ return computeMatchesFromRouteRecords(logicalPath, options.registry.manifest.records);
756
799
  }
757
800
  function resolveRoute(pathname) {
758
801
  const normalized = pathname.endsWith("/") && pathname !== "/" ? pathname.slice(0, -1) : pathname;
@@ -784,4 +827,4 @@ function _resolveRouteMatchFromRoutes(pathname, routeList) {
784
827
  return findBestResolvedRouteFromRoutes(pathname, routeList);
785
828
  }
786
829
  //#endregion
787
- export { insertRecordSorted as A, getCurrentPathPrefix as C, getRouteRecords as D, getRouteList as E, snapshotRouteState as F, computeRank as I, normalizeRouteSegmentName as L, pushRegistrationScope as M, restoreRouteState as N, hasActivePageScope as O, setDefaultRouteAuthOptions as P, parseSegments as R, getCurrentPageScope as S, getDefaultRouteAuthOptions as T, getCurrentInheritedAuthRequirements as _, resolveRouteFromRoutes as a, getCurrentLayoutChain as b, deepFreeze as c, _setActiveRouteAuthOptions as d, addRouteToStores as f, getActiveRoutes as g, getActiveRouteAuthOptions as h, getMatchingRouteRecord as i, lockRouteRegistration as j, hasRegisteredRoutes as k, makeQuery as l, clearRouteState as m, computeMatchesFromRoutes as n, buildRouteContext as o, assertRouteRegistrationUnlocked as p, computeRouteActivityMatches as r, buildRouteContextBase as s, _resolveRouteMatchFromRoutes as t, parseLocation as u, getCurrentInheritedMeta as v, getCurrentScopeKind as w, getCurrentPageChain as x, getCurrentInheritedPolicies as y, resource as z };
830
+ export { getDefaultRouteBasePath as A, setDefaultRouteBasePath as B, getCurrentInheritedPolicies as C, getCurrentPathPrefix as D, getCurrentPageScope as E, insertRecordSorted as F, resource as G, computeRank as H, lockRouteRegistration as I, pushRegistrationScope as L, getRouteRecords as M, hasActivePageScope as N, getCurrentScopeKind as O, hasRegisteredRoutes as P, restoreRouteState as R, getCurrentInheritedMeta as S, getCurrentPageChain as T, normalizeRouteSegmentName as U, snapshotRouteState as V, parseSegments as W, clearRouteState as _, resolveRouteFromRoutes as a, getActiveRoutes as b, removeRouteBasePath as c, deepFreeze as d, makeQuery as f, assertRouteRegistrationUnlocked as g, addRouteToStores as h, getMatchingRouteRecord as i, getRouteList as j, getDefaultRouteAuthOptions 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, getActiveRouteAuthOptions as v, getCurrentLayoutChain as w, getCurrentInheritedAuthRequirements as x, getActiveRouteBasePath as y, setDefaultRouteAuthOptions as z };
@@ -1,9 +1,9 @@
1
- import { c as RenderableChild } from "../control-Cix3yjVf.js";
1
+ import { u as RenderableChild } from "../control-DhUZU4_V.js";
2
2
  import { r as JSXElement, s as Props } from "../jsx-Dvr2SGRG.js";
3
- import { A as RouteHandler, B as RouteQuery, C as Route, D as RouteContext, E as RouteComponent, F as RouteMode, G as RouteRegistryOptions, H as RouteRef, I as RouteOptions, J as RouteRequestResult, K as RouteRenderResult, L as RouteParams, M as RouteMatch, N as RouteMeta, O as RouteDefinition, P as RouteMetaSource, R as RoutePathParams, S as ParsedSegment, T as RouteAuthResolver, U as RouteRefSearch, V as RouteRecord, W as RouteRegistry, X as RouteSearchValue, Y as RouteSearch, Z as RouteSnapshot, _ as AccessRedirectStatus, b as PageHelperOptions, f as AccessAllowDecision, g as AccessRedirectDecision, h as AccessDenyStatus, j as RouteManifest, k as RouteDestination, m as AccessDenyDecision, p as AccessDecision, q as RouteRequestOptions, v as GroupHelperOptions, w as RouteAuthOptions, x as PageScopeRecord, y as LayoutScopeRecord, z as RoutePolicy } from "../index-TlEvex-C.js";
3
+ import { A as RouteHandler, B as RouteQuery, C as Route, D as RouteContext, E as RouteComponent, F as RouteMode, G as RouteRegistryOptions, H as RouteRef, I as RouteOptions, J as RouteRequestResult, K as RouteRenderResult, L as RouteParams, M as RouteMatch, N as RouteMeta, O as RouteDefinition, P as RouteMetaSource, R as RoutePathParams, S as ParsedSegment, T as RouteAuthResolver, U as RouteRefSearch, V as RouteRecord, W as RouteRegistry, X as RouteSearchValue, Y as RouteSearch, Z as RouteSnapshot, _ as AccessRedirectStatus, b as PageHelperOptions, f as AccessAllowDecision, g as AccessRedirectDecision, h as AccessDenyStatus, j as RouteManifest, k as RouteDestination, m as AccessDenyDecision, p as AccessDecision, q as RouteRequestOptions, v as GroupHelperOptions, w as RouteAuthOptions, x as PageScopeRecord, y as LayoutScopeRecord, z as RoutePolicy } from "../index-pIgGaXvS.js";
4
4
  import "../types-C9YcqVpk.js";
5
- import { a as ScrollRestorationOptions, i as NavigationScrollBehavior, n as NavigateOptions, r as HistoryScrollBehavior, t as navigate } from "../navigate-DfY1BUYc.js";
6
- import { i as onRouteChange, n as RouteChangeOptions, r as currentRoute, t as RouteChangeCleanup } from "../activity-CXEaU-Al.js";
5
+ import { a as ScrollRestorationOptions, i as NavigationScrollBehavior, n as NavigateOptions, r as HistoryScrollBehavior, t as navigate } from "../navigate-NyIjQUwI.js";
6
+ import { i as onRouteChange, n as RouteChangeOptions, r as currentRoute, t as RouteChangeCleanup } from "../activity-B1I5HJQI.js";
7
7
  import { AuthContext, AuthContext as AuthContext$1, AuthRequirement, AuthRequirement as AuthRequirement$1 } from "@askrjs/auth";
8
8
  import { ObjectSchema } from "@askrjs/schema";
9
9
  //#region src/router/route-query.d.ts
@@ -29,7 +29,7 @@ type RouteComponentParam<TComponent extends AnyRouteComponent> = Parameters<TCom
29
29
  type CompatibleAbsoluteRouteComponent<Path extends string, TComponent extends AnyRouteComponent> = Parameters<TComponent> extends [] ? TComponent : RoutePathParams<Path> extends RouteComponentParam<TComponent> ? TComponent : never;
30
30
  type CompatibleRelativeRouteComponent<Path extends string, TComponent extends AnyRouteComponent> = Parameters<TComponent> extends [] ? TComponent : RouteComponentParam<TComponent> extends Record<keyof RoutePathParams<Path>, string> ? TComponent : never;
31
31
  type CompatibleRouteComponent<Path extends string, TComponent extends AnyRouteComponent> = Path extends `/${string}` ? CompatibleAbsoluteRouteComponent<Path, TComponent> : CompatibleRelativeRouteComponent<Path, TComponent>;
32
- type RouteOptionsForComponent<Path extends string, TComponent extends AnyRouteComponent, TSearchSchema extends ObjectSchema<RouteSearch> | undefined = ObjectSchema<RouteSearch> | undefined> = Parameters<TComponent> extends [] ? RouteOptions<RoutePathParams<Path>, TSearchSchema> : RouteComponentParam<TComponent> extends RouteParams ? RouteOptions<RouteComponentParam<TComponent>, TSearchSchema> : RouteOptions<RoutePathParams<Path>, TSearchSchema>;
32
+ type RouteOptionsForComponent<Path extends string, TComponent extends AnyRouteComponent, TSearchSchema extends ObjectSchema<RouteSearch> | undefined = ObjectSchema<RouteSearch> | undefined, TLoaderData = unknown, TDehydratedData = TLoaderData> = Parameters<TComponent> extends [] ? RouteOptions<RoutePathParams<Path>, TSearchSchema, TLoaderData, TDehydratedData> : RouteComponentParam<TComponent> extends RouteParams ? RouteOptions<RouteComponentParam<TComponent>, TSearchSchema, TLoaderData, TDehydratedData> : RouteOptions<RoutePathParams<Path>, TSearchSchema, TLoaderData, TDehydratedData>;
33
33
  declare function group(options: GroupHelperOptions, fn: RouteDefinition): void;
34
34
  declare function page<const TPath extends string>(path: TPath, Component: RouteComponent<RoutePathParams<TPath>>, fn: RouteDefinition): void;
35
35
  declare function page<const TPath extends string, TComponent extends AnyRouteComponent>(path: TPath, Component: CompatibleRouteComponent<TPath, TComponent>, fn: RouteDefinition): void;
@@ -37,8 +37,8 @@ declare function page<const TPath extends string>(path: TPath, Component: RouteC
37
37
  declare function page<const TPath extends string, TComponent extends AnyRouteComponent>(path: TPath, Component: CompatibleRouteComponent<TPath, TComponent>, options: PageHelperOptions, fn: RouteDefinition): void;
38
38
  declare function index(Component: RouteComponent, options?: RouteOptions): void;
39
39
  declare function fallback(Component: RouteComponent): void;
40
- declare function route<const TPath extends string, const TSearchSchema extends ObjectSchema<RouteSearch> | undefined = undefined>(path: TPath, Component: RouteComponent<RoutePathParams<TPath>>, options?: RouteOptions<RoutePathParams<TPath>, TSearchSchema>): RouteRef<RoutePathParams<TPath>, RouteRefSearch<TSearchSchema>>;
41
- declare function route<const TPath extends string, TComponent extends AnyRouteComponent, const TSearchSchema extends ObjectSchema<RouteSearch> | undefined = undefined>(path: TPath, Component: CompatibleRouteComponent<TPath, TComponent>, options?: RouteOptionsForComponent<TPath, TComponent, TSearchSchema>): RouteRef<RoutePathParams<TPath>, RouteRefSearch<TSearchSchema>>;
40
+ declare function route<const TPath extends string, const TSearchSchema extends ObjectSchema<RouteSearch> | undefined = undefined, TLoaderData = unknown, TDehydratedData = TLoaderData>(path: TPath, Component: RouteComponent<RoutePathParams<TPath>>, options?: RouteOptions<RoutePathParams<TPath>, TSearchSchema, TLoaderData, TDehydratedData>): RouteRef<RoutePathParams<TPath>, RouteRefSearch<TSearchSchema>>;
41
+ declare function route<const TPath extends string, TComponent extends AnyRouteComponent, const TSearchSchema extends ObjectSchema<RouteSearch> | undefined = undefined, TLoaderData = unknown, TDehydratedData = TLoaderData>(path: TPath, Component: CompatibleRouteComponent<TPath, TComponent>, options?: RouteOptionsForComponent<TPath, TComponent, TSearchSchema, TLoaderData, TDehydratedData>): RouteRef<RoutePathParams<TPath>, RouteRefSearch<TSearchSchema>>;
42
42
  //#endregion
43
43
  //#region src/router/auth.d.ts
44
44
  /** Return the identity resolved for the route currently being rendered. */
@@ -1,9 +1,10 @@
1
- import { a as resolveDeferredValues, b as Outlet, i as isDeferred, l as createRouteRegistry, m as resolveRouteRequest, n as Resolve, r as defer, s as routeData, w as lazy, y as currentAuth } from "../deferred-rdHAgyKe.js";
2
- import { a as isSafeHref } from "../csp-nonce-DDt0UNdt.js";
1
+ import { C as currentAuth, O as lazy, a as resolveDeferredValues, i as isDeferred, l as createRouteRegistry, m as resolveRouteRequest, n as Resolve, r as defer, s as routeData, w as Outlet } from "../deferred-vUOy-awa.js";
2
+ import { o as addRouteBasePath, y as getActiveRouteBasePath } from "../route-matching-DHduNiGk.js";
3
+ import { a as isSafeHref } from "../csp-nonce-Bc52OIVc.js";
3
4
  import { jsx } from "../jsx-runtime.js";
4
- import { a as route, i as page, n as group, r as index, t as fallback } from "../authoring-DbGEgg40.js";
5
- import { n as onRouteChange, t as currentRoute } from "../activity-CnSRFO3d.js";
6
- import { a as serializeRouteMeta, c as getCurrentHref, d as parseTargetUrl, h as syncRegisteredRouteSnapshot, i as resolveRouteMeta, l as getRegisteredAppsSnapshot, m as syncAppRegistrationLocation, n as navigate, p as setCurrentRouteLocation, r as reconcileRouteMeta, s as saveScrollPosition, u as getWindowHref } from "../navigate-Crvd5gUG.js";
5
+ import { a as route, i as page, n as group, r as index, t as fallback } from "../authoring-DdQ3pHqt.js";
6
+ import { n as onRouteChange, t as currentRoute } from "../activity-Jd9CgEa3.js";
7
+ import { a as serializeRouteMeta, c as getCurrentHref, d as parseTargetUrl, h as syncRegisteredRouteSnapshot, i as resolveRouteMeta, l as getRegisteredAppsSnapshot, m as syncAppRegistrationLocation, n as navigate, p as setCurrentRouteLocation, r as reconcileRouteMeta, s as saveScrollPosition, u as getWindowHref } from "../navigate-b4GGxO_l.js";
7
8
  import { o as mergeProps } from "../compose-ref-Cc_YkUpM.js";
8
9
  import { t as applyInteractionPolicy } from "../interactions-DgGQyUQv.js";
9
10
  //#region src/router/route-query.ts
@@ -116,7 +117,7 @@ function formatSearchIssues(issues) {
116
117
  return issues.map((issue) => `${issue.path.length ? issue.path.join(".") : "search"}: ${issue.message}`).join("; ");
117
118
  }
118
119
  function to(route, params, search) {
119
- const path = buildPath(route, params);
120
+ const path = addRouteBasePath(buildPath(route, params), route.basePath ?? "");
120
121
  const parsedSearch = route.searchSchema?.safeParse(search ?? {});
121
122
  if (parsedSearch && !parsedSearch.success) throw new Error(`Invalid route search. ${formatSearchIssues(parsedSearch.issues)}`);
122
123
  const values = parsedSearch?.success ? parsedSearch.data : search;
@@ -167,7 +168,8 @@ function isSameOriginNavigableHref(href) {
167
168
  * - Composable via mergeProps
168
169
  */
169
170
  function Link({ href: suppliedHref, to, class: className, children, rel, target, "aria-current": ariaCurrent, "aria-label": ariaLabel, onPress, onClick, ...rest }) {
170
- const href = to?.href ?? suppliedHref;
171
+ const supplied = to?.href ?? suppliedHref;
172
+ const href = supplied ? addRouteBasePath(supplied, getActiveRouteBasePath()) : supplied;
171
173
  if (!href) throw new Error("Link requires href or to.");
172
174
  if (!isSafeHref(href)) throw new TypeError("Link href uses an unsafe URL scheme.");
173
175
  const handleNavigation = (e) => {
@@ -1,6 +1,6 @@
1
- import { t as enqueueRuntimeLane } from "./access-ePqdQqkV.js";
2
- import { c as markReadableUsage, f as syncDerivedDependencySubscriptions, l as notifyReadableReaders, o as markReactivePropsDirtySource, p as withDerivedReadTracking, r as clearDerivedDependencySubscriptions, s as markReadableDerivedSubscribersDirty, u as recordReadableRead } from "./readable-B3VIOfd7.js";
1
+ import { t as enqueueRuntimeLane } from "./access-Dpfoi4cA.js";
3
2
  import { i as claimHookIndex, p as getCurrentInstance } from "./component-scope-DzJEbYGE.js";
3
+ import { c as markReadableUsage, f as syncDerivedDependencySubscriptions, l as notifyReadableReaders, o as markReactivePropsDirtySource, p as withDerivedReadTracking, r as clearDerivedDependencySubscriptions, s as markReadableDerivedSubscribersDirty, u as recordReadableRead } from "./readable-B5NtV7V0.js";
4
4
  //#region src/runtime/selector-store.ts
5
5
  const dirtySelectorRecords = /* @__PURE__ */ new Set();
6
6
  let hasPendingSelectorFlush = false;
@@ -1,5 +1,5 @@
1
- import { d as DocumentRenderContext, f as DocumentRenderer, u as DocumentRenderArgs } from "../control-Cix3yjVf.js";
2
- import { A as RouteHandler, I as RouteOptions, R as RoutePathParams, W as RouteRegistry, z as RoutePolicy } from "../index-TlEvex-C.js";
1
+ import { _ as SSRStyleRegistrationValidation, f as DocumentRenderArgs, m as DocumentRenderer, p as DocumentRenderContext } from "../control-DhUZU4_V.js";
2
+ import { A as RouteHandler, I as RouteOptions, R as RoutePathParams, W as RouteRegistry, z as RoutePolicy } from "../index-pIgGaXvS.js";
3
3
  import { AuthRequirement } from "@askrjs/auth";
4
4
  import "node:fs/promises";
5
5
  //#region src/ssg/types.d.ts
@@ -31,6 +31,10 @@ interface RouteConfig<Path extends string = string> {
31
31
  invalidationKeys?: string[];
32
32
  /** Route loader resolved completely before static HTML is rendered. */
33
33
  loader?: RouteOptions['loader'];
34
+ /** Select the loader data transported for initial hydration. */
35
+ dehydrate?: RouteOptions['dehydrate'];
36
+ /** @internal Public mount point inherited from the owning registry. */
37
+ basePath?: string;
34
38
  /**
35
39
  * SSG entry generator for parameterized routes.
36
40
  *
@@ -54,6 +58,8 @@ interface SSGBaseOptions {
54
58
  dataOverrides?: Record<string, unknown>;
55
59
  /** Optional document wrapper for full HTML output */
56
60
  document?: DocumentRenderer;
61
+ /** Diagnose document renderers that omit request-local SSR style registrations. */
62
+ styleRegistrationValidation?: SSRStyleRegistrationValidation;
57
63
  /** Static files or directories published with the generated routes. */
58
64
  assets?: readonly SSGAssetSource[];
59
65
  /** Optional concurrency limit for rendering (default: 1) */
@@ -68,7 +74,7 @@ interface SSGAssetSource {
68
74
  to?: string;
69
75
  }
70
76
  /** Options for createStaticGen */
71
- type SSGOptions<TRoutes extends readonly RouteConfig[] = RouteConfig[]> = SSGBaseOptions & {
77
+ type SSGOptions<_TRoutes extends readonly RouteConfig[] = RouteConfig[]> = SSGBaseOptions & {
72
78
  /** Explicit route registry captured with `createRouteRegistry()`. */
73
79
  registry: RouteRegistry;
74
80
  };
@@ -242,4 +248,4 @@ declare function createStaticGen(options: SSGOptions): {
242
248
  getResult(): SSGResult | null;
243
249
  };
244
250
  //#endregion
245
- export { type DiscoveredResources, type DocumentRenderArgs, type DocumentRenderContext, type DocumentRenderer, type RouteConfig, type RouteRenderReason, type RouteRenderResult, type RouteRenderStatus, type SSGAssetSource, type SSGGenerateOptions, type SSGMetadata, type SSGMode, type SSGOptions, type SSGResult, createStaticGen };
251
+ export { type DiscoveredResources, type DocumentRenderArgs, type DocumentRenderContext, type DocumentRenderer, type RouteConfig, type RouteRenderReason, type RouteRenderResult, type RouteRenderStatus, type SSGAssetSource, type SSGGenerateOptions, type SSGMetadata, type SSGMode, type SSGOptions, type SSGResult, type SSRStyleRegistrationValidation, createStaticGen };
package/dist/ssg/index.js CHANGED
@@ -1,8 +1,9 @@
1
- import "../access-ePqdQqkV.js";
2
- import { C as _preloadRouteHandler, S as getRenderHandler, a as resolveDeferredValues, l as createRouteRegistry, u as bindResolvedRouteData } from "../deferred-rdHAgyKe.js";
3
- import { a as route } from "../authoring-DbGEgg40.js";
4
- import { n as renderDocument } from "../ssr-CbQO5xd3.js";
5
- import { n as renderToString } from "../ssr-C_Ql5_Kg.js";
1
+ import "../access-Dpfoi4cA.js";
2
+ import { D as _preloadRouteHandler, E as getRenderHandler, a as resolveDeferredValues, g as prepareRouteHydrationData, l as createRouteRegistry, u as bindResolvedRouteData } from "../deferred-vUOy-awa.js";
3
+ import { o as addRouteBasePath } from "../route-matching-DHduNiGk.js";
4
+ import { a as route } from "../authoring-DdQ3pHqt.js";
5
+ import { n as renderDocument } from "../ssr-DSHd_Q9K.js";
6
+ import { n as renderToString } from "../ssr-CpiBHMNv.js";
6
7
  import * as fs from "node:fs/promises";
7
8
  import * as pathModule from "node:path";
8
9
  import * as os from "node:os";
@@ -141,17 +142,21 @@ function validateRoutes(routes) {
141
142
  * Render multiple routes in parallel with error handling
142
143
  */
143
144
  async function batchRenderRoutes(routes, options = {}) {
144
- const { seed = 12345, dataMap = {}, concurrency = 1, document } = options;
145
+ const { seed = 12345, dataMap = {}, concurrency = 1, document, styleRegistrationValidation = "warn" } = options;
145
146
  const workerCount = Math.max(1, Math.min(concurrency, routes.length || 1));
146
147
  const results = [];
147
148
  results.length = routes.length;
148
149
  let nextIndex = 0;
149
- const sharedRegistry = new Set(routes.map((route) => route.path)).size === routes.length ? createRouteRegistry(() => {
150
+ const hasUniquePaths = new Set(routes.map((route) => route.path)).size === routes.length;
151
+ const basePaths = new Set(routes.map((route) => route.basePath ?? ""));
152
+ const sharedBasePath = basePaths.size === 1 ? routes[0]?.basePath : void 0;
153
+ const sharedRegistry = hasUniquePaths && basePaths.size <= 1 ? createRouteRegistry(() => {
150
154
  for (const route$1 of routes) route(route$1.path, route$1.handler, { namespace: route$1.namespace });
151
- }) : void 0;
155
+ }, { basePath: sharedBasePath }) : void 0;
152
156
  const renderOne = async (route$2) => {
153
157
  const startTime = performance.now();
154
158
  const url = interpolateRoutePath(route$2.path, route$2.params);
159
+ const publicUrl = addRouteBasePath(url, route$2.basePath ?? "");
155
160
  const requestUrl = new URL(url, "http://localhost");
156
161
  const resolvedData = resolveSsgRouteData(dataMap, route$2.path, url);
157
162
  const baseData = resolvedData.hasData ? resolvedData.data : void 0;
@@ -161,6 +166,7 @@ async function batchRenderRoutes(routes, options = {}) {
161
166
  try {
162
167
  await _preloadRouteHandler(mergedHandler);
163
168
  let routeData;
169
+ let routeHydration;
164
170
  let hasRouteData = false;
165
171
  if (route$2.loader) {
166
172
  const controller = new AbortController();
@@ -179,24 +185,30 @@ async function batchRenderRoutes(routes, options = {}) {
179
185
  },
180
186
  signal: controller.signal
181
187
  };
188
+ const request = new Request(requestUrl);
182
189
  const loaded = await route$2.loader({
183
190
  ...loadContext,
184
- request: new Request(requestUrl)
191
+ request
185
192
  });
186
193
  await resolveDeferredValues(loaded, controller.signal);
187
194
  routeData = loaded;
195
+ routeHydration = prepareRouteHydrationData(loaded, route$2.dehydrate, {
196
+ ...loadContext,
197
+ request
198
+ }, url);
188
199
  hasRouteData = true;
189
200
  }
190
- const renderedHandler = hasRouteData ? bindResolvedRouteData(mergedHandler, routeData) : mergedHandler;
201
+ const renderedHandler = hasRouteData ? bindResolvedRouteData(mergedHandler, routeData, routeHydration) : mergedHandler;
191
202
  const registry = hasRouteData || !sharedRegistry ? createRouteRegistry(() => {
192
203
  route(route$2.path, renderedHandler, { namespace: route$2.namespace });
193
- }) : sharedRegistry;
204
+ }, { basePath: route$2.basePath }) : sharedRegistry;
194
205
  phase = "render";
195
206
  const html = renderToString({
196
- url,
207
+ url: publicUrl,
197
208
  registry,
198
209
  seed,
199
210
  data: baseData,
211
+ styleRegistrationValidation: "off",
200
212
  document: document === void 0 ? void 0 : ({ appHtml, context }) => renderDocument(document, {
201
213
  appHtml,
202
214
  context: {
@@ -215,7 +227,7 @@ async function batchRenderRoutes(routes, options = {}) {
215
227
  cspNonce: context.cspNonce,
216
228
  styles: context.styles
217
229
  }
218
- }, "createStaticGen()")
230
+ }, "createStaticGen()", styleRegistrationValidation)
219
231
  });
220
232
  const duration = performance.now() - startTime;
221
233
  return {
@@ -632,7 +644,9 @@ function routeRegistryToRouteConfigs(registry) {
632
644
  auth: options.auth,
633
645
  policies: options.policies,
634
646
  entries: options.entries,
635
- loader: options.loader
647
+ loader: options.loader,
648
+ dehydrate: options.dehydrate,
649
+ basePath: registry.manifest.basePath
636
650
  });
637
651
  }
638
652
  return routeConfigs;
@@ -766,7 +780,8 @@ function createStaticGen(options) {
766
780
  seed,
767
781
  dataMap,
768
782
  concurrency: resolvedConcurrency,
769
- document: options.document
783
+ document: options.document,
784
+ styleRegistrationValidation: options.styleRegistrationValidation
770
785
  }) : [];
771
786
  performance.now() - renderStartTime;
772
787
  const renderedByRouteId = /* @__PURE__ */ new Map();
@@ -1,6 +1,6 @@
1
- import { d as DocumentRenderContext, f as DocumentRenderer, m as SSRStyleRegistration, p as SSRData, u as DocumentRenderArgs } from "../control-Cix3yjVf.js";
1
+ import { _ as SSRStyleRegistrationValidation, f as DocumentRenderArgs, g as SSRStyleRegistration, h as SSRData, m as DocumentRenderer, p as DocumentRenderContext } from "../control-DhUZU4_V.js";
2
2
  import { r as JSXElement, s as Props } from "../jsx-Dvr2SGRG.js";
3
- import { A as RouteHandler, C as Route, J as RouteRequestResult, V as RouteRecord, W as RouteRegistry, g as AccessRedirectDecision, l as DeferredBoundaryRegistration, m as AccessDenyDecision, u as SSRPortalState, w as RouteAuthOptions } from "../index-TlEvex-C.js";
3
+ import { A as RouteHandler, C as Route, J as RouteRequestResult, V as RouteRecord, W as RouteRegistry, g as AccessRedirectDecision, l as DeferredBoundaryRegistration, m as AccessDenyDecision, u as SSRPortalState, w as RouteAuthOptions } from "../index-pIgGaXvS.js";
4
4
  import { D as QueryPrefetchContext, _ as CoreTelemetry, n as ServerQueryRegistry, v as DataRuntime } from "../index-5S-fi2xy.js";
5
5
  import { AuthContext } from "@askrjs/auth";
6
6
  //#region src/common/page-render-envelope.d.ts
@@ -29,6 +29,7 @@ interface RenderContext {
29
29
  params?: Record<string, string>;
30
30
  routes?: readonly Route[];
31
31
  routeAuth?: RouteAuthOptions;
32
+ basePath?: string;
32
33
  authContext?: AuthContext;
33
34
  signal?: AbortSignal;
34
35
  dataRuntime?: unknown;
@@ -51,6 +52,7 @@ declare function createRenderContext(seed?: number, opts?: {
51
52
  params?: Record<string, string>;
52
53
  routes?: readonly Route[];
53
54
  routeAuth?: RouteAuthOptions;
55
+ basePath?: string;
54
56
  signal?: AbortSignal;
55
57
  dataRuntime?: unknown;
56
58
  mode?: 'ssr' | 'spa';
@@ -92,6 +94,8 @@ type RouteRenderOptions = SSRRouteSource & {
92
94
  /** @internal Precomposed page state used by hydration verification. */
93
95
  envelope?: PageRenderEnvelope;
94
96
  cspNonce?: string;
97
+ /** Diagnose document renderers that omit request-local SSR style registrations. */
98
+ styleRegistrationValidation?: SSRStyleRegistrationValidation;
95
99
  };
96
100
  type RouteStreamOptions = RouteRenderOptions & {
97
101
  onChunk(html: string): void;
@@ -185,4 +189,4 @@ declare function renderToString(component: (props?: Record<string, unknown>) =>
185
189
  declare function renderToString(opts: RouteRenderOptions): string;
186
190
  declare function renderToStream(opts: RouteStreamOptions): void;
187
191
  //#endregion
188
- export { type DocumentRenderArgs, type DocumentRenderContext, type DocumentRenderer, type RenderRouteRequestOptions, type RenderRouteRequestResult, type SSRComponent, SSRDataMissingError, type SSRRoute, type SSRStyleRegistration, type VNode, createRenderContext, getRenderContext, renderResolvedToStringSync, renderRouteRequest, renderRouteRequestToString, renderToStream, renderToString, renderToStringSync, resolveRequest, withRenderContext, withRenderContextAsync };
192
+ export { type DocumentRenderArgs, type DocumentRenderContext, type DocumentRenderer, type RenderRouteRequestOptions, type RenderRouteRequestResult, type SSRComponent, SSRDataMissingError, type SSRRoute, type SSRStyleRegistration, type SSRStyleRegistrationValidation, type VNode, createRenderContext, getRenderContext, renderResolvedToStringSync, renderRouteRequest, renderRouteRequestToString, renderToStream, renderToString, renderToStringSync, resolveRequest, withRenderContext, withRenderContextAsync };
package/dist/ssr/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { d as SSRDataMissingError } from "../render-context-D-DFk2WN.js";
2
- import { a as renderResolvedToStringSync, c as createRenderContext, d as withRenderContextAsync, i as renderRouteRequestToString, l as getRenderContext, n as renderToString, o as renderToStringSync, r as renderRouteRequest, s as resolveRequest, t as renderToStream, u as withRenderContext } from "../ssr-C_Ql5_Kg.js";
2
+ import { a as renderResolvedToStringSync, c as createRenderContext, d as withRenderContextAsync, i as renderRouteRequestToString, l as getRenderContext, n as renderToString, o as renderToStringSync, r as renderRouteRequest, s as resolveRequest, t as renderToStream, u as withRenderContext } from "../ssr-CpiBHMNv.js";
3
3
  export { SSRDataMissingError, createRenderContext, getRenderContext, renderResolvedToStringSync, renderRouteRequest, renderRouteRequestToString, renderToStream, renderToString, renderToStringSync, resolveRequest, withRenderContext, withRenderContextAsync };
@@ -1,23 +1,23 @@
1
1
  import { t as __CONTROL_BOUNDARY__ } from "./control-C-ApnFs1.js";
2
2
  import { t as __ERROR_BOUNDARY__ } from "./vnode-D24p6IW2.js";
3
- import { v as logger } from "./access-ePqdQqkV.js";
4
- import { i as isFragmentType, n as Fragment, t as ELEMENT_TYPE } from "./jsx-C3IECePB.js";
5
- import { f as getExecutionContextFrame, h as markVNodeTreeWithContextFrame, l as callWithContext, n as createComponentInstance, p as getVNodeContextFrame } from "./component-internal-DsM75Gl1.js";
3
+ import { v as logger } from "./access-Dpfoi4cA.js";
6
4
  import { f as getCurrentComponentInstance, w as setCurrentComponentInstance } from "./component-scope-DzJEbYGE.js";
7
- import { t as cleanupComponent } from "./component-cleanup-oWN45rfa.js";
8
- import { p as isPromiseLike } from "./lifecycle-batch-CwHCDseR.js";
9
- import { _ as setControlBoundaryContextFrame, g as evaluateShowState, h as evaluateCaseState, i as evaluateForState, o as rollbackForStateTransaction, r as commitForStateTransaction } from "./for-internal-DRbV0h1d.js";
10
- import { _ as isPageRenderEnvelope, g as isEmptyPageRenderEnvelope, h as createPageRenderEnvelope, i as isDeferred, l as createRouteRegistry, m as resolveRouteRequest, t as DEFERRED_BOUNDARY } from "./deferred-rdHAgyKe.js";
5
+ import { i as isFragmentType, n as Fragment, t as ELEMENT_TYPE } from "./jsx-C3IECePB.js";
6
+ import { f as getExecutionContextFrame, h as markVNodeTreeWithContextFrame, l as callWithContext, n as createComponentInstance, p as getVNodeContextFrame } from "./component-internal-DcrLymUJ.js";
7
+ import { t as cleanupComponent } from "./component-cleanup-BUfUleGZ.js";
8
+ import { p as isPromiseLike } from "./lifecycle-batch-Dfpid9-A.js";
9
+ import { _ as setControlBoundaryContextFrame, g as evaluateShowState, h as evaluateCaseState, i as evaluateForState, o as rollbackForStateTransaction, r as commitForStateTransaction } from "./for-internal-B_mnQhan.js";
10
+ import { _ as validateRouteHydrationData, b as isEmptyPageRenderEnvelope, h as getRouteHydrationMetadata, i as isDeferred, l as createRouteRegistry, m as resolveRouteRequest, t as DEFERRED_BOUNDARY, x as isPageRenderEnvelope, y as createPageRenderEnvelope } from "./deferred-vUOy-awa.js";
11
11
  import { d as SSRDataMissingError, l as stopRenderPhase$1, s as startRenderPhase$1, t as configureRenderContextProvider } from "./render-context-D-DFk2WN.js";
12
- import { a as resolveRouteFromRoutes, t as _resolveRouteMatchFromRoutes } from "./route-matching-BUwz4kfl.js";
12
+ import { a as resolveRouteFromRoutes, c as removeRouteBasePath, s as normalizeRouteBasePath, t as _resolveRouteMatchFromRoutes } from "./route-matching-DHduNiGk.js";
13
13
  import { n as SSR_PORTAL_HOST, t as SSR_PORTAL_ANCHOR } from "./portal-w3oQ6oQU.js";
14
- import { a as disposeDefaultPortalScope, t as DefaultPortal } from "./portal-BZ_rN17v.js";
14
+ import { a as disposeDefaultPortalScope, t as DefaultPortal } from "./portal-BVWjAhNQ.js";
15
15
  import { n as getPublicAttributeName, t as sanitizeCssValue } from "./css-BuPaTOfe.js";
16
- import { a as isSafeHref, r as validateCspNonce, t as CspNonceScope } from "./csp-nonce-DDt0UNdt.js";
16
+ import { o as isUnsafeUrlAttribute, r as validateCspNonce, t as CspNonceScope } from "./csp-nonce-Bc52OIVc.js";
17
17
  import { t as createDataRuntime } from "./data-runtime-D68YOo9L.js";
18
18
  import { c as withTelemetry, i as dehydrateDataRuntime, t as createQueryPrefetchContext } from "./query-registry-BL6rjGsO.js";
19
- import { a as route } from "./authoring-DbGEgg40.js";
20
- import { n as renderDocument, t as SSR_RENDER_DATA_ATTR } from "./ssr-CbQO5xd3.js";
19
+ import { a as route } from "./authoring-DdQ3pHqt.js";
20
+ import { n as renderDocument, t as SSR_RENDER_DATA_ATTR } from "./ssr-DSHd_Q9K.js";
21
21
  //#region src/ssr/escape.ts
22
22
  /**
23
23
  * HTML escaping utilities for SSR
@@ -197,6 +197,7 @@ function createRenderContext(seed = 12345, opts = {}) {
197
197
  params: opts.params,
198
198
  routes: opts.routes,
199
199
  routeAuth: opts.routeAuth,
200
+ basePath: opts.basePath,
200
201
  signal: opts.signal,
201
202
  dataRuntime: opts.dataRuntime ?? createDataRuntime({ queryCache }),
202
203
  mode: opts.mode ?? "ssr",
@@ -307,7 +308,9 @@ function resolvePolicyAwareSSRRoute(opts, routeTable) {
307
308
  let href = opts.url;
308
309
  const visited = /* @__PURE__ */ new Set();
309
310
  for (let redirects = 0; redirects <= MAX_SSR_REDIRECTS; redirects += 1) {
310
- const matched = _resolveRouteMatchFromRoutes(new URL(href, "http://localhost").pathname, routeTable);
311
+ const logicalHref = removeRouteBasePath(href, normalizeRouteBasePath(manifest.basePath));
312
+ if (logicalHref === void 0) throw new Error(`SSR: no route found for url: ${href}`);
313
+ const matched = _resolveRouteMatchFromRoutes(new URL(logicalHref, "http://localhost").pathname, routeTable);
311
314
  if (!matched) throw new Error(`SSR: no route found for url: ${href}`);
312
315
  const resolved = getRouteRequestResultSync(resolveRouteRequest(href, {
313
316
  registry: opts.registry,
@@ -446,13 +449,14 @@ function resolveSSRRouteSource(source) {
446
449
  }));
447
450
  }
448
451
  function resolveSSRRouteRender(opts) {
449
- const { seed = 12345, data, document } = opts;
452
+ const { seed = 12345, data, document, styleRegistrationValidation = "warn" } = opts;
450
453
  const cspNonce = validateCspNonce(opts.cspNonce);
451
454
  const routeTable = resolveSSRRouteSource(opts);
452
455
  const resolvedRoute = resolvePolicyAwareSSRRoute(opts, routeTable);
453
456
  const requestUrl = new URL(resolvedRoute.url, "http://localhost");
454
457
  const ctx = createRenderContext(seed, {
455
458
  url: resolvedRoute.url,
459
+ basePath: opts.registry.manifest.basePath,
456
460
  data,
457
461
  params: resolvedRoute.params,
458
462
  routes: routeTable,
@@ -470,7 +474,8 @@ function resolveSSRRouteRender(opts) {
470
474
  data,
471
475
  ctx,
472
476
  document,
473
- cspNonce
477
+ cspNonce,
478
+ styleRegistrationValidation
474
479
  };
475
480
  }
476
481
  function buildDocumentRenderArgs(resolved, appHtml) {
@@ -514,7 +519,7 @@ function renderToSinkInternal(opts, host) {
514
519
  const appSink = new StringSink();
515
520
  renderResolvedRouteAppToSink(resolved, appSink, host);
516
521
  appSink.end();
517
- sink.write(renderDocument(resolved.document, buildDocumentRenderArgs(resolved, appSink.toString()), "renderToString()/renderToStream()"));
522
+ sink.write(renderDocument(resolved.document, buildDocumentRenderArgs(resolved, appSink.toString()), "renderToString()/renderToStream()", resolved.styleRegistrationValidation));
518
523
  });
519
524
  }
520
525
  function renderRouteToString(opts, host) {
@@ -781,7 +786,7 @@ function renderAttrsDirect(props, sink) {
781
786
  }
782
787
  if (value === false || value === null || value === void 0) continue;
783
788
  const strValue = String(value);
784
- if (attrName.toLowerCase() === "href" && !isSafeHref(strValue)) continue;
789
+ if (isUnsafeUrlAttribute(attrName, strValue)) continue;
785
790
  sink.write(" ");
786
791
  sink.write(attrName);
787
792
  sink.write("=\"");
@@ -816,7 +821,7 @@ function renderAttrs(props, opts) {
816
821
  else if (value === false || value === null || value === void 0) continue;
817
822
  else {
818
823
  const strValue = String(value);
819
- if (attrName.toLowerCase() === "href" && !isSafeHref(strValue)) continue;
824
+ if (isUnsafeUrlAttribute(attrName, strValue)) continue;
820
825
  attrParts.push(` ${attrName}="${getEscapedAttrValue(strValue)}"`);
821
826
  }
822
827
  }
@@ -853,6 +858,8 @@ function serializeHydrationRenderData(data, runtime) {
853
858
  route: current.route,
854
859
  framework: current.framework
855
860
  });
861
+ const routeHydration = getRouteHydrationMetadata(payload.framework);
862
+ if (routeHydration) validateRouteHydrationData(payload.route, routeHydration.r);
856
863
  if (isEmptyPageRenderEnvelope(payload)) return "";
857
864
  return `<script type="application/json" ${SSR_RENDER_DATA_ATTR}="true">${JSON.stringify(payload, hydrationReplacer).replace(/</g, "\\u003C").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029")}<\/script>`;
858
865
  }
@@ -880,20 +887,23 @@ function renderDeferredBoundarySync(node, ctx) {
880
887
  return `<askr-resolve data-askr-deferred="${id}">${renderRenderableSync(pending, ctx)}</askr-resolve>`;
881
888
  }
882
889
  function isMultiRangeChild(child) {
883
- if (Array.isArray(child)) return child.length !== 1;
890
+ if (Array.isArray(child)) return true;
884
891
  if (!child || typeof child !== "object" || !("type" in child)) return false;
885
- const vnode = child;
886
- if (!isFragmentType(vnode.type)) return false;
887
- return (getRenderableChildren(vnode)?.length ?? 0) !== 1;
892
+ return isFragmentType(child.type);
893
+ }
894
+ function renderForRangeChildSync(child, ctx) {
895
+ if (child && typeof child === "object" && "type" in child && typeof child.type === "function") {
896
+ const vnode = child;
897
+ return renderForRangeChildSync(inheritRenderableKey(vnode, executeComponentSync(vnode.type, vnode.props, ctx, getVNodeContextFrame(vnode) ?? null)), ctx);
898
+ }
899
+ const rendered = renderChildSync(child, ctx);
900
+ return isMultiRangeChild(child) ? `${RANGE_START}${rendered}${RANGE_END}` : rendered;
888
901
  }
889
902
  function renderControlChildrenSync(node, ctx) {
890
903
  const controlState = getControlBoundaryState(node);
891
904
  return withControlBoundaryChildren(node, (children) => {
892
905
  const values = children ?? [];
893
- if (controlState?.kind === "for") return values.map((child) => {
894
- const rendered = renderChildSync(child, ctx);
895
- return isMultiRangeChild(child) ? `${RANGE_START}${rendered}${RANGE_END}` : rendered;
896
- }).join("");
906
+ if (controlState?.kind === "for") return values.map((child) => renderForRangeChildSync(child, ctx)).join("");
897
907
  const rendered = renderChildrenSync(values, ctx);
898
908
  return values.length === 1 && isMultiRangeChild(values[0]) ? `${RANGE_START}${rendered}${RANGE_END}` : values.length !== 1 ? `${RANGE_START}${rendered}${RANGE_END}` : rendered;
899
909
  });
@@ -1398,6 +1408,9 @@ async function renderRouteRequestInternal(options) {
1398
1408
  });
1399
1409
  const context = createRenderContext(options.seed, {
1400
1410
  url: options.url,
1411
+ basePath: manifest.basePath,
1412
+ routes: options.registry.routes,
1413
+ routeAuth: options.auth ?? manifest.auth,
1401
1414
  data: options.data,
1402
1415
  framework: options.framework,
1403
1416
  signal,
@@ -1418,6 +1431,7 @@ async function renderRouteRequestInternal(options) {
1418
1431
  });
1419
1432
  if (!resolved) return { kind: "no-match" };
1420
1433
  if (resolved.kind !== "render") return resolved;
1434
+ context.params = resolved.params;
1421
1435
  const sink = new StringSink();
1422
1436
  renderSSRRouteAppToSink({
1423
1437
  route: {
@@ -0,0 +1,25 @@
1
+ //#region src/common/ssr.ts
2
+ function escapedStyleRawText(value) {
3
+ return value.replace(/<\//gi, "<\\/");
4
+ }
5
+ function validateDocumentStyleRegistrations(html, styles, apiName, validation) {
6
+ if (validation === "off" || !styles || styles.length === 0) return;
7
+ const dropped = styles.filter(({ cssText }) => !html.includes(cssText) && !html.includes(escapedStyleRawText(cssText)));
8
+ if (dropped.length === 0) return;
9
+ const registrations = dropped.map(({ id }) => JSON.stringify(id)).join(", ");
10
+ const message = `${apiName} document() dropped ${dropped.length} registered SSR style${dropped.length === 1 ? "" : "s"}: ${registrations}. Serialize context.styles into the returned document, or set styleRegistrationValidation to "off" when omission is intentional.`;
11
+ if (validation === "error") throw new Error(message);
12
+ console.warn(message);
13
+ }
14
+ function renderDocument(document, args, apiName, styleRegistrationValidation = "warn") {
15
+ const html = document(args);
16
+ if (typeof html !== "string") {
17
+ const received = typeof html === "object" && html !== null && "then" in html && typeof html.then === "function" ? "a Promise-like value" : html === null ? "null" : Array.isArray(html) ? "an array" : typeof html;
18
+ throw new Error(`${apiName} document() must synchronously return a string; received ${received}.`);
19
+ }
20
+ validateDocumentStyleRegistrations(html, args.context.styles, apiName, styleRegistrationValidation);
21
+ return html;
22
+ }
23
+ const SSR_RENDER_DATA_ATTR = "data-askr-render-data";
24
+ //#endregion
25
+ export { renderDocument as n, SSR_RENDER_DATA_ATTR as t };