@rangojs/router 0.0.0-experimental.eb0645d3 → 0.0.0-experimental.f1468e3c

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 (392) hide show
  1. package/AGENTS.md +8 -0
  2. package/README.md +126 -16
  3. package/dist/bin/rango.js +319 -95
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +2724 -1053
  6. package/package.json +68 -14
  7. package/skills/api-client/SKILL.md +211 -0
  8. package/skills/breadcrumbs/SKILL.md +64 -2
  9. package/skills/bundle-analysis/SKILL.md +159 -0
  10. package/skills/cache-guide/SKILL.md +224 -32
  11. package/skills/caching/SKILL.md +279 -17
  12. package/skills/composability/SKILL.md +27 -3
  13. package/skills/css/SKILL.md +76 -0
  14. package/skills/debug-manifest/SKILL.md +4 -2
  15. package/skills/document-cache/SKILL.md +78 -55
  16. package/skills/handler-use/SKILL.md +11 -9
  17. package/skills/hooks/SKILL.md +243 -29
  18. package/skills/host-router/SKILL.md +83 -23
  19. package/skills/i18n/SKILL.md +276 -0
  20. package/skills/intercept/SKILL.md +68 -19
  21. package/skills/layout/SKILL.md +13 -9
  22. package/skills/links/SKILL.md +190 -23
  23. package/skills/loader/SKILL.md +235 -9
  24. package/skills/middleware/SKILL.md +18 -10
  25. package/skills/migrate-nextjs/SKILL.md +43 -19
  26. package/skills/migrate-react-router/SKILL.md +8 -2
  27. package/skills/mime-routes/SKILL.md +28 -1
  28. package/skills/observability/SKILL.md +172 -0
  29. package/skills/parallel/SKILL.md +18 -7
  30. package/skills/prerender/SKILL.md +65 -60
  31. package/skills/rango/SKILL.md +251 -24
  32. package/skills/react-compiler/SKILL.md +168 -0
  33. package/skills/response-routes/SKILL.md +115 -48
  34. package/skills/route/SKILL.md +46 -5
  35. package/skills/router-setup/SKILL.md +30 -8
  36. package/skills/scripts/SKILL.md +179 -0
  37. package/skills/server-actions/SKILL.md +775 -0
  38. package/skills/tailwind/SKILL.md +27 -3
  39. package/skills/testing/SKILL.md +130 -0
  40. package/skills/testing/bindings.md +103 -0
  41. package/skills/testing/cache-prerender.md +127 -0
  42. package/skills/testing/client-components.md +124 -0
  43. package/skills/testing/e2e-parity.md +125 -0
  44. package/skills/testing/flight.md +91 -0
  45. package/skills/testing/handles.md +129 -0
  46. package/skills/testing/loader.md +128 -0
  47. package/skills/testing/middleware.md +99 -0
  48. package/skills/testing/render-handler.md +122 -0
  49. package/skills/testing/response-routes.md +95 -0
  50. package/skills/testing/reverse-and-types.md +84 -0
  51. package/skills/testing/server-actions.md +107 -0
  52. package/skills/testing/server-tree.md +128 -0
  53. package/skills/testing/setup.md +123 -0
  54. package/skills/typesafety/SKILL.md +322 -29
  55. package/skills/use-cache/SKILL.md +57 -14
  56. package/skills/view-transitions/SKILL.md +337 -0
  57. package/src/__augment-tests__/augment.ts +81 -0
  58. package/src/__augment-tests__/augmented.check.ts +116 -0
  59. package/src/__internal.ts +0 -65
  60. package/src/browser/action-coordinator.ts +53 -36
  61. package/src/browser/action-fence.ts +47 -0
  62. package/src/browser/app-shell.ts +39 -0
  63. package/src/browser/connection-warmup.ts +134 -0
  64. package/src/browser/cookie-name.ts +140 -0
  65. package/src/browser/event-controller.ts +192 -150
  66. package/src/browser/history-state.ts +21 -0
  67. package/src/browser/index.ts +3 -3
  68. package/src/browser/invalidate-client-cache.ts +52 -0
  69. package/src/browser/navigation-bridge.ts +94 -25
  70. package/src/browser/navigation-client.ts +121 -84
  71. package/src/browser/navigation-store-handle.ts +38 -0
  72. package/src/browser/navigation-store.ts +115 -67
  73. package/src/browser/navigation-transaction.ts +9 -59
  74. package/src/browser/network-error-handler.ts +34 -7
  75. package/src/browser/partial-update.ts +147 -128
  76. package/src/browser/prefetch/cache.ts +107 -56
  77. package/src/browser/prefetch/fetch.ts +204 -34
  78. package/src/browser/prefetch/queue.ts +6 -3
  79. package/src/browser/rango-state.ts +158 -76
  80. package/src/browser/react/Link.tsx +30 -7
  81. package/src/browser/react/NavigationProvider.tsx +283 -118
  82. package/src/browser/react/ScrollRestoration.tsx +10 -6
  83. package/src/browser/react/deferred-handle-resolution.ts +75 -0
  84. package/src/browser/react/filter-segment-order.ts +66 -7
  85. package/src/browser/react/index.ts +0 -48
  86. package/src/browser/react/location-state-shared.ts +178 -8
  87. package/src/browser/react/location-state.ts +39 -14
  88. package/src/browser/react/use-action.ts +6 -15
  89. package/src/browser/react/use-handle.ts +17 -14
  90. package/src/browser/react/use-href.tsx +8 -1
  91. package/src/browser/react/use-link-status.ts +33 -8
  92. package/src/browser/react/use-navigation.ts +10 -5
  93. package/src/browser/react/use-params.ts +11 -11
  94. package/src/browser/react/use-reverse.ts +106 -0
  95. package/src/browser/react/use-router.ts +25 -3
  96. package/src/browser/react/use-search-params.ts +0 -5
  97. package/src/browser/react/use-segments.ts +11 -21
  98. package/src/browser/response-adapter.ts +99 -8
  99. package/src/browser/rsc-router.tsx +91 -24
  100. package/src/browser/scroll-restoration.ts +30 -17
  101. package/src/browser/segment-structure-assert.ts +2 -2
  102. package/src/browser/server-action-bridge.ts +214 -55
  103. package/src/browser/types.ts +80 -9
  104. package/src/browser/validate-redirect-origin.ts +43 -16
  105. package/src/build/collect-fallback-refs.ts +107 -0
  106. package/src/build/generate-manifest.ts +60 -35
  107. package/src/build/generate-route-types.ts +2 -1
  108. package/src/build/index.ts +8 -2
  109. package/src/build/prefix-tree-utils.ts +123 -0
  110. package/src/build/route-trie.ts +117 -14
  111. package/src/build/route-types/ast-route-extraction.ts +15 -8
  112. package/src/build/route-types/codegen.ts +16 -5
  113. package/src/build/route-types/include-resolution.ts +117 -23
  114. package/src/build/route-types/param-extraction.ts +6 -3
  115. package/src/build/route-types/per-module-writer.ts +22 -6
  116. package/src/build/route-types/router-processing.ts +55 -28
  117. package/src/build/route-types/scan-filter.ts +1 -1
  118. package/src/build/route-types/source-scan.ts +216 -0
  119. package/src/build/runtime-discovery.ts +9 -20
  120. package/src/cache/cache-error.ts +104 -0
  121. package/src/cache/cache-key-utils.ts +29 -13
  122. package/src/cache/cache-policy.ts +108 -34
  123. package/src/cache/cache-runtime.ts +224 -41
  124. package/src/cache/cache-scope.ts +188 -82
  125. package/src/cache/cache-tag.ts +103 -0
  126. package/src/cache/cf/cf-base64.ts +33 -0
  127. package/src/cache/cf/cf-cache-constants.ts +127 -0
  128. package/src/cache/cf/cf-cache-store.ts +1989 -378
  129. package/src/cache/cf/cf-cache-types.ts +349 -0
  130. package/src/cache/cf/cf-kv-utils.ts +46 -0
  131. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  132. package/src/cache/cf/index.ts +6 -16
  133. package/src/cache/document-cache.ts +89 -21
  134. package/src/cache/handle-snapshot.ts +70 -0
  135. package/src/cache/index.ts +10 -20
  136. package/src/cache/memory-segment-store.ts +136 -37
  137. package/src/cache/profile-registry.ts +46 -31
  138. package/src/cache/read-through-swr.ts +56 -12
  139. package/src/cache/segment-codec.ts +9 -17
  140. package/src/cache/tag-invalidation.ts +230 -0
  141. package/src/cache/types.ts +37 -100
  142. package/src/client.rsc.tsx +44 -21
  143. package/src/client.tsx +36 -61
  144. package/src/cloudflare/index.ts +11 -0
  145. package/src/cloudflare/tracing.ts +109 -0
  146. package/src/component-utils.ts +19 -0
  147. package/src/components/DefaultDocument.tsx +8 -2
  148. package/src/context-var.ts +18 -6
  149. package/src/decode-loader-results.ts +52 -0
  150. package/src/defer.ts +196 -0
  151. package/src/deps/ssr.ts +0 -1
  152. package/src/encode-kv.ts +49 -0
  153. package/src/errors.ts +30 -4
  154. package/src/escape-script.ts +52 -0
  155. package/src/handle.ts +31 -23
  156. package/src/handles/MetaTags.tsx +62 -19
  157. package/src/handles/Scripts.tsx +183 -0
  158. package/src/handles/breadcrumbs.ts +37 -8
  159. package/src/handles/is-thenable.ts +19 -0
  160. package/src/handles/meta.ts +51 -40
  161. package/src/handles/script.ts +244 -0
  162. package/src/host/cookie-handler.ts +9 -60
  163. package/src/host/errors.ts +0 -24
  164. package/src/host/index.ts +8 -2
  165. package/src/host/pattern-matcher.ts +23 -52
  166. package/src/host/router.ts +107 -99
  167. package/src/host/testing.ts +40 -27
  168. package/src/host/types.ts +37 -4
  169. package/src/host/utils.ts +1 -1
  170. package/src/href-client.ts +137 -22
  171. package/src/index.rsc.ts +96 -12
  172. package/src/index.ts +94 -14
  173. package/src/internal-debug.ts +11 -10
  174. package/src/loader-store.ts +500 -0
  175. package/src/loader.rsc.ts +20 -13
  176. package/src/loader.ts +12 -11
  177. package/src/missing-id-error.ts +68 -0
  178. package/src/outlet-context.ts +1 -1
  179. package/src/outlet-provider.tsx +1 -5
  180. package/src/prerender/param-hash.ts +16 -16
  181. package/src/prerender/store.ts +32 -37
  182. package/src/prerender.ts +61 -6
  183. package/src/redirect-origin.ts +100 -0
  184. package/src/regex-escape.ts +8 -0
  185. package/src/render-error-thrower.tsx +20 -0
  186. package/src/response-utils.ts +34 -0
  187. package/src/reverse.ts +65 -40
  188. package/src/root-error-boundary.tsx +1 -19
  189. package/src/route-content-wrapper.tsx +19 -77
  190. package/src/route-definition/dsl-helpers.ts +304 -309
  191. package/src/route-definition/helper-factories.ts +28 -140
  192. package/src/route-definition/helpers-types.ts +82 -55
  193. package/src/route-definition/index.ts +1 -2
  194. package/src/route-definition/redirect.ts +44 -11
  195. package/src/route-definition/resolve-handler-use.ts +12 -1
  196. package/src/route-definition/use-item-types.ts +29 -0
  197. package/src/route-map-builder.ts +0 -16
  198. package/src/route-types.ts +19 -46
  199. package/src/router/basename.ts +14 -0
  200. package/src/router/content-negotiation.ts +73 -25
  201. package/src/router/error-handling.ts +45 -18
  202. package/src/router/find-match.ts +44 -23
  203. package/src/router/handler-context.ts +27 -43
  204. package/src/router/instrument.ts +350 -0
  205. package/src/router/intercept-resolution.ts +39 -20
  206. package/src/router/lazy-includes.ts +10 -47
  207. package/src/router/loader-resolution.ts +155 -72
  208. package/src/router/logging.ts +0 -6
  209. package/src/router/manifest.ts +18 -29
  210. package/src/router/match-api.ts +9 -24
  211. package/src/router/match-context.ts +0 -22
  212. package/src/router/match-handlers.ts +58 -58
  213. package/src/router/match-middleware/background-revalidation.ts +40 -24
  214. package/src/router/match-middleware/cache-lookup.ts +159 -285
  215. package/src/router/match-middleware/cache-store.ts +64 -52
  216. package/src/router/match-middleware/intercept-resolution.ts +0 -22
  217. package/src/router/match-middleware/segment-resolution.ts +0 -22
  218. package/src/router/match-pipelines.ts +1 -42
  219. package/src/router/match-result.ts +44 -74
  220. package/src/router/metrics.ts +0 -34
  221. package/src/router/middleware-types.ts +7 -134
  222. package/src/router/middleware.ts +247 -166
  223. package/src/router/navigation-snapshot.ts +0 -51
  224. package/src/router/params-util.ts +23 -0
  225. package/src/router/pattern-matching.ts +85 -94
  226. package/src/router/prefetch-cache-ttl.ts +51 -0
  227. package/src/router/prerender-match.ts +104 -65
  228. package/src/router/preview-match.ts +3 -1
  229. package/src/router/request-classification.ts +28 -62
  230. package/src/router/revalidation.ts +123 -73
  231. package/src/router/route-snapshot.ts +0 -1
  232. package/src/router/router-context.ts +3 -28
  233. package/src/router/router-interfaces.ts +83 -35
  234. package/src/router/router-options.ts +136 -5
  235. package/src/router/router-registry.ts +2 -5
  236. package/src/router/segment-resolution/fresh.ts +97 -84
  237. package/src/router/segment-resolution/helpers.ts +86 -6
  238. package/src/router/segment-resolution/loader-cache.ts +76 -39
  239. package/src/router/segment-resolution/revalidation.ts +272 -320
  240. package/src/router/segment-resolution/static-store.ts +19 -5
  241. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  242. package/src/router/segment-resolution/view-transition-default.ts +56 -0
  243. package/src/router/segment-resolution.ts +5 -1
  244. package/src/router/segment-wrappers.ts +6 -5
  245. package/src/router/state-cookie-name.ts +33 -0
  246. package/src/router/substitute-pattern-params.ts +56 -0
  247. package/src/router/telemetry-otel.ts +161 -199
  248. package/src/router/telemetry.ts +96 -19
  249. package/src/router/timeout.ts +0 -20
  250. package/src/router/tracing.ts +206 -0
  251. package/src/router/trie-matching.ts +162 -64
  252. package/src/router/types.ts +9 -63
  253. package/src/router/url-params.ts +0 -5
  254. package/src/router.ts +110 -55
  255. package/src/rsc/handler-context.ts +3 -2
  256. package/src/rsc/handler.ts +264 -220
  257. package/src/rsc/helpers.ts +100 -6
  258. package/src/rsc/index.ts +2 -5
  259. package/src/rsc/json-route-result.ts +38 -0
  260. package/src/rsc/loader-fetch.ts +114 -38
  261. package/src/rsc/manifest-init.ts +28 -41
  262. package/src/rsc/origin-guard.ts +39 -25
  263. package/src/rsc/progressive-enhancement.ts +117 -11
  264. package/src/rsc/redirect-guard.ts +99 -0
  265. package/src/rsc/response-cache-serve.ts +238 -0
  266. package/src/rsc/response-error.ts +79 -12
  267. package/src/rsc/response-route-handler.ts +88 -188
  268. package/src/rsc/rsc-rendering.ts +98 -76
  269. package/src/rsc/runtime-warnings.ts +23 -10
  270. package/src/rsc/server-action.ts +281 -117
  271. package/src/rsc/ssr-setup.ts +16 -0
  272. package/src/rsc/transition-gate.ts +89 -0
  273. package/src/rsc/types.ts +23 -5
  274. package/src/runtime-env.ts +18 -0
  275. package/src/search-params.ts +35 -30
  276. package/src/segment-loader-promise.ts +31 -4
  277. package/src/segment-system.tsx +254 -143
  278. package/src/serialize.ts +243 -0
  279. package/src/server/context.ts +163 -51
  280. package/src/server/cookie-parse.ts +32 -0
  281. package/src/server/cookie-store.ts +80 -5
  282. package/src/server/handle-store.ts +21 -38
  283. package/src/server/loader-registry.ts +33 -42
  284. package/src/server/request-context.ts +287 -178
  285. package/src/ssr/index.tsx +21 -16
  286. package/src/static-handler.ts +10 -13
  287. package/src/testing/cache-status.ts +162 -0
  288. package/src/testing/collect-handle.ts +40 -0
  289. package/src/testing/dispatch.ts +701 -0
  290. package/src/testing/dom.entry.ts +22 -0
  291. package/src/testing/e2e/fixture.ts +188 -0
  292. package/src/testing/e2e/index.ts +128 -0
  293. package/src/testing/e2e/matchers.ts +35 -0
  294. package/src/testing/e2e/page-helpers.ts +272 -0
  295. package/src/testing/e2e/parity.ts +387 -0
  296. package/src/testing/e2e/server.ts +195 -0
  297. package/src/testing/flight-matchers.ts +97 -0
  298. package/src/testing/flight-normalize.ts +11 -0
  299. package/src/testing/flight-runtime.d.ts +57 -0
  300. package/src/testing/flight-tree.ts +682 -0
  301. package/src/testing/flight.entry.ts +52 -0
  302. package/src/testing/flight.ts +257 -0
  303. package/src/testing/generated-routes.ts +183 -0
  304. package/src/testing/index.ts +105 -0
  305. package/src/testing/internal/context.ts +371 -0
  306. package/src/testing/internal/flight-client-globals.ts +30 -0
  307. package/src/testing/internal/seed-vars.ts +54 -0
  308. package/src/testing/render-handler.ts +357 -0
  309. package/src/testing/render-route.tsx +581 -0
  310. package/src/testing/run-loader.ts +385 -0
  311. package/src/testing/run-middleware.ts +205 -0
  312. package/src/testing/run-transition-when.ts +164 -0
  313. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  314. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  315. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  316. package/src/testing/vitest-stubs/version.ts +5 -0
  317. package/src/testing/vitest.ts +305 -0
  318. package/src/theme/ThemeProvider.tsx +20 -58
  319. package/src/theme/ThemeScript.tsx +7 -9
  320. package/src/theme/constants.ts +52 -13
  321. package/src/theme/index.ts +0 -7
  322. package/src/theme/theme-context.ts +1 -5
  323. package/src/theme/theme-script.ts +22 -21
  324. package/src/theme/use-theme.ts +0 -3
  325. package/src/types/boundaries.ts +0 -35
  326. package/src/types/cache-types.ts +13 -4
  327. package/src/types/error-types.ts +30 -90
  328. package/src/types/global-namespace.ts +54 -41
  329. package/src/types/handler-context.ts +110 -62
  330. package/src/types/index.ts +3 -10
  331. package/src/types/loader-types.ts +11 -9
  332. package/src/types/request-scope.ts +112 -0
  333. package/src/types/route-config.ts +6 -50
  334. package/src/types/route-entry.ts +0 -6
  335. package/src/types/segments.ts +135 -14
  336. package/src/urls/include-helper.ts +9 -56
  337. package/src/urls/index.ts +1 -11
  338. package/src/urls/path-helper-types.ts +29 -12
  339. package/src/urls/path-helper.ts +17 -106
  340. package/src/urls/pattern-types.ts +36 -19
  341. package/src/urls/response-types.ts +22 -29
  342. package/src/urls/type-extraction.ts +58 -139
  343. package/src/urls/urls-function.ts +1 -19
  344. package/src/use-loader.tsx +292 -107
  345. package/src/vite/debug.ts +185 -0
  346. package/src/vite/discovery/bundle-postprocess.ts +8 -7
  347. package/src/vite/discovery/discover-routers.ts +126 -85
  348. package/src/vite/discovery/discovery-errors.ts +194 -0
  349. package/src/vite/discovery/gate-state.ts +171 -0
  350. package/src/vite/discovery/prerender-collection.ts +96 -68
  351. package/src/vite/discovery/route-types-writer.ts +40 -84
  352. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  353. package/src/vite/discovery/state.ts +44 -0
  354. package/src/vite/discovery/virtual-module-codegen.ts +14 -34
  355. package/src/vite/index.ts +2 -0
  356. package/src/vite/inject-client-debug.ts +36 -0
  357. package/src/vite/plugin-types.ts +126 -8
  358. package/src/vite/plugins/cjs-to-esm.ts +16 -19
  359. package/src/vite/plugins/client-ref-dedup.ts +16 -11
  360. package/src/vite/plugins/client-ref-hashing.ts +28 -15
  361. package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -21
  362. package/src/vite/plugins/expose-action-id.ts +48 -95
  363. package/src/vite/plugins/expose-id-utils.ts +88 -55
  364. package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
  365. package/src/vite/plugins/expose-ids/handler-transform.ts +11 -90
  366. package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
  367. package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
  368. package/src/vite/plugins/expose-internal-ids.ts +505 -486
  369. package/src/vite/plugins/performance-tracks.ts +26 -25
  370. package/src/vite/plugins/refresh-cmd.ts +1 -1
  371. package/src/vite/plugins/use-cache-transform.ts +73 -83
  372. package/src/vite/plugins/version-injector.ts +40 -29
  373. package/src/vite/plugins/version-plugin.ts +37 -40
  374. package/src/vite/plugins/virtual-entries.ts +39 -25
  375. package/src/vite/rango.ts +109 -118
  376. package/src/vite/router-discovery.ts +718 -119
  377. package/src/vite/utils/ast-handler-extract.ts +26 -35
  378. package/src/vite/utils/banner.ts +1 -1
  379. package/src/vite/utils/bundle-analysis.ts +10 -15
  380. package/src/vite/utils/client-chunks.ts +184 -0
  381. package/src/vite/utils/directive-prologue.ts +40 -0
  382. package/src/vite/utils/forward-user-plugins.ts +171 -0
  383. package/src/vite/utils/manifest-utils.ts +4 -59
  384. package/src/vite/utils/package-resolution.ts +20 -52
  385. package/src/vite/utils/prerender-utils.ts +54 -39
  386. package/src/vite/utils/shared-utils.ts +90 -41
  387. package/src/browser/action-response-classifier.ts +0 -99
  388. package/src/browser/react/use-client-cache.ts +0 -58
  389. package/src/browser/shallow.ts +0 -40
  390. package/src/handles/index.ts +0 -7
  391. package/src/network-error-thrower.tsx +0 -23
  392. package/src/router/middleware-cookies.ts +0 -55
@@ -1,10 +1,3 @@
1
- /**
2
- * Match API
3
- *
4
- * Extracted from createRouter closure. Contains match context creation functions
5
- * and the matchError function for error boundary resolution.
6
- */
7
-
8
1
  import { CacheScope, createCacheScope } from "../cache/cache-scope.js";
9
2
  import { RouteNotFoundError } from "../errors";
10
3
  import {
@@ -22,10 +15,10 @@ import { collectRouteMiddleware } from "./middleware.js";
22
15
  import { traverseBack } from "./pattern-matching.js";
23
16
  import { DefaultErrorFallback } from "../default-error-boundary.js";
24
17
  import {
25
- EntryData,
26
- LoaderEntry,
18
+ type EntryData,
19
+ type LoaderEntry,
27
20
  getContext,
28
- InterceptSelectorContext,
21
+ type InterceptSelectorContext,
29
22
  } from "../server/context";
30
23
  import type { ErrorBoundaryHandler, ErrorInfo, MatchResult } from "../types";
31
24
  import type { ReactNode } from "react";
@@ -59,8 +52,6 @@ export async function createMatchContextForFull<TEnv>(
59
52
 
60
53
  const metricsStore = deps.getMetricsStore();
61
54
 
62
- // Full renders always resolve fresh with isSSR: true because loadManifest
63
- // keys its cache on isSSR and stamps Store.isSSR for downstream behavior.
64
55
  const result = await resolveRoute<TEnv>(pathname, {
65
56
  findMatch: (p) => deps.findMatch(p, metricsStore),
66
57
  metricsStore,
@@ -84,12 +75,10 @@ export async function createMatchContextForFull<TEnv>(
84
75
 
85
76
  const { matched } = snapshot;
86
77
 
87
- // Backward compat: downstream middleware reads matched.pt
88
78
  if (snapshot.isPassthrough) {
89
79
  matched.pt = true;
90
80
  }
91
81
 
92
- // Clean URL without internal _rsc* params for userland access
93
82
  const cleanUrl = stripInternalParams(url);
94
83
 
95
84
  const handlerContext = createHandlerContext(
@@ -231,7 +220,6 @@ export async function createMatchContextForPartial<TEnv>(
231
220
  matched.pt = true;
232
221
  }
233
222
 
234
- // Navigation state (prev + intercept-source findMatch calls)
235
223
  const nav = resolveNavigation(request, url, matched.routeKey, {
236
224
  findMatch: deps.findMatch,
237
225
  });
@@ -239,10 +227,6 @@ export async function createMatchContextForPartial<TEnv>(
239
227
  return null;
240
228
  }
241
229
 
242
- // Push route-matching metric. On the fresh path this covers all findMatch
243
- // calls (current + prev + intercept-source). On the reuse path, current-route
244
- // findMatch was already timed during classification, so this only covers
245
- // the nav lookups (prev + intercept-source).
246
230
  if (metricsStore) {
247
231
  const isReuse = !!classifiedRoute;
248
232
  metricsStore.metrics.push({
@@ -259,7 +243,6 @@ export async function createMatchContextForPartial<TEnv>(
259
243
  });
260
244
  }
261
245
 
262
- // Clean URL without internal _rsc* params for userland access
263
246
  const cleanUrl = stripInternalParams(url);
264
247
 
265
248
  const handlerContext = createHandlerContext(
@@ -304,10 +287,11 @@ export async function createMatchContextForPartial<TEnv>(
304
287
  });
305
288
  }
306
289
 
307
- // Store previous route key on the request context for revalidation
308
- // fromRouteName. Uses effectiveFromMatch so intercept-source navigations
309
- // see the intercept origin route, not the plain previous URL route.
310
- setRequestContextPrevRouteKey(nav.effectiveFromMatch?.routeKey);
290
+ setRequestContextPrevRouteKey(
291
+ nav.effectiveFromMatch?.routeKey,
292
+ nav.effectiveFromUrl,
293
+ nav.effectiveFromMatch?.params ?? nav.prevParams,
294
+ );
311
295
 
312
296
  const interceptSelectorContext: InterceptSelectorContext = {
313
297
  from: nav.effectiveFromUrl,
@@ -550,6 +534,7 @@ export async function matchError<TEnv>(
550
534
  segments: [errorSegment],
551
535
  matched: matchedIds,
552
536
  diff: [errorSegment.id],
537
+ resolvedIds: [errorSegment.id],
553
538
  params: matched.params,
554
539
  };
555
540
  }
@@ -242,25 +242,3 @@ export function createPipelineState(): MatchPipelineState {
242
242
  slots: {},
243
243
  };
244
244
  }
245
-
246
- /**
247
- * Input parameters for createMatchContext
248
- */
249
- export interface CreateMatchContextInput<TEnv = any> {
250
- request: Request;
251
- env: TEnv;
252
- actionContext?: ActionContext;
253
- }
254
-
255
- /**
256
- * Result from createMatchContext - either a context or null (fall back to full match)
257
- */
258
- export type CreateMatchContextResult<TEnv = any> =
259
- | { type: "context"; ctx: MatchContext<TEnv> }
260
- | { type: "fallback"; reason: string }
261
- | { type: "error"; error: Error };
262
-
263
- // Note: createMatchContext() will be implemented in Step J10 when we wire everything together.
264
- // It requires access to RouterContext (findMatch, loadManifest, etc.) which are closure
265
- // functions from createRouter(). The implementation will live in router.ts initially
266
- // and call getRouterContext() to access these dependencies.
@@ -33,10 +33,13 @@ import type { ErrorBoundaryHandler, NotFoundBoundaryHandler } from "../types";
33
33
  import type { MiddlewareFn } from "./middleware.js";
34
34
  import {
35
35
  type TelemetrySink,
36
+ type CacheSegmentSignal,
36
37
  safeEmit,
37
38
  resolveSink,
38
39
  getRequestId,
40
+ buildCacheSignalSegments,
39
41
  } from "./telemetry.js";
42
+ import { _getRequestContext } from "../server/request-context.js";
40
43
 
41
44
  export interface MatchHandlerDeps<TEnv = any> {
42
45
  buildRouterContext: () => RouterContext<TEnv>;
@@ -51,6 +54,12 @@ export interface MatchHandlerDeps<TEnv = any> {
51
54
  isAction: boolean,
52
55
  ) => { intercept: InterceptEntry; entry: EntryData } | null;
53
56
  telemetry?: TelemetrySink;
57
+ /**
58
+ * DEVELOPMENT/TEST ONLY gate for the X-Rango-Cache debug header. When true,
59
+ * match/matchPartial stash a coarse route-level cache signal on the request
60
+ * context for the response-finalization path to emit. Default off.
61
+ */
62
+ cacheSignalEnabled?: boolean;
54
63
  }
55
64
 
56
65
  export interface MatchHandlers<TEnv = any> {
@@ -80,20 +89,6 @@ export interface MatchHandlers<TEnv = any> {
80
89
  negotiated?: boolean;
81
90
  manifestEntry?: EntryData;
82
91
  } | null>;
83
- createMatchContextForFull: (
84
- request: Request,
85
- env: TEnv,
86
- ) => Promise<MatchContext<TEnv> | { type: "redirect"; redirectUrl: string }>;
87
- createMatchContextForPartial: (
88
- request: Request,
89
- env: TEnv,
90
- actionContext?: {
91
- actionId?: string;
92
- actionUrl?: URL;
93
- actionResult?: any;
94
- formData?: FormData;
95
- },
96
- ) => Promise<MatchContext<TEnv> | null>;
97
92
  }
98
93
 
99
94
  /**
@@ -113,6 +108,20 @@ export function createMatchHandlers<TEnv = any>(
113
108
  } = deps;
114
109
  const hasTelemetry = !!deps.telemetry;
115
110
  const telemetry = resolveSink(deps.telemetry);
111
+ const cacheSignalEnabled = !!deps.cacheSignalEnabled;
112
+ const buildSignal = (
113
+ routeKey: string,
114
+ state: {
115
+ cacheHit: boolean;
116
+ cacheSource?: "runtime" | "prerender";
117
+ shouldRevalidate?: boolean;
118
+ },
119
+ ): CacheSegmentSignal[] => buildCacheSignalSegments(routeKey, state);
120
+ const recordSignalIfEnabled = (segments: CacheSegmentSignal[]): void => {
121
+ if (!cacheSignalEnabled) return;
122
+ const reqCtx = _getRequestContext();
123
+ if (reqCtx) reqCtx._cacheSignal = segments;
124
+ };
116
125
 
117
126
  async function createMatchContextForFull(
118
127
  request: Request,
@@ -145,15 +154,6 @@ export function createMatchHandlers<TEnv = any>(
145
154
  );
146
155
  }
147
156
 
148
- /**
149
- * Match request and return segments (document/SSR requests)
150
- *
151
- * Uses generator middleware pipeline for clean separation of concerns:
152
- * - cache-lookup: Check cache first
153
- * - segment-resolution: Resolve segments on cache miss
154
- * - cache-store: Store results in cache
155
- * - background-revalidation: SWR revalidation
156
- */
157
157
  async function match(request: Request, env: TEnv): Promise<MatchResult> {
158
158
  const requestId = hasTelemetry ? getRequestId(request) : undefined;
159
159
  return runWithRouterLogContext({ request, transaction: "match" }, () => {
@@ -177,7 +177,6 @@ export function createMatchHandlers<TEnv = any>(
177
177
 
178
178
  const result = await createMatchContextForFull(request, env);
179
179
 
180
- // Handle redirect case
181
180
  if ("type" in result && result.type === "redirect") {
182
181
  if (hasTelemetry) {
183
182
  safeEmit(telemetry, {
@@ -196,6 +195,7 @@ export function createMatchHandlers<TEnv = any>(
196
195
  segments: [],
197
196
  matched: [],
198
197
  diff: [],
198
+ resolvedIds: [],
199
199
  params: {},
200
200
  redirect: result.redirectUrl,
201
201
  };
@@ -207,17 +207,24 @@ export function createMatchHandlers<TEnv = any>(
207
207
  const state = createPipelineState();
208
208
  const pipeline = createMatchPartialPipeline(ctx, state);
209
209
  const matchResult = await collectMatchResult(pipeline, ctx, state);
210
+ if (hasTelemetry || cacheSignalEnabled) {
211
+ const signalSegments = buildSignal(ctx.routeKey, state);
212
+ recordSignalIfEnabled(signalSegments);
213
+ if (hasTelemetry) {
214
+ safeEmit(telemetry, {
215
+ type: "cache.decision",
216
+ timestamp: performance.now(),
217
+ requestId,
218
+ pathname,
219
+ routeKey: ctx.routeKey,
220
+ hit: state.cacheHit,
221
+ shouldRevalidate: !!state.shouldRevalidate,
222
+ source: state.cacheSource,
223
+ segments: signalSegments,
224
+ });
225
+ }
226
+ }
210
227
  if (hasTelemetry) {
211
- safeEmit(telemetry, {
212
- type: "cache.decision",
213
- timestamp: performance.now(),
214
- requestId,
215
- pathname,
216
- routeKey: ctx.routeKey,
217
- hit: state.cacheHit,
218
- shouldRevalidate: !!state.shouldRevalidate,
219
- source: state.cacheSource,
220
- });
221
228
  safeEmit(telemetry, {
222
229
  type: "request.end",
223
230
  timestamp: performance.now(),
@@ -248,7 +255,6 @@ export function createMatchHandlers<TEnv = any>(
248
255
  });
249
256
  }
250
257
  if (error instanceof Response) throw error;
251
- // Report unhandled errors during full match pipeline
252
258
  callOnError(error, "routing", {
253
259
  request,
254
260
  url: ctx.url,
@@ -283,16 +289,6 @@ export function createMatchHandlers<TEnv = any>(
283
289
  );
284
290
  }
285
291
 
286
- /**
287
- * Match partial request with revalidation
288
- *
289
- * Uses generator middleware pipeline for clean separation of concerns:
290
- * - cache-lookup: Check cache first
291
- * - segment-resolution: Resolve segments on cache miss
292
- * - intercept-resolution: Handle intercept routes
293
- * - cache-store: Store results in cache
294
- * - background-revalidation: SWR revalidation
295
- */
296
292
  async function matchPartial(
297
293
  request: Request,
298
294
  context: TEnv,
@@ -362,17 +358,24 @@ export function createMatchHandlers<TEnv = any>(
362
358
  state,
363
359
  );
364
360
  flushRevalidationTrace();
361
+ if (hasTelemetry || cacheSignalEnabled) {
362
+ const signalSegments = buildSignal(ctx.routeKey, state);
363
+ recordSignalIfEnabled(signalSegments);
364
+ if (hasTelemetry) {
365
+ safeEmit(telemetry, {
366
+ type: "cache.decision",
367
+ timestamp: performance.now(),
368
+ requestId: partialRequestId,
369
+ pathname,
370
+ routeKey: ctx.routeKey,
371
+ hit: state.cacheHit,
372
+ shouldRevalidate: !!state.shouldRevalidate,
373
+ source: state.cacheSource,
374
+ segments: signalSegments,
375
+ });
376
+ }
377
+ }
365
378
  if (hasTelemetry) {
366
- safeEmit(telemetry, {
367
- type: "cache.decision",
368
- timestamp: performance.now(),
369
- requestId: partialRequestId,
370
- pathname,
371
- routeKey: ctx.routeKey,
372
- hit: state.cacheHit,
373
- shouldRevalidate: !!state.shouldRevalidate,
374
- source: state.cacheSource,
375
- });
376
379
  safeEmit(telemetry, {
377
380
  type: "request.end",
378
381
  timestamp: performance.now(),
@@ -405,7 +408,6 @@ export function createMatchHandlers<TEnv = any>(
405
408
  });
406
409
  }
407
410
  if (error instanceof Response) throw error;
408
- // Report unhandled errors during partial match pipeline
409
411
  callOnError(error, actionContext ? "action" : "revalidation", {
410
412
  request,
411
413
  url: ctx.url,
@@ -434,7 +436,5 @@ export function createMatchHandlers<TEnv = any>(
434
436
  matchPartial: matchPartial,
435
437
  matchError: matchError,
436
438
  previewMatch: previewMatch,
437
- createMatchContextForFull: createMatchContextForFull,
438
- createMatchContextForPartial: createMatchContextForPartial,
439
439
  };
440
440
  }
@@ -105,6 +105,10 @@ import { getRouterContext } from "../router-context.js";
105
105
  import type { GeneratorMiddleware } from "./cache-lookup.js";
106
106
  import { debugLog, debugWarn, getOrCreateRequestId } from "../logging.js";
107
107
  import { INTERNAL_RANGO_DEBUG } from "../../internal-debug.js";
108
+ import {
109
+ runWithRequestContext,
110
+ type RequestContext,
111
+ } from "../../server/request-context.js";
108
112
 
109
113
  /**
110
114
  * Creates background revalidation middleware
@@ -168,8 +172,6 @@ export function withBackgroundRevalidation<TEnv>(
168
172
  requestCtx._handleStore = createHandleStore();
169
173
 
170
174
  try {
171
- // Create fresh handler context and loader promises to avoid
172
- // reusing memoized results from the foreground pass
173
175
  const freshHandlerContext = createHandlerContext(
174
176
  ctx.matched.params,
175
177
  ctx.request,
@@ -185,32 +187,46 @@ export function withBackgroundRevalidation<TEnv>(
185
187
  const freshLoaderPromises = new Map<string, Promise<any>>();
186
188
  setupLoaderAccess(freshHandlerContext, freshLoaderPromises);
187
189
 
188
- // Resolve all segments fresh (without revalidation logic)
189
- // to ensure complete components for caching.
190
- // Skip DSL loaders they are never cached (cacheRoute filters them)
191
- // and are always resolved fresh on each request.
192
- const freshSegments = await ctx.Store.run(() =>
193
- resolveAllSegments(
194
- ctx.entries,
195
- ctx.routeKey,
196
- ctx.matched.params,
197
- freshHandlerContext,
198
- freshLoaderPromises,
199
- { skipLoaders: true },
200
- ),
190
+ // Re-establish the request-context ALS around the re-render. ctx.Store
191
+ // is a different ALS (DSL build context); on workerd a waitUntil task
192
+ // runs detached from the request's I/O context, so a handler/component
193
+ // that reads the ambient getRequestContext() during this background
194
+ // re-render would otherwise throw "called outside of a request context".
195
+ const freshSegments = await runWithRequestContext(
196
+ requestCtx as RequestContext<TEnv>,
197
+ () =>
198
+ ctx.Store.run(() =>
199
+ resolveAllSegments(
200
+ ctx.entries,
201
+ ctx.routeKey,
202
+ ctx.matched.params,
203
+ freshHandlerContext,
204
+ freshLoaderPromises,
205
+ { skipLoaders: true },
206
+ ),
207
+ ),
201
208
  );
202
209
 
203
- // Also resolve intercept segments fresh if applicable
204
210
  let freshInterceptSegments: ResolvedSegment[] = [];
205
211
  if (ctx.interceptResult) {
206
- freshInterceptSegments = await ctx.Store.run(() =>
207
- resolveInterceptEntry(
208
- ctx.interceptResult!.intercept,
209
- ctx.interceptResult!.entry,
210
- ctx.matched.params,
211
- freshHandlerContext,
212
- true,
213
- ),
212
+ freshInterceptSegments = await runWithRequestContext(
213
+ requestCtx as RequestContext<TEnv>,
214
+ () =>
215
+ ctx.Store.run(() =>
216
+ resolveInterceptEntry(
217
+ ctx.interceptResult!.intercept,
218
+ ctx.interceptResult!.entry,
219
+ ctx.matched.params,
220
+ freshHandlerContext,
221
+ true,
222
+ undefined,
223
+ // Skip intercept middleware: this is a post-response background
224
+ // re-render to refresh a stale cached route. The foreground
225
+ // already ran the middleware; re-running it would double its
226
+ // side effects and a short-circuit Response would abort the write.
227
+ { skipMiddleware: true },
228
+ ),
229
+ ),
214
230
  );
215
231
  }
216
232