@rangojs/router 0.0.0-experimental.0f44aca1

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