@rangojs/router 0.0.0-experimental.7 → 0.0.0-experimental.71

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 (307) hide show
  1. package/AGENTS.md +9 -0
  2. package/README.md +942 -4
  3. package/dist/bin/rango.js +1689 -0
  4. package/dist/vite/index.js +4951 -930
  5. package/package.json +70 -60
  6. package/skills/breadcrumbs/SKILL.md +250 -0
  7. package/skills/cache-guide/SKILL.md +294 -0
  8. package/skills/caching/SKILL.md +93 -23
  9. package/skills/composability/SKILL.md +172 -0
  10. package/skills/debug-manifest/SKILL.md +12 -8
  11. package/skills/document-cache/SKILL.md +18 -16
  12. package/skills/fonts/SKILL.md +167 -0
  13. package/skills/hooks/SKILL.md +334 -72
  14. package/skills/host-router/SKILL.md +218 -0
  15. package/skills/intercept/SKILL.md +131 -8
  16. package/skills/layout/SKILL.md +100 -3
  17. package/skills/links/SKILL.md +92 -31
  18. package/skills/loader/SKILL.md +404 -44
  19. package/skills/middleware/SKILL.md +173 -34
  20. package/skills/mime-routes/SKILL.md +128 -0
  21. package/skills/parallel/SKILL.md +204 -1
  22. package/skills/prerender/SKILL.md +685 -0
  23. package/skills/rango/SKILL.md +85 -16
  24. package/skills/response-routes/SKILL.md +411 -0
  25. package/skills/route/SKILL.md +257 -14
  26. package/skills/router-setup/SKILL.md +210 -32
  27. package/skills/tailwind/SKILL.md +129 -0
  28. package/skills/theme/SKILL.md +9 -8
  29. package/skills/typesafety/SKILL.md +328 -89
  30. package/skills/use-cache/SKILL.md +324 -0
  31. package/src/__internal.ts +102 -4
  32. package/src/bin/rango.ts +321 -0
  33. package/src/browser/action-coordinator.ts +97 -0
  34. package/src/browser/action-response-classifier.ts +99 -0
  35. package/src/browser/app-version.ts +14 -0
  36. package/src/browser/event-controller.ts +92 -64
  37. package/src/browser/history-state.ts +80 -0
  38. package/src/browser/intercept-utils.ts +52 -0
  39. package/src/browser/link-interceptor.ts +24 -4
  40. package/src/browser/logging.ts +55 -0
  41. package/src/browser/merge-segment-loaders.ts +20 -12
  42. package/src/browser/navigation-bridge.ts +296 -558
  43. package/src/browser/navigation-client.ts +179 -69
  44. package/src/browser/navigation-store.ts +73 -55
  45. package/src/browser/navigation-transaction.ts +297 -0
  46. package/src/browser/network-error-handler.ts +61 -0
  47. package/src/browser/partial-update.ts +328 -313
  48. package/src/browser/prefetch/cache.ts +206 -0
  49. package/src/browser/prefetch/fetch.ts +150 -0
  50. package/src/browser/prefetch/observer.ts +65 -0
  51. package/src/browser/prefetch/policy.ts +48 -0
  52. package/src/browser/prefetch/queue.ts +160 -0
  53. package/src/browser/prefetch/resource-ready.ts +77 -0
  54. package/src/browser/rango-state.ts +112 -0
  55. package/src/browser/react/Link.tsx +230 -74
  56. package/src/browser/react/NavigationProvider.tsx +87 -11
  57. package/src/browser/react/context.ts +11 -0
  58. package/src/browser/react/filter-segment-order.ts +11 -0
  59. package/src/browser/react/index.ts +12 -12
  60. package/src/browser/react/location-state-shared.ts +95 -53
  61. package/src/browser/react/location-state.ts +60 -15
  62. package/src/browser/react/mount-context.ts +6 -1
  63. package/src/browser/react/nonce-context.ts +23 -0
  64. package/src/browser/react/shallow-equal.ts +27 -0
  65. package/src/browser/react/use-action.ts +29 -51
  66. package/src/browser/react/use-client-cache.ts +5 -3
  67. package/src/browser/react/use-handle.ts +30 -126
  68. package/src/browser/react/use-href.tsx +2 -2
  69. package/src/browser/react/use-link-status.ts +6 -5
  70. package/src/browser/react/use-navigation.ts +22 -63
  71. package/src/browser/react/use-params.ts +65 -0
  72. package/src/browser/react/use-pathname.ts +47 -0
  73. package/src/browser/react/use-router.ts +76 -0
  74. package/src/browser/react/use-search-params.ts +56 -0
  75. package/src/browser/react/use-segments.ts +80 -97
  76. package/src/browser/response-adapter.ts +73 -0
  77. package/src/browser/rsc-router.tsx +214 -58
  78. package/src/browser/scroll-restoration.ts +127 -52
  79. package/src/browser/segment-reconciler.ts +221 -0
  80. package/src/browser/segment-structure-assert.ts +16 -0
  81. package/src/browser/server-action-bridge.ts +510 -603
  82. package/src/browser/shallow.ts +6 -1
  83. package/src/browser/types.ts +141 -48
  84. package/src/browser/validate-redirect-origin.ts +29 -0
  85. package/src/build/generate-manifest.ts +235 -24
  86. package/src/build/generate-route-types.ts +39 -0
  87. package/src/build/index.ts +13 -0
  88. package/src/build/route-trie.ts +265 -0
  89. package/src/build/route-types/ast-helpers.ts +25 -0
  90. package/src/build/route-types/ast-route-extraction.ts +98 -0
  91. package/src/build/route-types/codegen.ts +102 -0
  92. package/src/build/route-types/include-resolution.ts +418 -0
  93. package/src/build/route-types/param-extraction.ts +48 -0
  94. package/src/build/route-types/per-module-writer.ts +128 -0
  95. package/src/build/route-types/router-processing.ts +618 -0
  96. package/src/build/route-types/scan-filter.ts +85 -0
  97. package/src/build/runtime-discovery.ts +231 -0
  98. package/src/cache/background-task.ts +34 -0
  99. package/src/cache/cache-key-utils.ts +44 -0
  100. package/src/cache/cache-policy.ts +125 -0
  101. package/src/cache/cache-runtime.ts +342 -0
  102. package/src/cache/cache-scope.ts +167 -309
  103. package/src/cache/cf/cf-cache-store.ts +571 -17
  104. package/src/cache/cf/index.ts +13 -3
  105. package/src/cache/document-cache.ts +116 -77
  106. package/src/cache/handle-capture.ts +81 -0
  107. package/src/cache/handle-snapshot.ts +41 -0
  108. package/src/cache/index.ts +1 -15
  109. package/src/cache/memory-segment-store.ts +191 -13
  110. package/src/cache/profile-registry.ts +73 -0
  111. package/src/cache/read-through-swr.ts +134 -0
  112. package/src/cache/segment-codec.ts +256 -0
  113. package/src/cache/taint.ts +153 -0
  114. package/src/cache/types.ts +72 -122
  115. package/src/client.rsc.tsx +3 -1
  116. package/src/client.tsx +105 -179
  117. package/src/component-utils.ts +4 -4
  118. package/src/components/DefaultDocument.tsx +5 -1
  119. package/src/context-var.ts +156 -0
  120. package/src/debug.ts +19 -9
  121. package/src/errors.ts +108 -2
  122. package/src/handle.ts +55 -29
  123. package/src/handles/MetaTags.tsx +73 -20
  124. package/src/handles/breadcrumbs.ts +66 -0
  125. package/src/handles/index.ts +1 -0
  126. package/src/handles/meta.ts +30 -13
  127. package/src/host/cookie-handler.ts +21 -15
  128. package/src/host/errors.ts +8 -8
  129. package/src/host/index.ts +4 -7
  130. package/src/host/pattern-matcher.ts +27 -27
  131. package/src/host/router.ts +61 -39
  132. package/src/host/testing.ts +8 -8
  133. package/src/host/types.ts +15 -7
  134. package/src/host/utils.ts +1 -1
  135. package/src/href-client.ts +119 -29
  136. package/src/index.rsc.ts +155 -19
  137. package/src/index.ts +223 -30
  138. package/src/internal-debug.ts +11 -0
  139. package/src/loader.rsc.ts +26 -157
  140. package/src/loader.ts +27 -10
  141. package/src/network-error-thrower.tsx +3 -1
  142. package/src/outlet-provider.tsx +45 -0
  143. package/src/prerender/param-hash.ts +37 -0
  144. package/src/prerender/store.ts +186 -0
  145. package/src/prerender.ts +524 -0
  146. package/src/reverse.ts +351 -0
  147. package/src/root-error-boundary.tsx +41 -29
  148. package/src/route-content-wrapper.tsx +7 -4
  149. package/src/route-definition/dsl-helpers.ts +982 -0
  150. package/src/route-definition/helper-factories.ts +200 -0
  151. package/src/route-definition/helpers-types.ts +434 -0
  152. package/src/route-definition/index.ts +55 -0
  153. package/src/route-definition/redirect.ts +101 -0
  154. package/src/route-definition/resolve-handler-use.ts +149 -0
  155. package/src/route-definition.ts +1 -1428
  156. package/src/route-map-builder.ts +217 -123
  157. package/src/route-name.ts +53 -0
  158. package/src/route-types.ts +70 -8
  159. package/src/router/content-negotiation.ts +215 -0
  160. package/src/router/debug-manifest.ts +72 -0
  161. package/src/router/error-handling.ts +9 -9
  162. package/src/router/find-match.ts +160 -0
  163. package/src/router/handler-context.ts +435 -86
  164. package/src/router/intercept-resolution.ts +402 -0
  165. package/src/router/lazy-includes.ts +237 -0
  166. package/src/router/loader-resolution.ts +356 -128
  167. package/src/router/logging.ts +251 -0
  168. package/src/router/manifest.ts +154 -35
  169. package/src/router/match-api.ts +555 -0
  170. package/src/router/match-context.ts +5 -3
  171. package/src/router/match-handlers.ts +440 -0
  172. package/src/router/match-middleware/background-revalidation.ts +108 -93
  173. package/src/router/match-middleware/cache-lookup.ts +459 -10
  174. package/src/router/match-middleware/cache-store.ts +98 -26
  175. package/src/router/match-middleware/intercept-resolution.ts +57 -17
  176. package/src/router/match-middleware/segment-resolution.ts +80 -6
  177. package/src/router/match-pipelines.ts +10 -45
  178. package/src/router/match-result.ts +135 -35
  179. package/src/router/metrics.ts +240 -15
  180. package/src/router/middleware-cookies.ts +55 -0
  181. package/src/router/middleware-types.ts +220 -0
  182. package/src/router/middleware.ts +324 -369
  183. package/src/router/navigation-snapshot.ts +182 -0
  184. package/src/router/pattern-matching.ts +211 -43
  185. package/src/router/prerender-match.ts +502 -0
  186. package/src/router/preview-match.ts +98 -0
  187. package/src/router/request-classification.ts +310 -0
  188. package/src/router/revalidation.ts +137 -38
  189. package/src/router/route-snapshot.ts +245 -0
  190. package/src/router/router-context.ts +41 -21
  191. package/src/router/router-interfaces.ts +484 -0
  192. package/src/router/router-options.ts +618 -0
  193. package/src/router/router-registry.ts +24 -0
  194. package/src/router/segment-resolution/fresh.ts +748 -0
  195. package/src/router/segment-resolution/helpers.ts +268 -0
  196. package/src/router/segment-resolution/loader-cache.ts +199 -0
  197. package/src/router/segment-resolution/revalidation.ts +1379 -0
  198. package/src/router/segment-resolution/static-store.ts +67 -0
  199. package/src/router/segment-resolution.ts +21 -0
  200. package/src/router/segment-wrappers.ts +291 -0
  201. package/src/router/telemetry-otel.ts +299 -0
  202. package/src/router/telemetry.ts +300 -0
  203. package/src/router/timeout.ts +148 -0
  204. package/src/router/trie-matching.ts +239 -0
  205. package/src/router/types.ts +78 -3
  206. package/src/router.ts +740 -4252
  207. package/src/rsc/handler-context.ts +45 -0
  208. package/src/rsc/handler.ts +907 -797
  209. package/src/rsc/helpers.ts +140 -6
  210. package/src/rsc/index.ts +0 -20
  211. package/src/rsc/loader-fetch.ts +229 -0
  212. package/src/rsc/manifest-init.ts +90 -0
  213. package/src/rsc/nonce.ts +14 -0
  214. package/src/rsc/origin-guard.ts +141 -0
  215. package/src/rsc/progressive-enhancement.ts +391 -0
  216. package/src/rsc/response-error.ts +37 -0
  217. package/src/rsc/response-route-handler.ts +347 -0
  218. package/src/rsc/rsc-rendering.ts +246 -0
  219. package/src/rsc/runtime-warnings.ts +42 -0
  220. package/src/rsc/server-action.ts +356 -0
  221. package/src/rsc/ssr-setup.ts +128 -0
  222. package/src/rsc/types.ts +46 -11
  223. package/src/search-params.ts +230 -0
  224. package/src/segment-system.tsx +165 -17
  225. package/src/server/context.ts +315 -58
  226. package/src/server/cookie-store.ts +190 -0
  227. package/src/server/fetchable-loader-store.ts +37 -0
  228. package/src/server/handle-store.ts +113 -15
  229. package/src/server/loader-registry.ts +24 -64
  230. package/src/server/request-context.ts +607 -81
  231. package/src/server.ts +35 -130
  232. package/src/ssr/index.tsx +103 -30
  233. package/src/static-handler.ts +126 -0
  234. package/src/theme/ThemeProvider.tsx +21 -15
  235. package/src/theme/ThemeScript.tsx +5 -5
  236. package/src/theme/constants.ts +5 -2
  237. package/src/theme/index.ts +4 -14
  238. package/src/theme/theme-context.ts +4 -30
  239. package/src/theme/theme-script.ts +21 -18
  240. package/src/types/boundaries.ts +158 -0
  241. package/src/types/cache-types.ts +198 -0
  242. package/src/types/error-types.ts +192 -0
  243. package/src/types/global-namespace.ts +100 -0
  244. package/src/types/handler-context.ts +791 -0
  245. package/src/types/index.ts +88 -0
  246. package/src/types/loader-types.ts +210 -0
  247. package/src/types/route-config.ts +170 -0
  248. package/src/types/route-entry.ts +109 -0
  249. package/src/types/segments.ts +151 -0
  250. package/src/types.ts +1 -1623
  251. package/src/urls/include-helper.ts +197 -0
  252. package/src/urls/index.ts +53 -0
  253. package/src/urls/path-helper-types.ts +346 -0
  254. package/src/urls/path-helper.ts +364 -0
  255. package/src/urls/pattern-types.ts +107 -0
  256. package/src/urls/response-types.ts +116 -0
  257. package/src/urls/type-extraction.ts +372 -0
  258. package/src/urls/urls-function.ts +98 -0
  259. package/src/urls.ts +1 -802
  260. package/src/use-loader.tsx +161 -81
  261. package/src/vite/discovery/bundle-postprocess.ts +181 -0
  262. package/src/vite/discovery/discover-routers.ts +348 -0
  263. package/src/vite/discovery/prerender-collection.ts +439 -0
  264. package/src/vite/discovery/route-types-writer.ts +258 -0
  265. package/src/vite/discovery/self-gen-tracking.ts +47 -0
  266. package/src/vite/discovery/state.ts +117 -0
  267. package/src/vite/discovery/virtual-module-codegen.ts +203 -0
  268. package/src/vite/index.ts +15 -1129
  269. package/src/vite/plugin-types.ts +103 -0
  270. package/src/vite/plugins/cjs-to-esm.ts +93 -0
  271. package/src/vite/plugins/client-ref-dedup.ts +115 -0
  272. package/src/vite/plugins/client-ref-hashing.ts +105 -0
  273. package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +72 -53
  274. package/src/vite/plugins/expose-id-utils.ts +299 -0
  275. package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
  276. package/src/vite/plugins/expose-ids/handler-transform.ts +209 -0
  277. package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
  278. package/src/vite/plugins/expose-ids/router-transform.ts +110 -0
  279. package/src/vite/plugins/expose-ids/types.ts +45 -0
  280. package/src/vite/plugins/expose-internal-ids.ts +786 -0
  281. package/src/vite/plugins/performance-tracks.ts +88 -0
  282. package/src/vite/plugins/refresh-cmd.ts +127 -0
  283. package/src/vite/plugins/use-cache-transform.ts +323 -0
  284. package/src/vite/plugins/version-injector.ts +83 -0
  285. package/src/vite/plugins/version-plugin.ts +266 -0
  286. package/src/vite/{virtual-entries.ts → plugins/virtual-entries.ts} +23 -14
  287. package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
  288. package/src/vite/rango.ts +462 -0
  289. package/src/vite/router-discovery.ts +918 -0
  290. package/src/vite/utils/ast-handler-extract.ts +517 -0
  291. package/src/vite/utils/banner.ts +36 -0
  292. package/src/vite/utils/bundle-analysis.ts +137 -0
  293. package/src/vite/utils/manifest-utils.ts +70 -0
  294. package/src/vite/{package-resolution.ts → utils/package-resolution.ts} +25 -29
  295. package/src/vite/utils/prerender-utils.ts +207 -0
  296. package/src/vite/utils/shared-utils.ts +170 -0
  297. package/CLAUDE.md +0 -43
  298. package/src/browser/lru-cache.ts +0 -69
  299. package/src/browser/request-controller.ts +0 -164
  300. package/src/cache/memory-store.ts +0 -253
  301. package/src/href-context.ts +0 -33
  302. package/src/href.ts +0 -255
  303. package/src/server/route-manifest-cache.ts +0 -173
  304. package/src/vite/expose-handle-id.ts +0 -209
  305. package/src/vite/expose-loader-id.ts +0 -426
  306. package/src/vite/expose-location-state-id.ts +0 -177
  307. /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
@@ -0,0 +1,618 @@
1
+ import type { ComponentType, ReactNode } from "react";
2
+ import type { SegmentCacheStore } from "../cache/types.js";
3
+ import type {
4
+ ErrorBoundaryHandler,
5
+ NotFoundBoundaryHandler,
6
+ OnErrorCallback,
7
+ } from "../types";
8
+ import type { NonceProvider } from "../rsc/types.js";
9
+ import type { ExecutionContext } from "../server/request-context.js";
10
+ import type { UrlPatterns } from "../urls.js";
11
+ import type { UrlBuilder } from "../urls/pattern-types.js";
12
+ import type { NamedRouteEntry } from "./content-negotiation.js";
13
+ import type { TelemetrySink } from "./telemetry.js";
14
+ import type { RouterTimeouts, OnTimeoutCallback } from "./timeout.js";
15
+
16
+ /**
17
+ * SSR stream mode returned by resolveStreaming.
18
+ *
19
+ * - `"stream"` — start flushing HTML as soon as the shell is ready
20
+ * (default React SSR behavior via `renderToReadableStream`).
21
+ * - `"allReady"` — wait for every Suspense boundary to resolve before
22
+ * sending any bytes (equivalent to awaiting `stream.allReady`).
23
+ */
24
+ export type SSRStreamMode = "stream" | "allReady";
25
+
26
+ /**
27
+ * Context passed to the resolveStreaming callback.
28
+ */
29
+ export interface ResolveStreamingContext<TEnv = unknown> {
30
+ request: Request;
31
+ env: TEnv;
32
+ url: URL;
33
+ }
34
+
35
+ /**
36
+ * SSR configuration options.
37
+ */
38
+ export interface SSROptions<TEnv = unknown> {
39
+ /**
40
+ * Determine whether an HTML response should stream progressively or
41
+ * wait for full readiness before flushing.
42
+ *
43
+ * Called once per HTML request, before the HTML response is produced.
44
+ * Does NOT apply to RSC responses (`__rsc`, partial navigation, prefetch).
45
+ *
46
+ * Return `"stream"` (default) for progressive streaming or `"allReady"`
47
+ * to buffer the complete HTML before sending.
48
+ *
49
+ * @example Bot detection
50
+ * ```ts
51
+ * createRouter({
52
+ * ssr: {
53
+ * resolveStreaming: async ({ request, env }) => {
54
+ * const bot = await detectBot(request, env);
55
+ * return bot.isBot && !bot.supportsStreaming ? "allReady" : "stream";
56
+ * },
57
+ * },
58
+ * });
59
+ * ```
60
+ */
61
+ resolveStreaming?: (
62
+ context: ResolveStreamingContext<TEnv>,
63
+ ) => SSRStreamMode | Promise<SSRStreamMode>;
64
+ }
65
+
66
+ /**
67
+ * Props passed to the root layout component
68
+ */
69
+ export interface RootLayoutProps {
70
+ children: ReactNode;
71
+ }
72
+
73
+ /**
74
+ * Router configuration options
75
+ */
76
+ export interface RSCRouterOptions<TEnv = any> {
77
+ /**
78
+ * Unique identifier for this router instance.
79
+ * Used to namespace static output files and route maps.
80
+ * Auto-generated if not provided.
81
+ */
82
+ id?: string;
83
+
84
+ /**
85
+ * Injected by the Vite transform at compile time.
86
+ * Hash of filename + line number for stable cross-environment ID.
87
+ * @internal
88
+ */
89
+ $$id?: string;
90
+
91
+ /**
92
+ * Injected by the Vite transform at compile time.
93
+ * Absolute path of the source file that defines this router,
94
+ * relative to project root. Eliminates runtime stack trace parsing.
95
+ * @internal
96
+ */
97
+ $$sourceFile?: string;
98
+
99
+ /**
100
+ * URL prefix applied to all routes registered with this router.
101
+ *
102
+ * Useful when the app is served under a sub-path (e.g. `/admin` or `/v2`).
103
+ * All `path()` patterns are automatically prefixed and `reverse()` returns
104
+ * full paths including the basename. Route names are NOT prefixed.
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * const router = createRouter({
109
+ * basename: "/admin",
110
+ * }).routes(({ path }) => [
111
+ * path("/", Dashboard, { name: "home" }), // matches /admin
112
+ * path("/users", Users, { name: "users" }), // matches /admin/users
113
+ * ]);
114
+ *
115
+ * router.reverse("home"); // "/admin"
116
+ * router.reverse("users"); // "/admin/users"
117
+ * ```
118
+ */
119
+ basename?: string;
120
+
121
+ /**
122
+ * Enable performance metrics collection
123
+ * When enabled, metrics are output to console and available via Server-Timing header
124
+ */
125
+ debugPerformance?: boolean;
126
+
127
+ /**
128
+ * Allow the `?__debug_manifest` query parameter to return route manifest data as JSON.
129
+ * In development mode this is always enabled regardless of this setting.
130
+ * Defaults to false. Set to true to enable in production.
131
+ * @internal
132
+ */
133
+ allowDebugManifest?: boolean;
134
+
135
+ /**
136
+ * Document component that wraps the entire application.
137
+ *
138
+ * This component provides the HTML structure for your app and wraps
139
+ * both normal route content AND error states, preventing the app shell
140
+ * from unmounting during errors (avoids FOUC).
141
+ *
142
+ * Must be a client component ("use client") that accepts { children }.
143
+ *
144
+ * If not provided, a default document with basic HTML structure is used:
145
+ * `<html><head><meta charset/viewport></head><body>{children}</body></html>`
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * // components/Document.tsx
150
+ * "use client";
151
+ * export function Document({ children }: { children: ReactNode }) {
152
+ * return (
153
+ * <html lang="en">
154
+ * <head>
155
+ * <link rel="stylesheet" href="/styles.css" />
156
+ * </head>
157
+ * <body>
158
+ * <nav>...</nav>
159
+ * {children}
160
+ * </body>
161
+ * </html>
162
+ * );
163
+ * }
164
+ *
165
+ * // router.tsx
166
+ * const router = createRouter<AppEnv>({
167
+ * document: Document,
168
+ * });
169
+ * ```
170
+ */
171
+ document?: ComponentType<RootLayoutProps>;
172
+
173
+ /**
174
+ * Default error boundary fallback used when no error boundary is defined in the route tree
175
+ * If not provided, errors will propagate and crash the request
176
+ */
177
+ defaultErrorBoundary?: ReactNode | ErrorBoundaryHandler;
178
+
179
+ /**
180
+ * Default not-found boundary fallback used when no notFoundBoundary is defined in the route tree
181
+ * If not provided, DataNotFoundError will be treated as a regular error
182
+ */
183
+ defaultNotFoundBoundary?: ReactNode | NotFoundBoundaryHandler;
184
+
185
+ /**
186
+ * Component to render when no route matches the requested URL.
187
+ *
188
+ * This is rendered within your document/app shell with a 404 status code.
189
+ * Use this for a custom 404 page that maintains your app's look and feel.
190
+ *
191
+ * If not provided, a default "Page not found" component is rendered.
192
+ *
193
+ * Can be a static ReactNode or a function receiving the pathname.
194
+ *
195
+ * @example
196
+ * ```typescript
197
+ * // Simple static component
198
+ * const router = createRouter<AppEnv>({
199
+ * document: Document,
200
+ * notFound: <NotFound404 />,
201
+ * });
202
+ *
203
+ * // Dynamic component with pathname
204
+ * const router = createRouter<AppEnv>({
205
+ * document: Document,
206
+ * notFound: ({ pathname }) => (
207
+ * <div>
208
+ * <h1>404 - Not Found</h1>
209
+ * <p>No page exists at {pathname}</p>
210
+ * <a href="/">Go home</a>
211
+ * </div>
212
+ * ),
213
+ * });
214
+ * ```
215
+ */
216
+ notFound?: ReactNode | ((props: { pathname: string }) => ReactNode);
217
+
218
+ /**
219
+ * Callback invoked when an error occurs during request handling.
220
+ *
221
+ * This callback is for notification/logging purposes - it cannot modify
222
+ * the error handling flow. Use errorBoundary() in route definitions to
223
+ * customize error UI.
224
+ *
225
+ * The callback receives comprehensive context about the error including:
226
+ * - The error itself
227
+ * - Phase where it occurred (routing, middleware, loader, handler, etc.)
228
+ * - Request info (URL, method, params)
229
+ * - Route info (routeKey, segmentId)
230
+ * - Environment/bindings
231
+ * - Duration from request start
232
+ *
233
+ * @example
234
+ * ```typescript
235
+ * const router = createRouter<AppEnv>({
236
+ * onError: (context) => {
237
+ * // Send to error tracking service
238
+ * Sentry.captureException(context.error, {
239
+ * tags: {
240
+ * phase: context.phase,
241
+ * route: context.routeKey,
242
+ * },
243
+ * extra: {
244
+ * url: context.url.toString(),
245
+ * params: context.params,
246
+ * duration: context.duration,
247
+ * },
248
+ * });
249
+ * },
250
+ * });
251
+ * ```
252
+ */
253
+ onError?: OnErrorCallback<TEnv>;
254
+
255
+ /**
256
+ * Cache store for segment caching.
257
+ *
258
+ * When provided, enables route-level caching via cache() boundaries.
259
+ * The store handles persistence (memory, KV, Redis, etc.).
260
+ *
261
+ * Can be a static config or a function receiving env for runtime bindings.
262
+ *
263
+ * @example Static config
264
+ * ```typescript
265
+ * import { MemorySegmentCacheStore } from "@rangojs/router/cache";
266
+ *
267
+ * const router = createRouter({
268
+ * cache: {
269
+ * store: new MemorySegmentCacheStore({ defaults: { ttl: 60 } }),
270
+ * },
271
+ * });
272
+ * ```
273
+ *
274
+ * @example Dynamic config with env (e.g., Cloudflare Workers with ExecutionContext)
275
+ * ```typescript
276
+ * const router = createRouter<AppBindings>({
277
+ * cache: (_env, ctx) => ({
278
+ * store: new CFCacheStore({
279
+ * defaults: { ttl: 60 },
280
+ * ctx: ctx!, // ExecutionContext for non-blocking writes
281
+ * }),
282
+ * }),
283
+ * });
284
+ * ```
285
+ */
286
+ cache?:
287
+ | { store: SegmentCacheStore; enabled?: boolean }
288
+ | ((
289
+ env: TEnv,
290
+ ctx?: ExecutionContext,
291
+ ) => {
292
+ store: SegmentCacheStore;
293
+ enabled?: boolean;
294
+ });
295
+
296
+ /**
297
+ * Named cache profiles for "use cache" directive.
298
+ * Profile names map to TTL/SWR configuration.
299
+ *
300
+ * - `"use cache"` (no name) resolves to the `default` profile.
301
+ * - `"use cache: short"` resolves to the `short` profile.
302
+ *
303
+ * @example
304
+ * ```typescript
305
+ * createRouter({
306
+ * cacheProfiles: {
307
+ * default: { ttl: 900, swr: 1800 },
308
+ * short: { ttl: 60, swr: 120 },
309
+ * long: { ttl: 3600, swr: 7200 },
310
+ * products: { ttl: 300, swr: 600, tags: ['products'] },
311
+ * },
312
+ * });
313
+ * ```
314
+ */
315
+ cacheProfiles?: Record<
316
+ string,
317
+ import("../cache/profile-registry.js").CacheProfile
318
+ >;
319
+
320
+ /**
321
+ * Theme configuration for automatic theme management.
322
+ *
323
+ * When provided, enables:
324
+ * - ctx.theme and ctx.setTheme() in route handlers
325
+ * - useTheme() hook for client components
326
+ * - FOUC prevention via inline script in MetaTags
327
+ * - Automatic ThemeProvider wrapping in NavigationProvider
328
+ *
329
+ * @example
330
+ * ```typescript
331
+ * const router = createRouter<AppEnv>({
332
+ * theme: {
333
+ * defaultTheme: "system",
334
+ * themes: ["light", "dark"],
335
+ * }
336
+ * });
337
+ *
338
+ * // In route handler:
339
+ * route("settings", (ctx) => {
340
+ * const theme = ctx.theme; // "light" | "dark" | "system"
341
+ * ctx.setTheme("dark"); // Sets cookie
342
+ * return <SettingsPage />;
343
+ * });
344
+ *
345
+ * // In client component:
346
+ * import { useTheme } from "@rangojs/router/theme";
347
+ *
348
+ * function ThemeToggle() {
349
+ * const { theme, setTheme, themes } = useTheme();
350
+ * return <select value={theme} onChange={e => setTheme(e.target.value)}>
351
+ * {themes.map(t => <option key={t}>{t}</option>)}
352
+ * </select>;
353
+ * }
354
+ * ```
355
+ *
356
+ * Use `theme: true` to enable with all defaults.
357
+ */
358
+ theme?: import("../theme/types.js").ThemeConfig | true;
359
+
360
+ /**
361
+ * URL patterns to register with the router.
362
+ *
363
+ * Accepts either a `UrlPatterns` object from `urls()` or a builder function
364
+ * directly (urls() is called implicitly).
365
+ *
366
+ * @example
367
+ * ```typescript
368
+ * // With urls()
369
+ * createRouter<AppEnv>({
370
+ * document: Document,
371
+ * urls: urlpatterns,
372
+ * });
373
+ *
374
+ * // With builder function
375
+ * createRouter<AppEnv>({
376
+ * document: Document,
377
+ * urls: ({ path }) => [
378
+ * path("/", HomePage, { name: "home" }),
379
+ * path("/about", AboutPage, { name: "about" }),
380
+ * ],
381
+ * });
382
+ * ```
383
+ */
384
+ urls?: UrlPatterns<TEnv, any> | UrlBuilder<TEnv>;
385
+
386
+ /**
387
+ * Injected by the Vite transform at compile time.
388
+ * Static import of NamedRoutes from the generated named-routes file.
389
+ * Used to seed reverse() with the full named route map.
390
+ * @internal
391
+ */
392
+ $$routeNames?: Record<string, NamedRouteEntry>;
393
+
394
+ /**
395
+ * Nonce provider for Content Security Policy (CSP).
396
+ *
397
+ * Can be:
398
+ * - A function that returns a nonce string
399
+ * - A function that returns `true` to auto-generate a nonce
400
+ * - Undefined to disable nonce (default)
401
+ *
402
+ * The nonce will be applied to inline scripts injected by the RSC payload.
403
+ * It's also available to middleware via the typed `nonce` token:
404
+ * `import { nonce } from "@rangojs/router"; ctx.get(nonce)`
405
+ *
406
+ * @example Auto-generate nonce
407
+ * ```tsx
408
+ * createRouter({
409
+ * nonce: () => true,
410
+ * });
411
+ * ```
412
+ *
413
+ * @example Custom nonce from request context
414
+ * ```tsx
415
+ * createRouter({
416
+ * nonce: (request, env) => env.nonce,
417
+ * });
418
+ * ```
419
+ *
420
+ * @example Access nonce in middleware
421
+ * ```tsx
422
+ * import { nonce } from "@rangojs/router";
423
+ *
424
+ * const cspMiddleware: Middleware = async (ctx, next) => {
425
+ * const value = ctx.get(nonce); // string | undefined
426
+ * await next();
427
+ * };
428
+ * ```
429
+ */
430
+ nonce?: NonceProvider<TEnv>;
431
+
432
+ /**
433
+ * RSC version string included in metadata.
434
+ * The browser sends this back on partial requests to detect version mismatches.
435
+ *
436
+ * Defaults to the auto-generated VERSION from `@rangojs/router:version` virtual module.
437
+ * Only set this if you need a custom versioning strategy.
438
+ *
439
+ * @default VERSION from @rangojs/router:version
440
+ */
441
+ version?: string;
442
+
443
+ /**
444
+ * TTL (in seconds) for the in-memory prefetch cache and the
445
+ * Cache-Control header on prefetch responses.
446
+ *
447
+ * Controls how long prefetch responses are kept in the client-side
448
+ * in-memory cache and sets `Cache-Control: private, max-age=<ttl>`
449
+ * on server responses for CDN/edge caching.
450
+ *
451
+ * The cache is automatically invalidated on server actions regardless
452
+ * of TTL, so this is primarily a staleness safety net.
453
+ *
454
+ * Set to `false` to disable prefetch caching entirely.
455
+ *
456
+ * @default 300 (5 minutes)
457
+ */
458
+ prefetchCacheTTL?: number | false;
459
+
460
+ /**
461
+ * Enable connection warmup to keep TCP+TLS alive after idle periods.
462
+ *
463
+ * When enabled, the client sends a HEAD request after the user returns
464
+ * from an idle period (60s+), prewarming the TLS connection before
465
+ * the next navigation.
466
+ *
467
+ * @default true
468
+ */
469
+ warmup?: boolean;
470
+
471
+ /**
472
+ * Shorthand timeout (ms) applied to both action execution and render start.
473
+ * Does NOT apply to streamIdleMs.
474
+ * Overridden by individual values in `timeouts`.
475
+ *
476
+ * @example
477
+ * ```typescript
478
+ * createRouter({ timeout: 10_000 });
479
+ * ```
480
+ */
481
+ timeout?: number;
482
+
483
+ /**
484
+ * Structured timeout configuration per phase.
485
+ * Values here override the `timeout` shorthand.
486
+ *
487
+ * @example
488
+ * ```typescript
489
+ * createRouter({
490
+ * timeouts: {
491
+ * actionMs: 10_000,
492
+ * renderStartMs: 8_000,
493
+ * },
494
+ * });
495
+ * ```
496
+ */
497
+ timeouts?: RouterTimeouts;
498
+
499
+ /**
500
+ * Custom handler invoked when a timeout occurs.
501
+ * Receives context about which phase timed out and must return a Response.
502
+ * If not provided, returns a plain 504 with "Request timed out" body
503
+ * and X-Rango-Timeout-Phase header.
504
+ *
505
+ * If the callback throws, the default 504 response is used as fallback.
506
+ *
507
+ * @example
508
+ * ```typescript
509
+ * createRouter({
510
+ * timeout: 10_000,
511
+ * onTimeout: (ctx) => {
512
+ * return new Response(
513
+ * JSON.stringify({ error: "timeout", phase: ctx.phase }),
514
+ * { status: 504, headers: { "Content-Type": "application/json" } },
515
+ * );
516
+ * },
517
+ * });
518
+ * ```
519
+ */
520
+ onTimeout?: OnTimeoutCallback<TEnv>;
521
+
522
+ /**
523
+ * Telemetry sink for structured lifecycle events.
524
+ *
525
+ * When provided, the router emits events for request start/end,
526
+ * loader start/end/error, handler errors, cache decisions, and
527
+ * revalidation decisions.
528
+ *
529
+ * No-op when not configured (zero overhead).
530
+ *
531
+ * @example Console logging
532
+ * ```typescript
533
+ * import { createConsoleSink } from "@rangojs/router";
534
+ *
535
+ * const router = createRouter({
536
+ * telemetry: createConsoleSink(),
537
+ * });
538
+ * ```
539
+ *
540
+ * @example Custom sink
541
+ * ```typescript
542
+ * const router = createRouter({
543
+ * telemetry: {
544
+ * emit(event) {
545
+ * myTracer.record(event);
546
+ * },
547
+ * },
548
+ * });
549
+ * ```
550
+ */
551
+ telemetry?: TelemetrySink;
552
+
553
+ /**
554
+ * SSR configuration options.
555
+ *
556
+ * @example
557
+ * ```typescript
558
+ * createRouter({
559
+ * ssr: {
560
+ * resolveStreaming: async ({ request, env }) => {
561
+ * const bot = await detectBot(request, env);
562
+ * return bot.isBot ? "allReady" : "stream";
563
+ * },
564
+ * },
565
+ * });
566
+ * ```
567
+ */
568
+ ssr?: SSROptions<TEnv>;
569
+
570
+ /**
571
+ * Cross-origin request protection for server actions, loader fetches,
572
+ * and progressive enhancement form submissions.
573
+ *
574
+ * When enabled, the router validates that the request's Origin header
575
+ * (or Referer fallback) matches the Host before executing actions,
576
+ * loaders, or PE submissions. Requests without Origin/Referer are
577
+ * allowed (same-origin navigations, non-browser clients).
578
+ *
579
+ * The built-in check compares Origin against the Host header and
580
+ * url.protocol. It does NOT trust X-Forwarded-Host/Proto headers
581
+ * (they are client-controllable without a trusted proxy). On standard
582
+ * deployments (Cloudflare Workers, Node behind nginx/caddy) the Host
583
+ * header is already set to the public-facing host by the platform or
584
+ * proxy. For non-standard proxy setups where Host differs from the
585
+ * public origin, use a custom function that reads the appropriate
586
+ * forwarded headers from your trusted proxy.
587
+ *
588
+ * - `true` (default) -- enable built-in origin validation
589
+ * - `false` -- disable
590
+ * - function -- full custom control with access to env, phase,
591
+ * and the built-in check via `ctx.defaultCheck()`
592
+ *
593
+ * The callback receives `OriginCheckContext` with `request`, `url`,
594
+ * `env`, `routerId`, `phase` ("action" | "loader" | "pe-form"),
595
+ * and `defaultCheck()`. Return `true` to allow, `false` for default
596
+ * 403 rejection, or a `Response` for custom rejection.
597
+ *
598
+ * @default true
599
+ *
600
+ * @example Trusted proxy with X-Forwarded-Host
601
+ * ```ts
602
+ * createRouter({
603
+ * originCheck({ request, url, env, defaultCheck }) {
604
+ * if (env.TRUST_PROXY) {
605
+ * const origin = request.headers.get("origin");
606
+ * if (!origin) return true;
607
+ * if (origin === "null") return false;
608
+ * const host = request.headers.get("x-forwarded-host")
609
+ * ?? request.headers.get("host") ?? url.host;
610
+ * return origin.toLowerCase() === `${url.protocol}//${host}`.toLowerCase();
611
+ * }
612
+ * return defaultCheck();
613
+ * },
614
+ * });
615
+ * ```
616
+ */
617
+ originCheck?: import("../rsc/origin-guard.js").OriginCheckConfig<TEnv>;
618
+ }
@@ -0,0 +1,24 @@
1
+ import type { RSCRouterInternal } from "./router-interfaces.js";
2
+
3
+ /**
4
+ * Brand marker for identifying router instances at build time.
5
+ * Used by the Vite plugin to auto-discover routers from module exports.
6
+ */
7
+ export const RSC_ROUTER_BRAND = "__rsc_router__" as const;
8
+
9
+ /**
10
+ * Global registry of all router instances created via createRouter().
11
+ * Each router is keyed by its id (auto-generated or user-provided).
12
+ * Used by the Vite plugin at build time to discover routers and extract
13
+ * manifests, prefix trees, and pre-render candidates.
14
+ */
15
+ export const RouterRegistry: Map<
16
+ string,
17
+ RSCRouterInternal<any, any>
18
+ > = new Map();
19
+
20
+ export let routerAutoId = 0;
21
+
22
+ export function nextRouterAutoId(): number {
23
+ return routerAutoId++;
24
+ }