@rangojs/router 0.0.0-experimental.14 → 0.0.0-experimental.141

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 (460) hide show
  1. package/AGENTS.md +17 -0
  2. package/README.md +432 -7
  3. package/dist/bin/rango.js +2073 -213
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +7258 -2714
  6. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  7. package/package.json +140 -67
  8. package/skills/api-client/SKILL.md +211 -0
  9. package/skills/breadcrumbs/SKILL.md +329 -0
  10. package/skills/bundle-analysis/SKILL.md +159 -0
  11. package/skills/cache-guide/SKILL.md +487 -0
  12. package/skills/caching/SKILL.md +357 -25
  13. package/skills/comparison/SKILL.md +50 -0
  14. package/skills/comparison/agents/openai.yaml +4 -0
  15. package/skills/comparison/references/framework-comparison.md +837 -0
  16. package/skills/composability/SKILL.md +246 -0
  17. package/skills/css/SKILL.md +76 -0
  18. package/skills/debug-manifest/SKILL.md +16 -10
  19. package/skills/document-cache/SKILL.md +87 -62
  20. package/skills/fonts/SKILL.md +6 -4
  21. package/skills/handler-use/SKILL.md +364 -0
  22. package/skills/hooks/SKILL.md +557 -79
  23. package/skills/host-router/SKILL.md +320 -0
  24. package/skills/i18n/SKILL.md +276 -0
  25. package/skills/intercept/SKILL.md +207 -15
  26. package/skills/layout/SKILL.md +146 -6
  27. package/skills/links/SKILL.md +304 -25
  28. package/skills/loader/SKILL.md +616 -54
  29. package/skills/middleware/SKILL.md +217 -37
  30. package/skills/migrate-nextjs/SKILL.md +611 -0
  31. package/skills/migrate-react-router/SKILL.md +927 -0
  32. package/skills/mime-routes/SKILL.md +42 -11
  33. package/skills/observability/SKILL.md +194 -0
  34. package/skills/parallel/SKILL.md +284 -3
  35. package/skills/ppr/SKILL.md +293 -0
  36. package/skills/prerender/SKILL.md +437 -52
  37. package/skills/rango/SKILL.md +369 -22
  38. package/skills/react-compiler/SKILL.md +168 -0
  39. package/skills/response-routes/SKILL.md +263 -121
  40. package/skills/route/SKILL.md +350 -21
  41. package/skills/router-setup/SKILL.md +246 -33
  42. package/skills/scripts/SKILL.md +179 -0
  43. package/skills/server-actions/SKILL.md +775 -0
  44. package/skills/shell-manifest/SKILL.md +185 -0
  45. package/skills/streams-and-websockets/SKILL.md +283 -0
  46. package/skills/tailwind/SKILL.md +27 -3
  47. package/skills/testing/SKILL.md +126 -222
  48. package/skills/testing/bindings.md +103 -0
  49. package/skills/testing/cache-prerender.md +127 -0
  50. package/skills/testing/client-components.md +124 -0
  51. package/skills/testing/e2e-parity.md +125 -0
  52. package/skills/testing/flight.md +91 -0
  53. package/skills/testing/handles.md +131 -0
  54. package/skills/testing/loader.md +128 -0
  55. package/skills/testing/middleware.md +99 -0
  56. package/skills/testing/render-handler.md +122 -0
  57. package/skills/testing/response-routes.md +95 -0
  58. package/skills/testing/reverse-and-types.md +85 -0
  59. package/skills/testing/server-actions.md +107 -0
  60. package/skills/testing/server-tree.md +128 -0
  61. package/skills/testing/setup.md +123 -0
  62. package/skills/theme/SKILL.md +9 -8
  63. package/skills/typesafety/SKILL.md +532 -103
  64. package/skills/use-cache/SKILL.md +367 -0
  65. package/skills/vercel/SKILL.md +128 -0
  66. package/skills/view-transitions/SKILL.md +337 -0
  67. package/src/__augment-tests__/augment.ts +81 -0
  68. package/src/__augment-tests__/augmented.check.ts +116 -0
  69. package/src/__internal.ts +77 -44
  70. package/src/bin/rango.ts +312 -15
  71. package/src/browser/action-coordinator.ts +114 -0
  72. package/src/browser/action-fence.ts +47 -0
  73. package/src/browser/app-shell.ts +39 -0
  74. package/src/browser/app-version.ts +14 -0
  75. package/src/browser/connection-warmup.ts +134 -0
  76. package/src/browser/cookie-name.ts +140 -0
  77. package/src/browser/event-controller.ts +293 -202
  78. package/src/browser/history-state.ts +101 -0
  79. package/src/browser/index.ts +3 -3
  80. package/src/browser/intercept-utils.ts +52 -0
  81. package/src/browser/invalidate-client-cache.ts +52 -0
  82. package/src/browser/link-interceptor.ts +24 -4
  83. package/src/browser/logging.ts +11 -0
  84. package/src/browser/merge-segment-loaders.ts +20 -12
  85. package/src/browser/navigation-bridge.ts +385 -576
  86. package/src/browser/navigation-client.ts +245 -75
  87. package/src/browser/navigation-store-handle.ts +38 -0
  88. package/src/browser/navigation-store.ts +184 -118
  89. package/src/browser/navigation-transaction.ts +247 -0
  90. package/src/browser/network-error-handler.ts +88 -0
  91. package/src/browser/partial-update.ts +412 -364
  92. package/src/browser/prefetch/cache.ts +359 -0
  93. package/src/browser/prefetch/fetch.ts +452 -0
  94. package/src/browser/prefetch/observer.ts +65 -0
  95. package/src/browser/prefetch/policy.ts +48 -0
  96. package/src/browser/prefetch/queue.ts +209 -0
  97. package/src/browser/prefetch/resource-ready.ts +77 -0
  98. package/src/browser/rango-state.ts +194 -0
  99. package/src/browser/react/Link.tsx +275 -68
  100. package/src/browser/react/NavigationProvider.tsx +265 -109
  101. package/src/browser/react/ScrollRestoration.tsx +10 -6
  102. package/src/browser/react/context.ts +11 -0
  103. package/src/browser/react/filter-segment-order.ts +70 -0
  104. package/src/browser/react/index.ts +0 -48
  105. package/src/browser/react/location-state-shared.ts +272 -60
  106. package/src/browser/react/location-state.ts +90 -20
  107. package/src/browser/react/mount-context.ts +6 -1
  108. package/src/browser/react/nonce-context.ts +23 -0
  109. package/src/browser/react/shallow-equal.ts +27 -0
  110. package/src/browser/react/use-action.ts +35 -66
  111. package/src/browser/react/use-handle.ts +39 -126
  112. package/src/browser/react/use-href.tsx +8 -1
  113. package/src/browser/react/use-link-status.ts +39 -13
  114. package/src/browser/react/use-navigation.ts +53 -69
  115. package/src/browser/react/use-params.ts +75 -0
  116. package/src/browser/react/use-pathname.ts +47 -0
  117. package/src/browser/react/use-reverse.ts +106 -0
  118. package/src/browser/react/use-router.ts +98 -0
  119. package/src/browser/react/use-search-params.ts +51 -0
  120. package/src/browser/react/use-segments.ts +72 -99
  121. package/src/browser/response-adapter.ts +164 -0
  122. package/src/browser/rsc-router.tsx +300 -72
  123. package/src/browser/scroll-restoration.ts +138 -50
  124. package/src/browser/segment-reconciler.ts +243 -0
  125. package/src/browser/segment-structure-assert.ts +17 -1
  126. package/src/browser/server-action-bridge.ts +668 -613
  127. package/src/browser/types.ts +223 -51
  128. package/src/browser/validate-redirect-origin.ts +56 -0
  129. package/src/build/collect-fallback-refs.ts +107 -0
  130. package/src/build/generate-manifest.ts +252 -161
  131. package/src/build/generate-route-types.ts +41 -1038
  132. package/src/build/index.ts +12 -7
  133. package/src/build/prefix-tree-utils.ts +123 -0
  134. package/src/build/route-trie.ts +225 -42
  135. package/src/build/route-types/ast-helpers.ts +25 -0
  136. package/src/build/route-types/ast-route-extraction.ts +105 -0
  137. package/src/build/route-types/codegen.ts +113 -0
  138. package/src/build/route-types/include-resolution.ts +812 -0
  139. package/src/build/route-types/param-extraction.ts +51 -0
  140. package/src/build/route-types/per-module-writer.ts +144 -0
  141. package/src/build/route-types/router-processing.ts +695 -0
  142. package/src/build/route-types/scan-filter.ts +85 -0
  143. package/src/build/route-types/source-scan.ts +216 -0
  144. package/src/build/runtime-discovery.ts +223 -0
  145. package/src/cache/background-task.ts +34 -0
  146. package/src/cache/cache-error.ts +104 -0
  147. package/src/cache/cache-key-utils.ts +60 -0
  148. package/src/cache/cache-policy.ts +199 -0
  149. package/src/cache/cache-runtime.ts +525 -0
  150. package/src/cache/cache-scope.ts +298 -332
  151. package/src/cache/cache-tag.ts +103 -0
  152. package/src/cache/cf/cf-base64.ts +33 -0
  153. package/src/cache/cf/cf-cache-constants.ts +127 -0
  154. package/src/cache/cf/cf-cache-store.ts +2508 -158
  155. package/src/cache/cf/cf-cache-types.ts +349 -0
  156. package/src/cache/cf/cf-kv-utils.ts +46 -0
  157. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  158. package/src/cache/cf/index.ts +17 -17
  159. package/src/cache/document-cache.ts +199 -92
  160. package/src/cache/handle-capture.ts +81 -0
  161. package/src/cache/handle-snapshot.ts +111 -0
  162. package/src/cache/index.ts +24 -35
  163. package/src/cache/memory-segment-store.ts +363 -30
  164. package/src/cache/profile-registry.ts +88 -0
  165. package/src/cache/read-through-swr.ts +178 -0
  166. package/src/cache/segment-codec.ts +248 -0
  167. package/src/cache/shell-snapshot.ts +368 -0
  168. package/src/cache/tag-invalidation.ts +230 -0
  169. package/src/cache/taint.ts +153 -0
  170. package/src/cache/types.ts +222 -211
  171. package/src/cache/vercel/index.ts +11 -0
  172. package/src/cache/vercel/vercel-cache-store.ts +1113 -0
  173. package/src/client.rsc.tsx +43 -21
  174. package/src/client.tsx +131 -347
  175. package/src/cloudflare/index.ts +11 -0
  176. package/src/cloudflare/tracing.ts +109 -0
  177. package/src/component-utils.ts +23 -4
  178. package/src/components/DefaultDocument.tsx +13 -3
  179. package/src/context-var.ts +168 -0
  180. package/src/debug.ts +19 -9
  181. package/src/decode-loader-results.ts +52 -0
  182. package/src/defer.ts +185 -0
  183. package/src/deps/ssr.ts +0 -1
  184. package/src/encode-kv.ts +49 -0
  185. package/src/errors.ts +106 -10
  186. package/src/escape-script.ts +52 -0
  187. package/src/handle.ts +110 -35
  188. package/src/handles/MetaTags.tsx +83 -59
  189. package/src/handles/Scripts.tsx +183 -0
  190. package/src/handles/breadcrumbs.ts +93 -0
  191. package/src/handles/deferred-resolution.ts +127 -0
  192. package/src/handles/is-thenable.ts +18 -0
  193. package/src/handles/meta.ts +44 -53
  194. package/src/handles/script.ts +244 -0
  195. package/src/host/cookie-handler.ts +20 -65
  196. package/src/host/errors.ts +21 -30
  197. package/src/host/index.ts +13 -9
  198. package/src/host/pattern-matcher.ts +50 -79
  199. package/src/host/router.ts +151 -121
  200. package/src/host/testing.ts +45 -32
  201. package/src/host/types.ts +52 -11
  202. package/src/host/utils.ts +2 -2
  203. package/src/href-client.ts +192 -57
  204. package/src/index.rsc.ts +173 -35
  205. package/src/index.ts +241 -73
  206. package/src/internal-debug.ts +9 -2
  207. package/src/loader-store.ts +500 -0
  208. package/src/loader.rsc.ts +31 -99
  209. package/src/loader.ts +30 -12
  210. package/src/missing-id-error.ts +68 -0
  211. package/src/outlet-context.ts +1 -1
  212. package/src/outlet-provider.tsx +41 -0
  213. package/src/prerender/param-hash.ts +16 -14
  214. package/src/prerender/store.ts +121 -21
  215. package/src/prerender.ts +460 -26
  216. package/src/redirect-origin.ts +100 -0
  217. package/src/regex-escape.ts +8 -0
  218. package/src/render-error-thrower.tsx +20 -0
  219. package/src/response-utils.ts +62 -0
  220. package/src/reverse.ts +198 -128
  221. package/src/root-error-boundary.tsx +42 -48
  222. package/src/route-content-wrapper.tsx +22 -77
  223. package/src/route-definition/dsl-helpers.ts +1116 -0
  224. package/src/route-definition/helper-factories.ts +88 -0
  225. package/src/route-definition/helpers-types.ts +505 -0
  226. package/src/route-definition/index.ts +54 -0
  227. package/src/route-definition/redirect.ts +134 -0
  228. package/src/route-definition/resolve-handler-use.ts +160 -0
  229. package/src/route-definition/use-item-types.ts +29 -0
  230. package/src/route-definition.ts +1 -1481
  231. package/src/route-map-builder.ts +82 -144
  232. package/src/route-name.ts +53 -0
  233. package/src/route-types.ts +71 -45
  234. package/src/router/basename.ts +14 -0
  235. package/src/router/content-negotiation.ts +263 -0
  236. package/src/router/debug-manifest.ts +72 -0
  237. package/src/router/error-handling.ts +54 -27
  238. package/src/router/find-match.ts +245 -0
  239. package/src/router/handler-context.ts +377 -125
  240. package/src/router/instrument.ts +350 -0
  241. package/src/router/intercept-resolution.ts +59 -28
  242. package/src/router/lazy-includes.ts +254 -0
  243. package/src/router/loader-resolution.ts +421 -157
  244. package/src/router/logging.ts +106 -6
  245. package/src/router/manifest.ts +131 -57
  246. package/src/router/match-api.ts +167 -246
  247. package/src/router/match-context.ts +4 -24
  248. package/src/router/match-handlers.ts +440 -0
  249. package/src/router/match-middleware/background-revalidation.ts +117 -93
  250. package/src/router/match-middleware/cache-lookup.ts +297 -150
  251. package/src/router/match-middleware/cache-store.ts +123 -51
  252. package/src/router/match-middleware/intercept-resolution.ts +44 -43
  253. package/src/router/match-middleware/segment-resolution.ts +64 -22
  254. package/src/router/match-pipelines.ts +11 -87
  255. package/src/router/match-result.ts +121 -50
  256. package/src/router/metrics.ts +219 -28
  257. package/src/router/middleware-types.ts +93 -0
  258. package/src/router/middleware.ts +505 -441
  259. package/src/router/navigation-snapshot.ts +133 -0
  260. package/src/router/params-util.ts +23 -0
  261. package/src/router/parse-pattern.ts +115 -0
  262. package/src/router/pattern-matching.ts +311 -142
  263. package/src/router/prefetch-cache-ttl.ts +51 -0
  264. package/src/router/prefetch-limits.ts +37 -0
  265. package/src/router/prerender-match.ts +547 -0
  266. package/src/router/preview-match.ts +102 -0
  267. package/src/router/request-classification.ts +278 -0
  268. package/src/router/revalidation.ts +203 -62
  269. package/src/router/route-snapshot.ts +246 -0
  270. package/src/router/router-context.ts +45 -48
  271. package/src/router/router-interfaces.ts +554 -0
  272. package/src/router/router-options.ts +779 -0
  273. package/src/router/router-registry.ts +21 -0
  274. package/src/router/segment-resolution/fresh.ts +772 -0
  275. package/src/router/segment-resolution/helpers.ts +348 -0
  276. package/src/router/segment-resolution/loader-cache.ts +250 -0
  277. package/src/router/segment-resolution/loader-mask.ts +44 -0
  278. package/src/router/segment-resolution/revalidation.ts +1331 -0
  279. package/src/router/segment-resolution/static-store.ts +81 -0
  280. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  281. package/src/router/segment-resolution/view-transition-default.ts +56 -0
  282. package/src/router/segment-resolution.ts +25 -1354
  283. package/src/router/segment-wrappers.ts +292 -0
  284. package/src/router/state-cookie-name.ts +33 -0
  285. package/src/router/substitute-pattern-params.ts +75 -0
  286. package/src/router/telemetry-otel.ts +261 -0
  287. package/src/router/telemetry.ts +377 -0
  288. package/src/router/timeout.ts +128 -0
  289. package/src/router/tracing.ts +206 -0
  290. package/src/router/trie-matching.ts +240 -61
  291. package/src/router/types.ts +23 -70
  292. package/src/router/url-params.ts +57 -0
  293. package/src/router.ts +781 -2378
  294. package/src/rsc/full-payload.ts +70 -0
  295. package/src/rsc/handler-context.ts +46 -0
  296. package/src/rsc/handler.ts +905 -1142
  297. package/src/rsc/helpers.ts +275 -19
  298. package/src/rsc/index.ts +2 -25
  299. package/src/rsc/json-route-result.ts +38 -0
  300. package/src/rsc/loader-fetch.ts +305 -0
  301. package/src/rsc/manifest-init.ts +77 -0
  302. package/src/rsc/nonce.ts +14 -0
  303. package/src/rsc/origin-guard.ts +155 -0
  304. package/src/rsc/progressive-enhancement.ts +502 -0
  305. package/src/rsc/redirect-guard.ts +99 -0
  306. package/src/rsc/response-cache-serve.ts +238 -0
  307. package/src/rsc/response-error.ts +104 -0
  308. package/src/rsc/response-route-handler.ts +257 -0
  309. package/src/rsc/rsc-rendering.ts +527 -0
  310. package/src/rsc/runtime-warnings.ts +55 -0
  311. package/src/rsc/server-action.ts +522 -0
  312. package/src/rsc/shell-capture.ts +897 -0
  313. package/src/rsc/shell-serve.ts +124 -0
  314. package/src/rsc/ssr-setup.ts +144 -0
  315. package/src/rsc/transition-gate.ts +89 -0
  316. package/src/rsc/types.ts +95 -12
  317. package/src/runtime-env.ts +18 -0
  318. package/src/search-params.ts +99 -82
  319. package/src/segment-content-promise.ts +67 -0
  320. package/src/segment-loader-promise.ts +149 -0
  321. package/src/segment-system.tsx +349 -134
  322. package/src/serialize.ts +243 -0
  323. package/src/server/context.ts +459 -85
  324. package/src/server/cookie-parse.ts +32 -0
  325. package/src/server/cookie-store.ts +310 -0
  326. package/src/server/fetchable-loader-store.ts +11 -6
  327. package/src/server/handle-store.ts +123 -42
  328. package/src/server/loader-registry.ts +51 -100
  329. package/src/server/request-context.ts +848 -157
  330. package/src/server.ts +15 -8
  331. package/src/ssr/index.tsx +443 -135
  332. package/src/ssr/ssr-root.tsx +228 -0
  333. package/src/static-handler.ts +45 -18
  334. package/src/testing/cache-status.ts +162 -0
  335. package/src/testing/collect-handle.ts +46 -0
  336. package/src/testing/dispatch.ts +701 -0
  337. package/src/testing/dom.entry.ts +22 -0
  338. package/src/testing/e2e/fixture.ts +188 -0
  339. package/src/testing/e2e/index.ts +128 -0
  340. package/src/testing/e2e/matchers.ts +35 -0
  341. package/src/testing/e2e/page-helpers.ts +272 -0
  342. package/src/testing/e2e/parity.ts +387 -0
  343. package/src/testing/e2e/server.ts +195 -0
  344. package/src/testing/flight-matchers.ts +97 -0
  345. package/src/testing/flight-normalize.ts +11 -0
  346. package/src/testing/flight-runtime.d.ts +57 -0
  347. package/src/testing/flight-tree.ts +682 -0
  348. package/src/testing/flight.entry.ts +52 -0
  349. package/src/testing/flight.ts +257 -0
  350. package/src/testing/generated-routes.ts +199 -0
  351. package/src/testing/index.ts +105 -0
  352. package/src/testing/internal/context.ts +371 -0
  353. package/src/testing/internal/flight-client-globals.ts +30 -0
  354. package/src/testing/internal/seed-vars.ts +54 -0
  355. package/src/testing/render-handler.ts +357 -0
  356. package/src/testing/render-route.tsx +584 -0
  357. package/src/testing/run-loader.ts +385 -0
  358. package/src/testing/run-middleware.ts +205 -0
  359. package/src/testing/run-transition-when.ts +164 -0
  360. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  361. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  362. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  363. package/src/testing/vitest-stubs/version.ts +5 -0
  364. package/src/testing/vitest.ts +305 -0
  365. package/src/theme/ThemeProvider.tsx +76 -98
  366. package/src/theme/ThemeScript.tsx +12 -14
  367. package/src/theme/constants.ts +57 -15
  368. package/src/theme/index.ts +3 -20
  369. package/src/theme/theme-context.ts +5 -35
  370. package/src/theme/theme-script.ts +43 -39
  371. package/src/theme/use-theme.ts +0 -3
  372. package/src/types/boundaries.ts +123 -0
  373. package/src/types/cache-types.ts +207 -0
  374. package/src/types/error-types.ts +132 -0
  375. package/src/types/global-namespace.ts +113 -0
  376. package/src/types/handler-context.ts +839 -0
  377. package/src/types/index.ts +81 -0
  378. package/src/types/loader-types.ts +212 -0
  379. package/src/types/request-scope.ts +112 -0
  380. package/src/types/route-config.ts +138 -0
  381. package/src/types/route-entry.ts +114 -0
  382. package/src/types/segments.ts +271 -0
  383. package/src/types.ts +1 -1795
  384. package/src/urls/include-helper.ts +162 -0
  385. package/src/urls/include-provider.ts +71 -0
  386. package/src/urls/index.ts +44 -0
  387. package/src/urls/path-helper-types.ts +413 -0
  388. package/src/urls/path-helper.ts +280 -0
  389. package/src/urls/pattern-types.ts +160 -0
  390. package/src/urls/response-types.ts +109 -0
  391. package/src/urls/type-extraction.ts +316 -0
  392. package/src/urls/urls-function.ts +80 -0
  393. package/src/urls.ts +1 -1341
  394. package/src/use-loader.tsx +406 -141
  395. package/src/vercel/index.ts +11 -0
  396. package/src/vercel/tracing.ts +88 -0
  397. package/src/vite/debug.ts +185 -0
  398. package/src/vite/discovery/bundle-postprocess.ts +182 -0
  399. package/src/vite/discovery/discover-routers.ts +389 -0
  400. package/src/vite/discovery/discovery-errors.ts +255 -0
  401. package/src/vite/discovery/gate-state.ts +171 -0
  402. package/src/vite/discovery/prerender-collection.ts +467 -0
  403. package/src/vite/discovery/route-types-writer.ts +214 -0
  404. package/src/vite/discovery/self-gen-tracking.ts +73 -0
  405. package/src/vite/discovery/state.ts +161 -0
  406. package/src/vite/discovery/virtual-module-codegen.ts +183 -0
  407. package/src/vite/index.ts +23 -2255
  408. package/src/vite/inject-client-debug.ts +36 -0
  409. package/src/vite/plugin-types.ts +303 -0
  410. package/src/vite/plugins/cjs-to-esm.ts +90 -0
  411. package/src/vite/plugins/client-ref-dedup.ts +120 -0
  412. package/src/vite/plugins/client-ref-hashing.ts +118 -0
  413. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  414. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  415. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  416. package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +88 -110
  417. package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +89 -79
  418. package/src/vite/plugins/expose-ids/export-analysis.ts +363 -0
  419. package/src/vite/plugins/expose-ids/handler-transform.ts +130 -0
  420. package/src/vite/plugins/expose-ids/loader-transform.ts +64 -0
  421. package/src/vite/plugins/expose-ids/router-transform.ts +199 -0
  422. package/src/vite/plugins/expose-ids/types.ts +45 -0
  423. package/src/vite/plugins/expose-internal-ids.ts +805 -0
  424. package/src/vite/plugins/performance-tracks.ts +89 -0
  425. package/src/vite/plugins/refresh-cmd.ts +127 -0
  426. package/src/vite/plugins/use-cache-transform.ts +313 -0
  427. package/src/vite/plugins/vercel-output.ts +384 -0
  428. package/src/vite/plugins/version-injector.ts +94 -0
  429. package/src/vite/plugins/version-plugin.ts +263 -0
  430. package/src/vite/plugins/virtual-entries.ts +234 -0
  431. package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
  432. package/src/vite/rango.ts +560 -0
  433. package/src/vite/router-discovery.ts +1638 -0
  434. package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +200 -37
  435. package/src/vite/utils/banner.ts +36 -0
  436. package/src/vite/utils/bundle-analysis.ts +132 -0
  437. package/src/vite/utils/client-chunks.ts +184 -0
  438. package/src/vite/utils/directive-prologue.ts +40 -0
  439. package/src/vite/utils/forward-user-plugins.ts +171 -0
  440. package/src/vite/utils/manifest-utils.ts +15 -0
  441. package/src/vite/utils/package-resolution.ts +89 -0
  442. package/src/vite/utils/prerender-utils.ts +249 -0
  443. package/src/vite/utils/shared-utils.ts +269 -0
  444. package/CLAUDE.md +0 -43
  445. package/dist/vite/index.named-routes.gen.ts +0 -103
  446. package/src/browser/lru-cache.ts +0 -69
  447. package/src/browser/react/use-client-cache.ts +0 -56
  448. package/src/browser/request-controller.ts +0 -164
  449. package/src/browser/shallow.ts +0 -35
  450. package/src/cache/memory-store.ts +0 -253
  451. package/src/handles/index.ts +0 -6
  452. package/src/href-context.ts +0 -33
  453. package/src/network-error-thrower.tsx +0 -21
  454. package/src/router.gen.ts +0 -6
  455. package/src/static-handler.gen.ts +0 -5
  456. package/src/urls.gen.ts +0 -8
  457. package/src/vite/expose-internal-ids.ts +0 -1167
  458. package/src/vite/package-resolution.ts +0 -125
  459. package/src/vite/virtual-entries.ts +0 -114
  460. /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
@@ -5,60 +5,185 @@
5
5
  */
6
6
 
7
7
  import type { HandlerContext, InternalHandlerContext } from "../types";
8
- import type { HandleStore } from "../server/handle-store.js";
9
- import { getRequestContext } from "../server/request-context.js";
10
- import { getSearchSchema } from "../route-map-builder.js";
8
+ import { _getRequestContext } from "../server/request-context.js";
9
+ import { getSearchSchema, isRouteRootScoped } from "../route-map-builder.js";
11
10
  import { parseSearchParams, serializeSearchParams } from "../search-params.js";
11
+ import {
12
+ contextGet,
13
+ contextSet,
14
+ isNonCacheable,
15
+ type ContextSetOptions,
16
+ } from "../context-var.js";
17
+ import { isInsideCacheScope } from "../server/context.js";
18
+ import { NOCACHE_SYMBOL, assertNotInsideCacheExec } from "../cache/taint.js";
19
+ import { isAutoGeneratedRouteName } from "../route-name.js";
20
+ import { PRERENDER_PASSTHROUGH } from "../prerender.js";
21
+ import { substitutePatternParams } from "./substitute-pattern-params.js";
22
+ import { fireAndForgetWaitUntil } from "../types/request-scope.js";
23
+
24
+ // Mutating Headers methods guarded so they throw inside "use cache" / cache()
25
+ // scope. Module-level constant (read-only, .has() lookups) so it is allocated
26
+ // once at module load instead of per createHandlerContext (per-request) call.
27
+ const MUTATING_HEADERS_METHODS = new Set(["set", "append", "delete"]);
28
+
29
+ /**
30
+ * Strip internal _rsc* query params from a URL.
31
+ * Returns a new URL with only user-facing params.
32
+ */
33
+ export function stripInternalParams(url: URL): URL {
34
+ const clean = new URL(url);
35
+ for (const key of [...clean.searchParams.keys()]) {
36
+ if (key.startsWith("_rsc")) {
37
+ clean.searchParams.delete(key);
38
+ }
39
+ }
40
+ return clean;
41
+ }
12
42
 
13
43
  /**
14
44
  * Resolve route name with namespace prefix support.
15
- * Supports local names, absolute names (dot notation), and path-based URLs.
45
+ * Supports local names (dot-prefixed) and absolute names (global lookup).
46
+ *
47
+ * @param rootScoped - Explicit override for root-scope check. When undefined,
48
+ * falls back to the global scope registry, then to a heuristic.
16
49
  */
17
50
  function resolveRouteName(
18
51
  name: string,
19
52
  routeMap: Record<string, string>,
20
- currentRoutePrefix?: string
53
+ currentRoutePrefix?: string,
54
+ rootScoped?: boolean,
21
55
  ): string | undefined {
22
- // 1. Path-based - starts with /
23
- if (name.startsWith("/")) {
24
- return name;
25
- }
26
-
27
- // 2. Absolute name - already has a dot (e.g., "shop.cart")
28
- if (name.includes(".")) {
29
- return routeMap[name];
30
- }
56
+ // 1. Dot-prefixed (".article", ".author.posts") — local resolution only.
57
+ // Resolves within the current include() scope using the mount prefix.
58
+ if (name.startsWith(".")) {
59
+ const lookupName = name.slice(1);
60
+ if (!currentRoutePrefix) return undefined;
31
61
 
32
- // 3. Local name - try with current prefix first, then fall back to direct lookup
33
- if (currentRoutePrefix) {
34
- // Extract the prefix from current route name
35
- // e.g., "blog.posts.detail" → prefix is "blog.posts"
62
+ // Extract the include prefix from current route name
63
+ // e.g., "magazine.author" -> prefix is "magazine"
36
64
  const lastDot = currentRoutePrefix.lastIndexOf(".");
37
- const prefix = lastDot > 0 ? currentRoutePrefix.substring(0, lastDot) : currentRoutePrefix;
65
+ const prefix =
66
+ lastDot > 0
67
+ ? currentRoutePrefix.substring(0, lastDot)
68
+ : currentRoutePrefix;
38
69
 
39
- // Try prefixed name
40
- const prefixedName = `${prefix}.${name}`;
70
+ // Try prefixed name at current level
71
+ const prefixedName = `${prefix}.${lookupName}`;
41
72
  if (routeMap[prefixedName] !== undefined) {
42
73
  return routeMap[prefixedName];
43
74
  }
44
75
 
45
- // If current route is a nested include, try parent prefixes
46
- // e.g., for "blog.posts.detail", try "blog.posts.index", then "blog.index"
76
+ // Walk up parent prefixes for nested includes
47
77
  let currentPrefix = prefix;
48
78
  while (currentPrefix.includes(".")) {
49
79
  const parentDot = currentPrefix.lastIndexOf(".");
50
80
  currentPrefix = currentPrefix.substring(0, parentDot);
51
- const parentPrefixedName = `${currentPrefix}.${name}`;
81
+ const parentPrefixedName = `${currentPrefix}.${lookupName}`;
52
82
  if (routeMap[parentPrefixedName] !== undefined) {
53
83
  return routeMap[parentPrefixedName];
54
84
  }
55
85
  }
86
+
87
+ // Fallback: try bare name at root scope only.
88
+ // Routes inside { name: "" } mounts are at root scope — their dot-local
89
+ // names can fall back to bare names (e.g., "sub.detail" reaching "flatIndex").
90
+ // Routes inside named mounts (e.g., { name: "magazine" }) are NOT at root
91
+ // scope — dot-local must not leak into unrelated global names.
92
+ //
93
+ // Resolution order: explicit param > scope registry > heuristic.
94
+ const isRootScoped =
95
+ rootScoped ??
96
+ isRouteRootScoped(currentRoutePrefix) ??
97
+ !currentRoutePrefix.includes(".");
98
+ if (isRootScoped) {
99
+ if (routeMap[lookupName] !== undefined) {
100
+ return routeMap[lookupName];
101
+ }
102
+ }
103
+
104
+ return undefined;
56
105
  }
57
106
 
58
- // Fall back to direct lookup (route without prefix)
107
+ // 2. Unprefixed ("magazine.index", "blog.post") — global resolution only.
108
+ // Direct lookup in the full named-routes map.
59
109
  return routeMap[name];
60
110
  }
61
111
 
112
+ function createPrerenderPassthroughFn(
113
+ build: boolean,
114
+ isPassthroughRoute: boolean,
115
+ ): () => typeof PRERENDER_PASSTHROUGH {
116
+ return () => {
117
+ if (!build) {
118
+ throw new Error(
119
+ "ctx.passthrough() can only be called during build-time prerendering.",
120
+ );
121
+ }
122
+ if (!isPassthroughRoute) {
123
+ throw new Error(
124
+ "ctx.passthrough() is only available on routes wrapped with " +
125
+ "Passthrough(). Remove the passthrough() call or wrap the " +
126
+ "Prerender definition with Passthrough(prerenderDef, liveHandler).",
127
+ );
128
+ }
129
+ return PRERENDER_PASSTHROUGH;
130
+ };
131
+ }
132
+
133
+ /**
134
+ * Create a reverse function for URL generation from route names.
135
+ * Used by both HandlerContext and MiddlewareContext.
136
+ *
137
+ * When currentParams is provided, those params are used as defaults for URL
138
+ * generation. This enables auto-filling mount params from include() prefixes:
139
+ * inner handlers can call ctx.reverse(".sibling") without explicitly passing
140
+ * params that are already known from the current URL match.
141
+ * Explicitly passed hrefParams take priority over currentParams.
142
+ */
143
+ export function createReverseFunction(
144
+ routeMap: Record<string, string>,
145
+ currentRoutePrefix?: string,
146
+ currentParams?: Record<string, string>,
147
+ rootScoped?: boolean,
148
+ ): (
149
+ name: string,
150
+ hrefParams?: Record<string, string>,
151
+ search?: Record<string, unknown>,
152
+ ) => string {
153
+ return (name, hrefParams, search) => {
154
+ // Resolve route name with namespace support
155
+ const pattern = resolveRouteName(
156
+ name,
157
+ routeMap,
158
+ currentRoutePrefix,
159
+ rootScoped,
160
+ );
161
+
162
+ if (pattern === undefined) {
163
+ throw new Error(
164
+ `Unknown route: "${name}"${currentRoutePrefix ? ` (current route: ${currentRoutePrefix})` : ""}`,
165
+ );
166
+ }
167
+
168
+ // Merge current request params as defaults, explicit params override
169
+ const effectiveParams = currentParams
170
+ ? { ...currentParams, ...hrefParams }
171
+ : hrefParams;
172
+
173
+ let result = effectiveParams
174
+ ? substitutePatternParams(pattern, effectiveParams, name)
175
+ : pattern;
176
+
177
+ // Append search params as query string
178
+ if (search) {
179
+ const qs = serializeSearchParams(search);
180
+ if (qs) result += `?${qs}`;
181
+ }
182
+
183
+ return result;
184
+ };
185
+ }
186
+
62
187
  /**
63
188
  * Create HandlerContext with typed env/var/get/set
64
189
  */
@@ -68,55 +193,91 @@ export function createHandlerContext<TEnv>(
68
193
  searchParams: URLSearchParams,
69
194
  pathname: string,
70
195
  url: URL,
71
- bindings: any = {},
196
+ bindings: TEnv = {} as TEnv,
72
197
  routeMap: Record<string, string> = {},
73
- routeName?: string
198
+ routeName?: string,
199
+ responseType?: string,
200
+ isPassthroughRoute: boolean = false,
74
201
  ): InternalHandlerContext<any, TEnv> {
75
202
  // Get variables from request context - this is the unified context
76
203
  // shared between middleware and route handlers
77
- const requestContext = getRequestContext();
78
- const variables: any = requestContext?.var ?? {};
79
-
80
- // Filter system parameters (starting with _rsc) from searchParams
81
- // This ensures handlers only see user-facing query params
82
- const cleanSearchParams = new URLSearchParams();
83
- searchParams.forEach((value, key) => {
84
- if (!key.startsWith("_rsc")) {
85
- cleanSearchParams.set(key, value);
86
- }
87
- });
88
-
89
- // Create clean URL without system params
90
- const cleanUrl = new URL(url);
91
- cleanUrl.search = cleanSearchParams.toString();
204
+ const requestContext = _getRequestContext();
205
+ const variables: any = requestContext?._variables ?? {};
92
206
 
93
207
  // If route has a search schema, parse URLSearchParams into typed object
94
208
  const searchSchema = routeName ? getSearchSchema(routeName) : undefined;
95
209
  const resolvedSearchParams = searchSchema
96
- ? parseSearchParams(cleanSearchParams, searchSchema)
97
- : cleanSearchParams;
210
+ ? parseSearchParams(searchParams, searchSchema)
211
+ : searchParams;
98
212
 
99
213
  // Get stub response from request context for setting headers
100
- const stubResponse = requestContext?.res ?? new Response(null, { status: 200 });
214
+ const stubResponse =
215
+ requestContext?.res ?? new Response(null, { status: 200 });
101
216
 
102
- return {
217
+ // Guard mutating Headers methods so they throw inside "use cache" or cache() scope.
218
+ // Uses lazy `ctx` reference (assigned below) — only the specific handler ctx
219
+ // is stamped by cache-runtime, not the shared request context.
220
+ // MUTATING_HEADERS_METHODS is hoisted to module scope (constant, read-only).
221
+ let ctx: InternalHandlerContext<any, TEnv>;
222
+ const guardedHeaders = new Proxy(stubResponse.headers, {
223
+ get(target, prop, receiver) {
224
+ const value = Reflect.get(target, prop, receiver);
225
+ if (typeof value === "function") {
226
+ if (MUTATING_HEADERS_METHODS.has(prop as string)) {
227
+ return (...args: any[]) => {
228
+ assertNotInsideCacheExec(ctx, "headers");
229
+ if (isInsideCacheScope()) {
230
+ throw new Error(
231
+ `ctx.headers.${String(prop)}() cannot be called inside a cache() boundary. ` +
232
+ `On cache hit the handler is skipped, so this side effect would be lost. ` +
233
+ `Move header mutations to a middleware or layout outside the cache() scope.`,
234
+ );
235
+ }
236
+ return value.apply(target, args);
237
+ };
238
+ }
239
+ return value.bind(target);
240
+ }
241
+ return value;
242
+ },
243
+ });
244
+
245
+ ctx = {
103
246
  params,
247
+ build: false,
248
+ dev: false,
104
249
  request,
105
- searchParams: resolvedSearchParams as any, // Filtered params (typed object or URLSearchParams)
250
+ searchParams,
251
+ search: searchSchema ? resolvedSearchParams : {},
106
252
  pathname,
107
- url: cleanUrl, // Clean URL
253
+ url,
254
+ originalUrl: requestContext?.originalUrl ?? new URL(request.url),
108
255
  env: bindings,
109
- var: variables,
110
- get: ((key: string) => variables[key]) as HandlerContext<
111
- any,
112
- TEnv
113
- >["get"],
114
- set: ((key: string, value: any) => {
115
- variables[key] = value;
256
+ waitUntil: requestContext
257
+ ? requestContext.waitUntil.bind(requestContext)
258
+ : fireAndForgetWaitUntil,
259
+ executionContext: requestContext?.executionContext,
260
+ _variables: variables,
261
+ get: ((keyOrVar: any) => {
262
+ // Read-time guard: non-cacheable var inside cache() → throw.
263
+ // Works for both ContextVar tokens and string keys.
264
+ if (isNonCacheable(variables, keyOrVar) && isInsideCacheScope()) {
265
+ throw new Error(
266
+ `ctx.get() for a non-cacheable variable cannot be called inside a cache() boundary. ` +
267
+ `The variable was created with { cache: false } or set with { cache: false }, ` +
268
+ `and its value would be stale on cache hit. Move the read outside the cached scope.`,
269
+ );
270
+ }
271
+ return contextGet(variables, keyOrVar);
272
+ }) as HandlerContext<any, TEnv>["get"],
273
+ set: ((keyOrVar: any, value: any, options?: ContextSetOptions) => {
274
+ assertNotInsideCacheExec(ctx, "set");
275
+ // Write is dumb: store value + non-cacheable metadata.
276
+ // Enforcement happens at read time via ctx.get().
277
+ contextSet(variables, keyOrVar, value, options);
116
278
  }) as HandlerContext<any, TEnv>["set"],
117
- _originalRequest: request, // Raw request for advanced use
118
279
  res: stubResponse, // Stub response for setting headers
119
- headers: stubResponse.headers, // Shorthand for res.headers
280
+ headers: guardedHeaders, // Guarded shorthand for res.headers
120
281
  // Placeholder use() - will be replaced with actual implementation during request
121
282
  use: () => {
122
283
  throw new Error("ctx.use() called before loaders were initialized");
@@ -124,73 +285,55 @@ export function createHandlerContext<TEnv>(
124
285
  // Theme support (when enabled via router config)
125
286
  theme: requestContext?.theme,
126
287
  setTheme: requestContext?.setTheme,
127
- // Scoped reverse for URL generation
128
- reverse: (name: string, hrefParams?: Record<string, string>, search?: Record<string, unknown>) => {
129
- // Path-based - return directly (optionally with param substitution)
130
- if (name.startsWith("/")) {
131
- let result = name;
132
- if (hrefParams) {
133
- result = result.replace(/:([^/]+)/g, (_, key) => {
134
- const value = hrefParams[key];
135
- if (value === undefined) {
136
- throw new Error(`Missing param "${key}" for path "${name}"`);
137
- }
138
- return encodeURIComponent(value);
139
- });
140
- }
141
- if (search) {
142
- const qs = serializeSearchParams(search);
143
- if (qs) result += `?${qs}`;
144
- }
145
- return result;
146
- }
147
-
148
- // Resolve route name with namespace support
149
- const pattern = resolveRouteName(name, routeMap, routeName);
150
-
151
- if (pattern === undefined) {
288
+ // Location state support (delegates to request context)
289
+ setLocationState(entries) {
290
+ if (!requestContext) {
152
291
  throw new Error(
153
- `Unknown route: "${name}"${routeName ? ` (current route: ${routeName})` : ""}`
292
+ "setLocationState() is not available outside a request context",
154
293
  );
155
294
  }
156
-
157
- let result = pattern;
158
-
159
- // Substitute params
160
- if (hrefParams) {
161
- result = result.replace(/:([^/]+)/g, (_, key) => {
162
- const value = hrefParams[key];
163
- if (value === undefined) {
164
- throw new Error(`Missing param "${key}" for route "${name}"`);
165
- }
166
- return encodeURIComponent(value);
167
- });
168
- }
169
-
170
- // Append search params as query string
171
- if (search) {
172
- const qs = serializeSearchParams(search);
173
- if (qs) result += `?${qs}`;
174
- }
175
-
176
- return result;
295
+ requestContext.setLocationState(entries);
177
296
  },
297
+ routeName: (routeName && !isAutoGeneratedRouteName(routeName)
298
+ ? routeName
299
+ : undefined) as HandlerContext["routeName"],
300
+ // Scoped reverse for URL generation (auto-fills current request params).
301
+ // Resolve rootScoped eagerly so the reverse function is self-contained
302
+ // and does not depend on the global rootScopeRoutes registry at call time.
303
+ reverse: createReverseFunction(
304
+ routeMap,
305
+ routeName,
306
+ params,
307
+ routeName ? isRouteRootScoped(routeName) : undefined,
308
+ ),
309
+ passthrough: createPrerenderPassthroughFn(false, isPassthroughRoute),
310
+ _responseType: responseType,
311
+ _routeName: routeName,
178
312
  };
313
+ // Brand with taint symbol so "use cache" excludes ctx from cache keys
314
+ (ctx as any)[NOCACHE_SYMBOL] = true;
315
+ return ctx;
179
316
  }
180
317
 
181
318
  /**
182
- * Create a BuildContext for pre-rendering.
319
+ * Create a PrerenderContext for Prerender() handlers at build time.
183
320
  *
184
- * Returns a HandlerContext-compatible object where params, pathname, url,
185
- * and use(handle) work, but request/env/headers/cookies/var/searchParams
186
- * throw with a clear error. Loaders are not available during pre-rendering.
321
+ * Returns an InternalHandlerContext where params, pathname, url, searchParams,
322
+ * search, reverse, and use(handle) work. Request-time properties
323
+ * (request, env, headers, cookies, get, set, res) throw with a clear error.
187
324
  */
188
- export function createBuildContext<TEnv>(
325
+ export function createPrerenderContext<TEnv>(
189
326
  params: Record<string, string>,
190
327
  pathname: string,
191
- handleStore: HandleStore,
328
+ routeMap: Record<string, string>,
329
+ routeName?: string,
330
+ buildVars?: Record<string, any>,
331
+ isPassthroughRoute?: boolean,
332
+ buildEnv?: TEnv,
333
+ devMode?: boolean,
192
334
  ): InternalHandlerContext<any, TEnv> {
193
335
  const syntheticUrl = new URL(`http://prerender${pathname}`);
336
+ const variables = buildVars ?? {};
194
337
 
195
338
  function throwUnavailable(prop: string): never {
196
339
  throw new Error(
@@ -201,29 +344,128 @@ export function createBuildContext<TEnv>(
201
344
 
202
345
  return {
203
346
  params,
347
+ build: true,
348
+ dev: devMode ?? false,
204
349
  get request(): Request {
205
350
  return throwUnavailable("request");
206
351
  },
207
- get searchParams(): URLSearchParams {
208
- return throwUnavailable("searchParams");
209
- },
352
+ searchParams: syntheticUrl.searchParams,
353
+ search: {},
210
354
  pathname,
211
355
  url: syntheticUrl,
356
+ originalUrl: syntheticUrl,
212
357
  get env(): TEnv {
213
- return throwUnavailable("env");
358
+ if (buildEnv !== undefined) return buildEnv;
359
+ throw new Error(
360
+ "ctx.env is not available during pre-rendering. " +
361
+ "Configure buildEnv in your rango() plugin options to enable build-time env access.",
362
+ );
214
363
  },
215
- get var(): any {
216
- return throwUnavailable("var");
217
- },
218
- get: (() => {
219
- throwUnavailable("get");
220
- }) as any,
221
- set: (() => {
222
- throwUnavailable("set");
364
+ // Build-time prerender has no live request. waitUntil is a true no-op
365
+ // (running fn() here would fire side effects during build, which is
366
+ // incorrect — these are meant to outlive the live response).
367
+ // executionContext is absent for the same reason.
368
+ waitUntil: () => {},
369
+ executionContext: undefined,
370
+ _variables: variables,
371
+ get: ((keyOrVar: any) => contextGet(variables, keyOrVar)) as any,
372
+ set: ((keyOrVar: any, value: any) => {
373
+ contextSet(variables, keyOrVar, value);
223
374
  }) as any,
224
- get _originalRequest(): Request {
375
+ get res(): Response {
376
+ return throwUnavailable("res");
377
+ },
378
+ get headers(): Headers {
379
+ return throwUnavailable("headers");
380
+ },
381
+ // Placeholder use() - replaced by setupBuildUse
382
+ use: () => {
383
+ throw new Error("ctx.use() called before build context was initialized");
384
+ },
385
+ theme: undefined,
386
+ setTheme: undefined,
387
+ routeName: (routeName && !isAutoGeneratedRouteName(routeName)
388
+ ? routeName
389
+ : undefined) as HandlerContext["routeName"],
390
+ setLocationState: () => {
391
+ throwUnavailable("setLocationState");
392
+ },
393
+ reverse: createReverseFunction(
394
+ routeMap,
395
+ routeName,
396
+ params,
397
+ routeName ? isRouteRootScoped(routeName) : undefined,
398
+ ),
399
+ passthrough: createPrerenderPassthroughFn(
400
+ true,
401
+ isPassthroughRoute === true,
402
+ ),
403
+ _routeName: routeName,
404
+ } as InternalHandlerContext<any, TEnv>;
405
+ }
406
+
407
+ /**
408
+ * Create a StaticContext for Static() handlers at build time.
409
+ *
410
+ * Returns an InternalHandlerContext where only reverse and use(handle) work.
411
+ * Static handlers have no URL, no params, no pathname — everything else throws.
412
+ */
413
+ export function createStaticContext<TEnv>(
414
+ routeMap: Record<string, string>,
415
+ routeName?: string,
416
+ buildEnv?: TEnv,
417
+ devMode?: boolean,
418
+ ): InternalHandlerContext<any, TEnv> {
419
+ const variables: Record<string, any> = {};
420
+
421
+ function throwUnavailable(prop: string): never {
422
+ throw new Error(
423
+ `Property "${prop}" is not available in Static() handlers. ` +
424
+ `Static handlers render content without request context.`,
425
+ );
426
+ }
427
+
428
+ return {
429
+ get params(): any {
430
+ return throwUnavailable("params");
431
+ },
432
+ build: true,
433
+ dev: devMode ?? false,
434
+ get request(): Request {
225
435
  return throwUnavailable("request");
226
436
  },
437
+ get searchParams(): URLSearchParams {
438
+ return throwUnavailable("searchParams");
439
+ },
440
+ get search(): any {
441
+ return throwUnavailable("search");
442
+ },
443
+ get pathname(): string {
444
+ return throwUnavailable("pathname");
445
+ },
446
+ get url(): URL {
447
+ return throwUnavailable("url");
448
+ },
449
+ get originalUrl(): URL {
450
+ return throwUnavailable("originalUrl");
451
+ },
452
+ get env(): TEnv {
453
+ if (buildEnv !== undefined) return buildEnv;
454
+ throw new Error(
455
+ "ctx.env is not available in Static() handlers. " +
456
+ "Configure buildEnv in your rango() plugin options to enable build-time env access.",
457
+ );
458
+ },
459
+ // Static() handlers have no live request. waitUntil is a true no-op
460
+ // (running fn() here would fire side effects during build, which is
461
+ // incorrect). executionContext is absent for the same reason.
462
+ waitUntil: () => {},
463
+ executionContext: undefined,
464
+ _variables: variables,
465
+ get: ((keyOrVar: any) => contextGet(variables, keyOrVar)) as any,
466
+ set: ((keyOrVar: any, value: any) => {
467
+ contextSet(variables, keyOrVar, value);
468
+ }) as any,
227
469
  get res(): Response {
228
470
  return throwUnavailable("res");
229
471
  },
@@ -236,8 +478,18 @@ export function createBuildContext<TEnv>(
236
478
  },
237
479
  theme: undefined,
238
480
  setTheme: undefined,
239
- reverse: () => {
240
- throwUnavailable("reverse");
481
+ routeName: (routeName && !isAutoGeneratedRouteName(routeName)
482
+ ? routeName
483
+ : undefined) as HandlerContext["routeName"],
484
+ setLocationState: () => {
485
+ throwUnavailable("setLocationState");
241
486
  },
487
+ reverse: createReverseFunction(
488
+ routeMap,
489
+ routeName,
490
+ undefined,
491
+ routeName ? isRouteRootScoped(routeName) : undefined,
492
+ ),
493
+ _routeName: routeName,
242
494
  } as InternalHandlerContext<any, TEnv>;
243
495
  }