@rangojs/router 0.4.0 → 0.4.1

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 (482) hide show
  1. package/README.md +19 -1
  2. package/dist/types/browser/event-controller.d.ts +4 -0
  3. package/dist/types/browser/link-interceptor.d.ts +17 -7
  4. package/dist/types/browser/navigation-bridge.d.ts +13 -1
  5. package/dist/types/browser/notify-listeners.d.ts +2 -0
  6. package/dist/types/browser/prefetch/cache.d.ts +1 -1
  7. package/dist/types/browser/prefetch/default-strategy.d.ts +12 -3
  8. package/dist/types/browser/prefetch/invalidation.d.ts +6 -0
  9. package/dist/types/browser/prefetch/loader.d.ts +3 -1
  10. package/dist/types/browser/prefetch/observer.d.ts +3 -6
  11. package/dist/types/browser/rango-state.d.ts +4 -0
  12. package/dist/types/browser/react/Link.d.ts +4 -9
  13. package/dist/types/browser/react/context.d.ts +3 -0
  14. package/dist/types/browser/rsc-router.d.ts +7 -2
  15. package/dist/types/browser/types.d.ts +1 -0
  16. package/dist/types/cache/cache-key-utils.d.ts +11 -3
  17. package/dist/types/cache/cache-scope.d.ts +82 -3
  18. package/dist/types/cache/cf/cf-cache-store.d.ts +2 -2
  19. package/dist/types/cache/index.d.ts +3 -1
  20. package/dist/types/cache/search-params-filter.d.ts +64 -0
  21. package/dist/types/cache/shell-snapshot.d.ts +4 -4
  22. package/dist/types/cache/types.d.ts +30 -2
  23. package/dist/types/cache/vercel/vercel-cache-store.d.ts +2 -2
  24. package/dist/types/index.d.ts +1 -0
  25. package/dist/types/index.rsc.d.ts +1 -0
  26. package/dist/types/router/match-middleware/cache-lookup.d.ts +13 -0
  27. package/dist/types/router/navigation-snapshot.d.ts +29 -0
  28. package/dist/types/router/router-options.d.ts +27 -3
  29. package/dist/types/rsc/shell-build-manifest.d.ts +7 -1
  30. package/dist/types/rsc/shell-serve.d.ts +7 -1
  31. package/dist/types/rsc/types.d.ts +17 -0
  32. package/dist/types/server/request-context.d.ts +57 -4
  33. package/dist/types/testing/render-route.d.ts +10 -1
  34. package/dist/types/testing/shell-status.d.ts +6 -3
  35. package/dist/types/vite/plugin-types.d.ts +1 -1
  36. package/dist/vite/index.js +5 -5
  37. package/package.json +23 -22
  38. package/skills/caching/SKILL.md +39 -0
  39. package/skills/comparison/references/framework-comparison.md +7 -1
  40. package/skills/links/SKILL.md +24 -0
  41. package/skills/ppr/SKILL.md +53 -4
  42. package/skills/router-setup/SKILL.md +7 -2
  43. package/skills/testing/client-components.md +15 -14
  44. package/skills/vercel/SKILL.md +1 -1
  45. package/src/browser/event-controller.ts +110 -11
  46. package/src/browser/link-interceptor.ts +469 -20
  47. package/src/browser/navigation-bridge.ts +71 -2
  48. package/src/browser/navigation-store.ts +24 -1
  49. package/src/browser/notify-listeners.ts +22 -0
  50. package/src/browser/prefetch/cache.ts +4 -2
  51. package/src/browser/prefetch/default-strategy.ts +43 -3
  52. package/src/browser/prefetch/invalidation.ts +30 -0
  53. package/src/browser/prefetch/loader.ts +19 -12
  54. package/src/browser/prefetch/observer.ts +50 -22
  55. package/src/browser/rango-state.ts +21 -0
  56. package/src/browser/react/Link.tsx +97 -88
  57. package/src/browser/react/NavigationProvider.tsx +1 -0
  58. package/src/browser/react/context.ts +4 -0
  59. package/src/browser/rsc-router.tsx +22 -9
  60. package/src/browser/types.ts +1 -0
  61. package/src/cache/cache-key-utils.ts +18 -4
  62. package/src/cache/cache-runtime.ts +7 -2
  63. package/src/cache/cache-scope.ts +152 -23
  64. package/src/cache/cf/cf-cache-store.ts +51 -16
  65. package/src/cache/document-cache.ts +7 -1
  66. package/src/cache/index.ts +7 -0
  67. package/src/cache/search-params-filter.ts +118 -0
  68. package/src/cache/shell-snapshot.ts +8 -4
  69. package/src/cache/types.ts +33 -2
  70. package/src/cache/vercel/vercel-cache-store.ts +17 -3
  71. package/src/index.rsc.ts +4 -0
  72. package/src/index.ts +6 -0
  73. package/src/router/match-middleware/cache-lookup.ts +146 -33
  74. package/src/router/match-middleware/cache-store.ts +70 -0
  75. package/src/router/navigation-snapshot.ts +46 -6
  76. package/src/router/router-options.ts +31 -4
  77. package/src/rsc/handler.ts +9 -0
  78. package/src/rsc/response-cache-serve.ts +1 -1
  79. package/src/rsc/rsc-rendering.ts +252 -27
  80. package/src/rsc/shell-build-manifest.ts +8 -1
  81. package/src/rsc/shell-capture.ts +5 -0
  82. package/src/rsc/shell-serve.ts +8 -2
  83. package/src/rsc/types.ts +17 -0
  84. package/src/server/request-context.ts +62 -3
  85. package/src/testing/dispatch.ts +21 -3
  86. package/src/testing/render-route.tsx +86 -17
  87. package/src/testing/shell-status.ts +20 -3
  88. package/src/vite/plugin-types.ts +1 -1
  89. package/src/vite/plugins/vercel-output.ts +2 -2
  90. package/dist/types.backup/__internal.d.ts +0 -127
  91. package/dist/types.backup/bin/rango.d.ts +0 -1
  92. package/dist/types.backup/browser/action-coordinator.d.ts +0 -57
  93. package/dist/types.backup/browser/action-fence.d.ts +0 -33
  94. package/dist/types.backup/browser/app-shell.d.ts +0 -34
  95. package/dist/types.backup/browser/app-version.d.ts +0 -6
  96. package/dist/types.backup/browser/connection-warmup.d.ts +0 -31
  97. package/dist/types.backup/browser/cookie-name.d.ts +0 -66
  98. package/dist/types.backup/browser/event-controller.d.ts +0 -221
  99. package/dist/types.backup/browser/history-state.d.ts +0 -26
  100. package/dist/types.backup/browser/index.d.ts +0 -1
  101. package/dist/types.backup/browser/intercept-utils.d.ts +0 -30
  102. package/dist/types.backup/browser/invalidate-client-cache.d.ts +0 -17
  103. package/dist/types.backup/browser/link-interceptor.d.ts +0 -43
  104. package/dist/types.backup/browser/logging.d.ts +0 -33
  105. package/dist/types.backup/browser/merge-segment-loaders.d.ts +0 -38
  106. package/dist/types.backup/browser/navigation-bridge.d.ts +0 -27
  107. package/dist/types.backup/browser/navigation-client.d.ts +0 -17
  108. package/dist/types.backup/browser/navigation-store-handle.d.ts +0 -25
  109. package/dist/types.backup/browser/navigation-store.d.ts +0 -95
  110. package/dist/types.backup/browser/navigation-transaction.d.ts +0 -75
  111. package/dist/types.backup/browser/network-error-handler.d.ts +0 -35
  112. package/dist/types.backup/browser/partial-update.d.ts +0 -61
  113. package/dist/types.backup/browser/prefetch/cache.d.ts +0 -183
  114. package/dist/types.backup/browser/prefetch/fetch.d.ts +0 -52
  115. package/dist/types.backup/browser/prefetch/observer.d.ts +0 -27
  116. package/dist/types.backup/browser/prefetch/policy.d.ts +0 -13
  117. package/dist/types.backup/browser/prefetch/queue.d.ts +0 -48
  118. package/dist/types.backup/browser/prefetch/resource-ready.d.ts +0 -28
  119. package/dist/types.backup/browser/rango-state.d.ts +0 -52
  120. package/dist/types.backup/browser/react/Link.d.ts +0 -140
  121. package/dist/types.backup/browser/react/NavigationProvider.d.ts +0 -88
  122. package/dist/types.backup/browser/react/ScrollRestoration.d.ts +0 -78
  123. package/dist/types.backup/browser/react/context.d.ts +0 -54
  124. package/dist/types.backup/browser/react/filter-segment-order.d.ts +0 -35
  125. package/dist/types.backup/browser/react/index.d.ts +0 -1
  126. package/dist/types.backup/browser/react/location-state-shared.d.ts +0 -162
  127. package/dist/types.backup/browser/react/location-state.d.ts +0 -29
  128. package/dist/types.backup/browser/react/mount-context.d.ts +0 -23
  129. package/dist/types.backup/browser/react/nonce-context.d.ts +0 -14
  130. package/dist/types.backup/browser/react/shallow-equal.d.ts +0 -5
  131. package/dist/types.backup/browser/react/use-action.d.ts +0 -61
  132. package/dist/types.backup/browser/react/use-handle.d.ts +0 -21
  133. package/dist/types.backup/browser/react/use-href.d.ts +0 -32
  134. package/dist/types.backup/browser/react/use-link-status.d.ts +0 -36
  135. package/dist/types.backup/browser/react/use-mount.d.ts +0 -24
  136. package/dist/types.backup/browser/react/use-navigation.d.ts +0 -15
  137. package/dist/types.backup/browser/react/use-params.d.ts +0 -21
  138. package/dist/types.backup/browser/react/use-pathname.d.ts +0 -13
  139. package/dist/types.backup/browser/react/use-reverse.d.ts +0 -40
  140. package/dist/types.backup/browser/react/use-router.d.ts +0 -23
  141. package/dist/types.backup/browser/react/use-search-params.d.ts +0 -19
  142. package/dist/types.backup/browser/react/use-segments.d.ts +0 -29
  143. package/dist/types.backup/browser/response-adapter.d.ts +0 -58
  144. package/dist/types.backup/browser/rsc-router.d.ts +0 -141
  145. package/dist/types.backup/browser/scroll-restoration.d.ts +0 -103
  146. package/dist/types.backup/browser/segment-reconciler.d.ts +0 -74
  147. package/dist/types.backup/browser/segment-structure-assert.d.ts +0 -16
  148. package/dist/types.backup/browser/server-action-bridge.d.ts +0 -29
  149. package/dist/types.backup/browser/types.d.ts +0 -530
  150. package/dist/types.backup/browser/validate-redirect-origin.d.ts +0 -28
  151. package/dist/types.backup/build/collect-fallback-refs.d.ts +0 -5
  152. package/dist/types.backup/build/generate-manifest.d.ts +0 -100
  153. package/dist/types.backup/build/generate-route-types.d.ts +0 -8
  154. package/dist/types.backup/build/index.d.ts +0 -21
  155. package/dist/types.backup/build/prefix-tree-utils.d.ts +0 -56
  156. package/dist/types.backup/build/route-trie.d.ts +0 -89
  157. package/dist/types.backup/build/route-types/ast-helpers.d.ts +0 -3
  158. package/dist/types.backup/build/route-types/ast-route-extraction.d.ts +0 -13
  159. package/dist/types.backup/build/route-types/codegen.d.ts +0 -16
  160. package/dist/types.backup/build/route-types/include-resolution.d.ts +0 -74
  161. package/dist/types.backup/build/route-types/param-extraction.d.ts +0 -13
  162. package/dist/types.backup/build/route-types/per-module-writer.d.ts +0 -18
  163. package/dist/types.backup/build/route-types/router-processing.d.ts +0 -82
  164. package/dist/types.backup/build/route-types/scan-filter.d.ts +0 -17
  165. package/dist/types.backup/build/route-types/source-scan.d.ts +0 -13
  166. package/dist/types.backup/build/runtime-discovery.d.ts +0 -24
  167. package/dist/types.backup/cache/background-task.d.ts +0 -21
  168. package/dist/types.backup/cache/cache-error.d.ts +0 -71
  169. package/dist/types.backup/cache/cache-key-utils.d.ts +0 -35
  170. package/dist/types.backup/cache/cache-policy.d.ts +0 -59
  171. package/dist/types.backup/cache/cache-runtime.d.ts +0 -51
  172. package/dist/types.backup/cache/cache-scope.d.ts +0 -134
  173. package/dist/types.backup/cache/cache-tag.d.ts +0 -79
  174. package/dist/types.backup/cache/cf/cf-base64.d.ts +0 -4
  175. package/dist/types.backup/cache/cf/cf-cache-constants.d.ts +0 -105
  176. package/dist/types.backup/cache/cf/cf-cache-store.d.ts +0 -481
  177. package/dist/types.backup/cache/cf/cf-cache-types.d.ts +0 -300
  178. package/dist/types.backup/cache/cf/cf-kv-utils.d.ts +0 -22
  179. package/dist/types.backup/cache/cf/cf-tag-marker-memo.d.ts +0 -15
  180. package/dist/types.backup/cache/cf/index.d.ts +0 -3
  181. package/dist/types.backup/cache/document-cache.d.ts +0 -69
  182. package/dist/types.backup/cache/handle-capture.d.ts +0 -23
  183. package/dist/types.backup/cache/handle-snapshot.d.ts +0 -39
  184. package/dist/types.backup/cache/index.d.ts +0 -7
  185. package/dist/types.backup/cache/memory-segment-store.d.ts +0 -163
  186. package/dist/types.backup/cache/profile-registry.d.ts +0 -40
  187. package/dist/types.backup/cache/read-through-swr.d.ts +0 -60
  188. package/dist/types.backup/cache/segment-codec.d.ts +0 -78
  189. package/dist/types.backup/cache/shell-snapshot.d.ts +0 -162
  190. package/dist/types.backup/cache/tag-invalidation.d.ts +0 -74
  191. package/dist/types.backup/cache/taint.d.ts +0 -71
  192. package/dist/types.backup/cache/types.d.ts +0 -407
  193. package/dist/types.backup/cache/vercel/index.d.ts +0 -1
  194. package/dist/types.backup/cache/vercel/vercel-cache-store.d.ts +0 -267
  195. package/dist/types.backup/client.d.ts +0 -184
  196. package/dist/types.backup/client.rsc.d.ts +0 -39
  197. package/dist/types.backup/cloudflare/index.d.ts +0 -7
  198. package/dist/types.backup/cloudflare/tracing.d.ts +0 -53
  199. package/dist/types.backup/component-utils.d.ts +0 -46
  200. package/dist/types.backup/components/DefaultDocument.d.ts +0 -13
  201. package/dist/types.backup/context-var.d.ts +0 -84
  202. package/dist/types.backup/debug.d.ts +0 -57
  203. package/dist/types.backup/decode-loader-results.d.ts +0 -5
  204. package/dist/types.backup/default-error-boundary.d.ts +0 -10
  205. package/dist/types.backup/defer.d.ts +0 -89
  206. package/dist/types.backup/deps/browser.d.ts +0 -1
  207. package/dist/types.backup/deps/html-stream-client.d.ts +0 -1
  208. package/dist/types.backup/deps/html-stream-server.d.ts +0 -1
  209. package/dist/types.backup/deps/rsc.d.ts +0 -1
  210. package/dist/types.backup/deps/ssr.d.ts +0 -1
  211. package/dist/types.backup/encode-kv.d.ts +0 -35
  212. package/dist/types.backup/errors.d.ts +0 -226
  213. package/dist/types.backup/escape-script.d.ts +0 -44
  214. package/dist/types.backup/handle.d.ts +0 -93
  215. package/dist/types.backup/handles/MetaTags.d.ts +0 -17
  216. package/dist/types.backup/handles/Scripts.d.ts +0 -38
  217. package/dist/types.backup/handles/breadcrumbs.d.ts +0 -43
  218. package/dist/types.backup/handles/deferred-resolution.d.ts +0 -53
  219. package/dist/types.backup/handles/is-thenable.d.ts +0 -12
  220. package/dist/types.backup/handles/meta.d.ts +0 -43
  221. package/dist/types.backup/handles/script.d.ts +0 -139
  222. package/dist/types.backup/host/cookie-handler.d.ts +0 -8
  223. package/dist/types.backup/host/errors.d.ts +0 -40
  224. package/dist/types.backup/host/index.d.ts +0 -33
  225. package/dist/types.backup/host/pattern-matcher.d.ts +0 -30
  226. package/dist/types.backup/host/router.d.ts +0 -12
  227. package/dist/types.backup/host/testing.d.ts +0 -41
  228. package/dist/types.backup/host/types.d.ts +0 -148
  229. package/dist/types.backup/host/utils.d.ts +0 -20
  230. package/dist/types.backup/href-client.d.ts +0 -214
  231. package/dist/types.backup/index.d.ts +0 -112
  232. package/dist/types.backup/index.rsc.d.ts +0 -51
  233. package/dist/types.backup/internal-debug.d.ts +0 -1
  234. package/dist/types.backup/loader-store.d.ts +0 -193
  235. package/dist/types.backup/loader.d.ts +0 -18
  236. package/dist/types.backup/loader.rsc.d.ts +0 -18
  237. package/dist/types.backup/missing-id-error.d.ts +0 -1
  238. package/dist/types.backup/outlet-context.d.ts +0 -12
  239. package/dist/types.backup/outlet-provider.d.ts +0 -12
  240. package/dist/types.backup/prerender/build-shell-capture.d.ts +0 -104
  241. package/dist/types.backup/prerender/param-hash.d.ts +0 -6
  242. package/dist/types.backup/prerender/shell-manifest-key.d.ts +0 -18
  243. package/dist/types.backup/prerender/store.d.ts +0 -62
  244. package/dist/types.backup/prerender.d.ts +0 -292
  245. package/dist/types.backup/redirect-origin.d.ts +0 -55
  246. package/dist/types.backup/regex-escape.d.ts +0 -6
  247. package/dist/types.backup/render-error-thrower.d.ts +0 -13
  248. package/dist/types.backup/response-utils.d.ts +0 -35
  249. package/dist/types.backup/reverse.d.ts +0 -206
  250. package/dist/types.backup/root-error-boundary.d.ts +0 -32
  251. package/dist/types.backup/route-content-wrapper.d.ts +0 -40
  252. package/dist/types.backup/route-definition/dsl-helpers.d.ts +0 -130
  253. package/dist/types.backup/route-definition/helper-factories.d.ts +0 -22
  254. package/dist/types.backup/route-definition/helpers-types.d.ts +0 -392
  255. package/dist/types.backup/route-definition/index.d.ts +0 -7
  256. package/dist/types.backup/route-definition/redirect.d.ts +0 -48
  257. package/dist/types.backup/route-definition/resolve-handler-use.d.ts +0 -19
  258. package/dist/types.backup/route-definition/use-item-types.d.ts +0 -1
  259. package/dist/types.backup/route-definition.d.ts +0 -1
  260. package/dist/types.backup/route-map-builder.d.ts +0 -127
  261. package/dist/types.backup/route-name.d.ts +0 -27
  262. package/dist/types.backup/route-types.d.ts +0 -172
  263. package/dist/types.backup/router/basename.d.ts +0 -10
  264. package/dist/types.backup/router/content-negotiation.d.ts +0 -91
  265. package/dist/types.backup/router/debug-manifest.d.ts +0 -7
  266. package/dist/types.backup/router/error-handling.d.ts +0 -76
  267. package/dist/types.backup/router/find-match.d.ts +0 -19
  268. package/dist/types.backup/router/handler-context.d.ts +0 -41
  269. package/dist/types.backup/router/instrument.d.ts +0 -161
  270. package/dist/types.backup/router/intercept-resolution.d.ts +0 -79
  271. package/dist/types.backup/router/lazy-includes.d.ts +0 -26
  272. package/dist/types.backup/router/loader-resolution.d.ts +0 -63
  273. package/dist/types.backup/router/logging.d.ts +0 -41
  274. package/dist/types.backup/router/manifest.d.ts +0 -8
  275. package/dist/types.backup/router/match-api.d.ts +0 -19
  276. package/dist/types.backup/router/match-context.d.ts +0 -184
  277. package/dist/types.backup/router/match-handlers.d.ts +0 -49
  278. package/dist/types.backup/router/match-middleware/background-revalidation.d.ts +0 -113
  279. package/dist/types.backup/router/match-middleware/cache-lookup.d.ts +0 -113
  280. package/dist/types.backup/router/match-middleware/cache-store.d.ts +0 -112
  281. package/dist/types.backup/router/match-middleware/index.d.ts +0 -80
  282. package/dist/types.backup/router/match-middleware/intercept-resolution.d.ts +0 -116
  283. package/dist/types.backup/router/match-middleware/segment-resolution.d.ts +0 -94
  284. package/dist/types.backup/router/match-pipelines.d.ts +0 -103
  285. package/dist/types.backup/router/match-result.d.ts +0 -114
  286. package/dist/types.backup/router/metrics.d.ts +0 -6
  287. package/dist/types.backup/router/middleware-types.d.ts +0 -74
  288. package/dist/types.backup/router/middleware.d.ts +0 -116
  289. package/dist/types.backup/router/navigation-snapshot.d.ts +0 -22
  290. package/dist/types.backup/router/params-util.d.ts +0 -8
  291. package/dist/types.backup/router/parse-pattern.d.ts +0 -38
  292. package/dist/types.backup/router/pattern-matching.d.ts +0 -169
  293. package/dist/types.backup/router/prefetch-cache-ttl.d.ts +0 -27
  294. package/dist/types.backup/router/prefetch-limits.d.ts +0 -20
  295. package/dist/types.backup/router/prerender-match.d.ts +0 -50
  296. package/dist/types.backup/router/preview-match.d.ts +0 -22
  297. package/dist/types.backup/router/request-classification.d.ts +0 -104
  298. package/dist/types.backup/router/revalidation.d.ts +0 -57
  299. package/dist/types.backup/router/route-snapshot.d.ts +0 -112
  300. package/dist/types.backup/router/router-context.d.ts +0 -137
  301. package/dist/types.backup/router/router-interfaces.d.ts +0 -432
  302. package/dist/types.backup/router/router-options.d.ts +0 -738
  303. package/dist/types.backup/router/router-registry.d.ts +0 -15
  304. package/dist/types.backup/router/segment-resolution/fresh.d.ts +0 -55
  305. package/dist/types.backup/router/segment-resolution/helpers.d.ts +0 -93
  306. package/dist/types.backup/router/segment-resolution/loader-cache.d.ts +0 -33
  307. package/dist/types.backup/router/segment-resolution/loader-mask.d.ts +0 -44
  308. package/dist/types.backup/router/segment-resolution/loader-snapshot.d.ts +0 -90
  309. package/dist/types.backup/router/segment-resolution/mask-nested.d.ts +0 -53
  310. package/dist/types.backup/router/segment-resolution/revalidation.d.ts +0 -85
  311. package/dist/types.backup/router/segment-resolution/static-store.d.ts +0 -17
  312. package/dist/types.backup/router/segment-resolution/streamed-handler-telemetry.d.ts +0 -16
  313. package/dist/types.backup/router/segment-resolution/view-transition-default.d.ts +0 -28
  314. package/dist/types.backup/router/segment-resolution.d.ts +0 -3
  315. package/dist/types.backup/router/segment-wrappers.d.ts +0 -53
  316. package/dist/types.backup/router/state-cookie-name.d.ts +0 -1
  317. package/dist/types.backup/router/substitute-pattern-params.d.ts +0 -23
  318. package/dist/types.backup/router/telemetry-otel.d.ts +0 -113
  319. package/dist/types.backup/router/telemetry.d.ts +0 -215
  320. package/dist/types.backup/router/timeout.d.ts +0 -68
  321. package/dist/types.backup/router/tracing.d.ts +0 -125
  322. package/dist/types.backup/router/trie-matching.d.ts +0 -32
  323. package/dist/types.backup/router/types.d.ts +0 -98
  324. package/dist/types.backup/router/url-params.d.ts +0 -26
  325. package/dist/types.backup/router.d.ts +0 -7
  326. package/dist/types.backup/rsc/capture-queue.d.ts +0 -6
  327. package/dist/types.backup/rsc/full-payload.d.ts +0 -22
  328. package/dist/types.backup/rsc/handler-context.d.ts +0 -31
  329. package/dist/types.backup/rsc/handler.d.ts +0 -9
  330. package/dist/types.backup/rsc/helpers.d.ts +0 -213
  331. package/dist/types.backup/rsc/index.d.ts +0 -17
  332. package/dist/types.backup/rsc/json-route-result.d.ts +0 -20
  333. package/dist/types.backup/rsc/loader-fetch.d.ts +0 -14
  334. package/dist/types.backup/rsc/manifest-init.d.ts +0 -18
  335. package/dist/types.backup/rsc/nonce.d.ts +0 -28
  336. package/dist/types.backup/rsc/origin-guard.d.ts +0 -50
  337. package/dist/types.backup/rsc/progressive-enhancement.d.ts +0 -19
  338. package/dist/types.backup/rsc/redirect-guard.d.ts +0 -35
  339. package/dist/types.backup/rsc/response-cache-serve.d.ts +0 -46
  340. package/dist/types.backup/rsc/response-error.d.ts +0 -19
  341. package/dist/types.backup/rsc/response-route-handler.d.ts +0 -29
  342. package/dist/types.backup/rsc/rsc-rendering.d.ts +0 -23
  343. package/dist/types.backup/rsc/runtime-warnings.d.ts +0 -22
  344. package/dist/types.backup/rsc/server-action.d.ts +0 -68
  345. package/dist/types.backup/rsc/shell-build-manifest.d.ts +0 -84
  346. package/dist/types.backup/rsc/shell-capture-constants.d.ts +0 -27
  347. package/dist/types.backup/rsc/shell-capture.d.ts +0 -374
  348. package/dist/types.backup/rsc/shell-serve.d.ts +0 -136
  349. package/dist/types.backup/rsc/ssr-setup.d.ts +0 -48
  350. package/dist/types.backup/rsc/transition-gate.d.ts +0 -27
  351. package/dist/types.backup/rsc/types.d.ts +0 -290
  352. package/dist/types.backup/runtime-env.d.ts +0 -1
  353. package/dist/types.backup/search-params.d.ts +0 -125
  354. package/dist/types.backup/segment-content-promise.d.ts +0 -13
  355. package/dist/types.backup/segment-fragments.d.ts +0 -56
  356. package/dist/types.backup/segment-loader-promise.d.ts +0 -22
  357. package/dist/types.backup/segment-system.d.ts +0 -84
  358. package/dist/types.backup/serialize.d.ts +0 -164
  359. package/dist/types.backup/server/context.d.ts +0 -494
  360. package/dist/types.backup/server/cookie-parse.d.ts +0 -10
  361. package/dist/types.backup/server/cookie-store.d.ts +0 -107
  362. package/dist/types.backup/server/fetchable-loader-store.d.ts +0 -20
  363. package/dist/types.backup/server/handle-store.d.ts +0 -100
  364. package/dist/types.backup/server/loader-registry.d.ts +0 -32
  365. package/dist/types.backup/server/request-context.d.ts +0 -596
  366. package/dist/types.backup/server/root-layout.d.ts +0 -3
  367. package/dist/types.backup/server.d.ts +0 -15
  368. package/dist/types.backup/ssr/index.d.ts +0 -233
  369. package/dist/types.backup/ssr/inject-rsc-eager.d.ts +0 -3
  370. package/dist/types.backup/ssr/preinit-client-references.d.ts +0 -71
  371. package/dist/types.backup/ssr/ssr-root.d.ts +0 -69
  372. package/dist/types.backup/static-handler.d.ts +0 -57
  373. package/dist/types.backup/testing/cache-status.d.ts +0 -63
  374. package/dist/types.backup/testing/collect-handle.d.ts +0 -20
  375. package/dist/types.backup/testing/dispatch.d.ts +0 -123
  376. package/dist/types.backup/testing/dom.entry.d.ts +0 -15
  377. package/dist/types.backup/testing/e2e/fixture.d.ts +0 -37
  378. package/dist/types.backup/testing/e2e/index.d.ts +0 -30
  379. package/dist/types.backup/testing/e2e/matchers.d.ts +0 -17
  380. package/dist/types.backup/testing/e2e/page-helpers.d.ts +0 -62
  381. package/dist/types.backup/testing/e2e/parity.d.ts +0 -111
  382. package/dist/types.backup/testing/e2e/server.d.ts +0 -35
  383. package/dist/types.backup/testing/flight-matchers.d.ts +0 -55
  384. package/dist/types.backup/testing/flight-normalize.d.ts +0 -1
  385. package/dist/types.backup/testing/flight-tree.d.ts +0 -192
  386. package/dist/types.backup/testing/flight.d.ts +0 -115
  387. package/dist/types.backup/testing/flight.entry.d.ts +0 -27
  388. package/dist/types.backup/testing/generated-routes.d.ts +0 -66
  389. package/dist/types.backup/testing/index.d.ts +0 -52
  390. package/dist/types.backup/testing/internal/context.d.ts +0 -225
  391. package/dist/types.backup/testing/internal/flight-client-globals.d.ts +0 -1
  392. package/dist/types.backup/testing/internal/seed-vars.d.ts +0 -30
  393. package/dist/types.backup/testing/render-handler.d.ts +0 -160
  394. package/dist/types.backup/testing/render-route.d.ts +0 -246
  395. package/dist/types.backup/testing/run-loader.d.ts +0 -186
  396. package/dist/types.backup/testing/run-middleware.d.ts +0 -132
  397. package/dist/types.backup/testing/run-transition-when.d.ts +0 -77
  398. package/dist/types.backup/testing/vitest-stubs/cloudflare-email.d.ts +0 -6
  399. package/dist/types.backup/testing/vitest-stubs/cloudflare-workers.d.ts +0 -13
  400. package/dist/types.backup/testing/vitest-stubs/plugin-rsc.d.ts +0 -7
  401. package/dist/types.backup/testing/vitest-stubs/version.d.ts +0 -1
  402. package/dist/types.backup/testing/vitest.d.ts +0 -205
  403. package/dist/types.backup/theme/ThemeProvider.d.ts +0 -13
  404. package/dist/types.backup/theme/ThemeScript.d.ts +0 -45
  405. package/dist/types.backup/theme/constants.d.ts +0 -39
  406. package/dist/types.backup/theme/index.d.ts +0 -29
  407. package/dist/types.backup/theme/theme-context.d.ts +0 -21
  408. package/dist/types.backup/theme/theme-script.d.ts +0 -26
  409. package/dist/types.backup/theme/types.d.ts +0 -162
  410. package/dist/types.backup/theme/use-theme.d.ts +0 -8
  411. package/dist/types.backup/types/boundaries.d.ts +0 -93
  412. package/dist/types.backup/types/cache-types.d.ts +0 -191
  413. package/dist/types.backup/types/error-types.d.ts +0 -114
  414. package/dist/types.backup/types/global-namespace.d.ts +0 -90
  415. package/dist/types.backup/types/handler-context.d.ts +0 -658
  416. package/dist/types.backup/types/index.d.ts +0 -11
  417. package/dist/types.backup/types/loader-types.d.ts +0 -182
  418. package/dist/types.backup/types/request-scope.d.ts +0 -93
  419. package/dist/types.backup/types/route-config.d.ts +0 -105
  420. package/dist/types.backup/types/route-entry.d.ts +0 -95
  421. package/dist/types.backup/types/segments.d.ts +0 -234
  422. package/dist/types.backup/types.d.ts +0 -1
  423. package/dist/types.backup/urls/include-helper.d.ts +0 -17
  424. package/dist/types.backup/urls/include-provider.d.ts +0 -27
  425. package/dist/types.backup/urls/index.d.ts +0 -6
  426. package/dist/types.backup/urls/path-helper-types.d.ts +0 -197
  427. package/dist/types.backup/urls/path-helper.d.ts +0 -12
  428. package/dist/types.backup/urls/pattern-types.d.ts +0 -166
  429. package/dist/types.backup/urls/response-types.d.ts +0 -67
  430. package/dist/types.backup/urls/type-extraction.d.ts +0 -157
  431. package/dist/types.backup/urls/urls-function.d.ts +0 -24
  432. package/dist/types.backup/urls.d.ts +0 -1
  433. package/dist/types.backup/use-loader.d.ts +0 -150
  434. package/dist/types.backup/vercel/index.d.ts +0 -10
  435. package/dist/types.backup/vercel/tracing.d.ts +0 -70
  436. package/dist/types.backup/vite/debug.d.ts +0 -80
  437. package/dist/types.backup/vite/discovery/bundle-postprocess.d.ts +0 -12
  438. package/dist/types.backup/vite/discovery/dev-prerender-cache.d.ts +0 -65
  439. package/dist/types.backup/vite/discovery/discover-routers.d.ts +0 -17
  440. package/dist/types.backup/vite/discovery/discovery-errors.d.ts +0 -113
  441. package/dist/types.backup/vite/discovery/gate-state.d.ts +0 -79
  442. package/dist/types.backup/vite/discovery/prerender-collection.d.ts +0 -24
  443. package/dist/types.backup/vite/discovery/route-types-writer.d.ts +0 -32
  444. package/dist/types.backup/vite/discovery/self-gen-tracking.d.ts +0 -22
  445. package/dist/types.backup/vite/discovery/shell-prerender-phase.d.ts +0 -40
  446. package/dist/types.backup/vite/discovery/state.d.ts +0 -162
  447. package/dist/types.backup/vite/discovery/virtual-module-codegen.d.ts +0 -15
  448. package/dist/types.backup/vite/index.d.ts +0 -11
  449. package/dist/types.backup/vite/inject-client-debug.d.ts +0 -56
  450. package/dist/types.backup/vite/plugin-types.d.ts +0 -298
  451. package/dist/types.backup/vite/plugins/cjs-to-esm.d.ts +0 -6
  452. package/dist/types.backup/vite/plugins/client-ref-dedup.d.ts +0 -40
  453. package/dist/types.backup/vite/plugins/client-ref-hashing.d.ts +0 -35
  454. package/dist/types.backup/vite/plugins/cloudflare-protocol-stub.d.ts +0 -64
  455. package/dist/types.backup/vite/plugins/expose-action-id.d.ts +0 -18
  456. package/dist/types.backup/vite/plugins/expose-id-utils.d.ts +0 -37
  457. package/dist/types.backup/vite/plugins/expose-ids/export-analysis.d.ts +0 -19
  458. package/dist/types.backup/vite/plugins/expose-ids/handler-transform.d.ts +0 -10
  459. package/dist/types.backup/vite/plugins/expose-ids/loader-transform.d.ts +0 -8
  460. package/dist/types.backup/vite/plugins/expose-ids/router-transform.d.ts +0 -13
  461. package/dist/types.backup/vite/plugins/expose-ids/types.d.ts +0 -29
  462. package/dist/types.backup/vite/plugins/expose-internal-ids.d.ts +0 -6
  463. package/dist/types.backup/vite/plugins/performance-tracks.d.ts +0 -25
  464. package/dist/types.backup/vite/plugins/refresh-cmd.d.ts +0 -20
  465. package/dist/types.backup/vite/plugins/use-cache-transform.d.ts +0 -20
  466. package/dist/types.backup/vite/plugins/vercel-output.d.ts +0 -85
  467. package/dist/types.backup/vite/plugins/version-injector.d.ts +0 -21
  468. package/dist/types.backup/vite/plugins/version-plugin.d.ts +0 -19
  469. package/dist/types.backup/vite/plugins/virtual-entries.d.ts +0 -36
  470. package/dist/types.backup/vite/plugins/virtual-stub-plugin.d.ts +0 -7
  471. package/dist/types.backup/vite/rango.d.ts +0 -29
  472. package/dist/types.backup/vite/router-discovery.d.ts +0 -23
  473. package/dist/types.backup/vite/utils/ast-handler-extract.d.ts +0 -64
  474. package/dist/types.backup/vite/utils/banner.d.ts +0 -2
  475. package/dist/types.backup/vite/utils/bundle-analysis.d.ts +0 -28
  476. package/dist/types.backup/vite/utils/client-chunks.d.ts +0 -55
  477. package/dist/types.backup/vite/utils/directive-prologue.d.ts +0 -16
  478. package/dist/types.backup/vite/utils/forward-user-plugins.d.ts +0 -37
  479. package/dist/types.backup/vite/utils/manifest-utils.d.ts +0 -7
  480. package/dist/types.backup/vite/utils/package-resolution.d.ts +0 -6
  481. package/dist/types.backup/vite/utils/prerender-utils.d.ts +0 -32
  482. package/dist/types.backup/vite/utils/shared-utils.d.ts +0 -55
@@ -106,6 +106,7 @@ import {
106
106
  runWithRequestContext,
107
107
  } from "../../server/request-context.js";
108
108
  import type { MatchContext, MatchPipelineState } from "../match-context.js";
109
+ import { createShellImplicitDocScope } from "../../cache/cache-scope.js";
109
110
  import { getRouterContext } from "../router-context.js";
110
111
  import { debugLog, debugWarn, getOrCreateRequestId } from "../logging.js";
111
112
  import { INTERNAL_RANGO_DEBUG } from "../../internal-debug.js";
@@ -134,6 +135,14 @@ export function withCacheStore<TEnv>(
134
135
 
135
136
  const ownStart = performance.now();
136
137
 
138
+ // Shell capture composition (capture side): a route-derived cache() scope
139
+ // keeps its normal store write below, but the capture's shell entry still
140
+ // needs the CANONICAL doc segment record for navigation replay. Recorded
141
+ // before the skip check because it must run on the explicit tier's hit
142
+ // path too (state.cacheHit skips the normal write, yet the served
143
+ // segments were collected into allSegments either way).
144
+ recordShellCaptureDocRecord(ctx, state, allSegments);
145
+
137
146
  if (
138
147
  !ctx.cacheScope?.enabled ||
139
148
  ctx.isAction ||
@@ -348,3 +357,64 @@ export function withCacheStore<TEnv>(
348
357
  }
349
358
  };
350
359
  }
360
+
361
+ /**
362
+ * During a SHELL CAPTURE of a route with a route-derived cache() scope, write
363
+ * the matched non-loader segments as the canonical doc segment record through
364
+ * the capture marker's SnapshotOnlySegmentStore — IN ADDITION to the explicit
365
+ * scope's normal real-store write. The record rides only inside the shell
366
+ * entry (a real doc-keyed write would poison the next capture's lookup; see
367
+ * RecordingShellStore.recordSegmentWrite), so no real-store behavior changes.
368
+ * Without it, navigation replay was structurally dead for any ppr route under
369
+ * a cache() scope (including an app-wide one): the snapshot held only
370
+ * explicit-tier-keyed records a partial lookup can never resolve.
371
+ *
372
+ * Records nothing when:
373
+ * - not a capture render, or the route derived no scope (the implicit doc
374
+ * scope's own cacheRoute below already records the doc record);
375
+ * - the scope is STATICALLY disabled (cache(false)) — the replay gate
376
+ * pre-decides that shape as `cache-disabled` before any shell read, so a
377
+ * record would be dead weight;
378
+ * - the prerender store supplied the match: those partials are served from
379
+ * build-time segments and report `prerender-store`.
380
+ *
381
+ * A false condition() suppresses the record too — the consumer's write
382
+ * refusal is absolute. The prelude-already-bakes-it argument does NOT excuse
383
+ * recording: a NAVIGATION-ONLY capture's prelude is never served as a
384
+ * document, so for those entries the segment record would be the sole
385
+ * persisted copy of a render the consumer refused to cache — and a later
386
+ * request where condition() flips true could consume it through the seeded
387
+ * fallback. The lookup-time `cache-disabled` report stays reachable without
388
+ * the record: matchPartialWithPprReplay installs a REPORT-ONLY marker (no
389
+ * store) on the no-eligible-snapshot path, so the lookup's own refusal is
390
+ * still surfaced while the fallback has nothing to serve.
391
+ *
392
+ * Wrapped in requestCtx.waitUntil — during a capture that is the tracked-write
393
+ * override, so captureAndStoreShell's settleWrites awaits the record before
394
+ * draining the snapshot.
395
+ */
396
+ function recordShellCaptureDocRecord<TEnv>(
397
+ ctx: MatchContext<TEnv>,
398
+ state: MatchPipelineState,
399
+ segments: ResolvedSegment[],
400
+ ): void {
401
+ const requestCtx = getRequestContext();
402
+ if (!requestCtx?._shellCaptureRun) return;
403
+ const marker = requestCtx._shellImplicitCache;
404
+ if (!marker?.store) return;
405
+ const scope = ctx.cacheScope;
406
+ if (!scope || scope.isShellImplicitDocScope) return;
407
+ if (ctx.isAction || ctx.isIntercept || ctx.request.method !== "GET") return;
408
+ if (state.cacheSource === "prerender") return;
409
+ if (!scope.allowsCache("write")) return;
410
+
411
+ const docScope = createShellImplicitDocScope(marker);
412
+ requestCtx.waitUntil(() =>
413
+ docScope.cacheRoute(
414
+ ctx.pathname,
415
+ ctx.matched.params,
416
+ segments,
417
+ ctx.isIntercept,
418
+ ),
419
+ );
420
+ }
@@ -30,6 +30,50 @@ export interface ResolveNavigationDeps {
30
30
  ) => RouteMatchResult | null | Promise<RouteMatchResult | null>;
31
31
  }
32
32
 
33
+ /**
34
+ * The raw navigation-context header for a partial request, or null when the
35
+ * request carries none. Single source of truth shared by resolveNavigation and
36
+ * the PPR replay gate (matchPartialWithPprReplay): a context-less partial can
37
+ * never produce a partial match, so the replay path must decide
38
+ * `no-navigation-context` BEFORE spending shell-store reads — the two
39
+ * predicates drifting apart would misattribute the bypass again.
40
+ */
41
+ export function getNavigationContextHeader(request: Request): string | null {
42
+ return (
43
+ request.headers.get("X-RSC-Router-Client-Path") ||
44
+ request.headers.get("Referer")
45
+ );
46
+ }
47
+
48
+ /**
49
+ * Whether withCacheLookup's prerender short-circuit will serve this partial
50
+ * from the build-time prerender store: a Prerender() match (`matched.pr`)
51
+ * outside dev HMR — the short-circuit is disabled on X-RSC-HMR so HMR
52
+ * navigations pick up edited modules. Shared by withCacheLookup and the PPR
53
+ * replay gate (matchPartialWithPprReplay) for the same drift reason as
54
+ * getNavigationContextHeader: the gate's `prerender-store` bypass must decide
55
+ * exactly what the middleware will actually do. (Both callers additionally
56
+ * exclude actions on their own paths — the gate via its GET-only check.)
57
+ */
58
+ export function prerenderStoreShortCircuits(
59
+ pr: true | undefined,
60
+ request: Request,
61
+ ): boolean {
62
+ return pr === true && !request.headers.get("X-RSC-HMR");
63
+ }
64
+
65
+ /**
66
+ * The intercept-source header for a partial request, or null when the request
67
+ * carries none. Shared by resolveNavigation and the PPR replay gate's
68
+ * prerender probe: intercept navigations consult the intercept-specific
69
+ * prerender artifact (`paramHash + "/i"`), so the probe must check the same
70
+ * variant the middleware will — probing the bare hash for an intercept
71
+ * request would report `prerender-store` for an artifact that cannot serve.
72
+ */
73
+ export function getInterceptSourceHeader(request: Request): string | null {
74
+ return request.headers.get("X-RSC-Router-Intercept-Source");
75
+ }
76
+
33
77
  export async function resolveNavigation(
34
78
  request: Request,
35
79
  url: URL,
@@ -39,12 +83,8 @@ export async function resolveNavigation(
39
83
  const clientSegmentIds =
40
84
  url.searchParams.get("_rsc_segments")?.split(",").filter(Boolean) || [];
41
85
  const stale = url.searchParams.get("_rsc_stale") === "true";
42
- const previousUrl =
43
- request.headers.get("X-RSC-Router-Client-Path") ||
44
- request.headers.get("Referer");
45
- const interceptSourceUrl = request.headers.get(
46
- "X-RSC-Router-Intercept-Source",
47
- );
86
+ const previousUrl = getNavigationContextHeader(request);
87
+ const interceptSourceUrl = getInterceptSourceHeader(request);
48
88
  const isHmr = !!request.headers.get("X-RSC-HMR");
49
89
 
50
90
  if (!previousUrl) {
@@ -1,5 +1,6 @@
1
1
  import type { ComponentType, ReactNode } from "react";
2
2
  import type { SegmentCacheStore } from "../cache/types.js";
3
+ import type { CacheSearchParams } from "../cache/search-params-filter.js";
3
4
  import type {
4
5
  ErrorBoundaryHandler,
5
6
  NotFoundBoundaryHandler,
@@ -304,15 +305,37 @@ export interface RangoOptions<TEnv = any> {
304
305
  * }),
305
306
  * });
306
307
  * ```
308
+ *
309
+ * `searchParams` controls which query params key the cache (default:
310
+ * `"all"`). Cache keys only -- handlers still see the full query string.
311
+ * Excluding a param is a promise that rendered output does not depend on
312
+ * it; if it does, the first variant is cached and served to everyone.
313
+ *
314
+ * @example Ignore tracking params for cache keys
315
+ * ```typescript
316
+ * import { TRACKING_SEARCH_PARAMS } from "@rangojs/router";
317
+ *
318
+ * const router = createRouter({
319
+ * cache: {
320
+ * store: cacheStore,
321
+ * searchParams: { exclude: TRACKING_SEARCH_PARAMS },
322
+ * },
323
+ * });
324
+ * ```
307
325
  */
308
326
  cache?:
309
- | { store: SegmentCacheStore; enabled?: boolean }
327
+ | {
328
+ store: SegmentCacheStore;
329
+ enabled?: boolean;
330
+ searchParams?: CacheSearchParams;
331
+ }
310
332
  | ((
311
333
  env: TEnv,
312
334
  ctx?: ExecutionContext,
313
335
  ) => {
314
336
  store: SegmentCacheStore;
315
337
  enabled?: boolean;
338
+ searchParams?: CacheSearchParams;
316
339
  });
317
340
 
318
341
  /**
@@ -535,9 +558,13 @@ export interface RangoOptions<TEnv = any> {
535
558
 
536
559
  /**
537
560
  * Default prefetch strategy for every `<Link>` that does not set its own
538
- * `prefetch` prop. A per-Link `prefetch` prop always wins, in both
539
- * directions (a Link can opt out of an aggressive default with
540
- * `prefetch="none"`, or opt in under `defaultPrefetch: "none"`).
561
+ * `prefetch` prop and every eligible intercepted plain anchor. Plain anchors
562
+ * can opt out with `data-prefetch="false"` or `data-prefetch="none"`. Common
563
+ * static-resource suffixes are excluded unless `data-prefetch="true"` marks
564
+ * the URL as an application route. Mark side-effectful GET links such as
565
+ * `/logout` with an opt-out because the router cannot infer endpoint safety.
566
+ * A per-Link `prefetch` prop always wins in both directions (a Link can opt
567
+ * out with `prefetch="none"`, or opt in under `defaultPrefetch: "none"`).
541
568
  *
542
569
  * - `"viewport"` (production default): prefetch when the link enters the viewport —
543
570
  * idle-gated and queued (see `prefetchConcurrency`), so prefetches never
@@ -64,6 +64,10 @@ import {
64
64
  } from "../route-map-builder.js";
65
65
  import type { HandlerContext } from "./handler-context.js";
66
66
  import type { CacheErrorCategory } from "../cache/cache-error.js";
67
+ import {
68
+ compileSearchParamsFilter,
69
+ type SearchParamsFilter,
70
+ } from "../cache/search-params-filter.js";
67
71
  import type { SegmentCacheStore } from "../cache/types.js";
68
72
  import { buildRouterTrieFromUrlpatterns } from "./manifest-init.js";
69
73
  import { handleProgressiveEnhancement } from "./progressive-enhancement.js";
@@ -460,6 +464,7 @@ export function createRSCHandler<
460
464
  // Priority: options.cache (handler override) > router.cache (router default)
461
465
  // Store is enabled only if: config provided, enabled, and no ?__no_cache query param
462
466
  let cacheStore: SegmentCacheStore | undefined;
467
+ let searchParamsFilter: SearchParamsFilter | undefined;
463
468
  const cacheOption = options.cache ?? router.cache;
464
469
  if (cacheOption && !url.searchParams.has("__no_cache")) {
465
470
  const cacheConfig =
@@ -469,6 +474,9 @@ export function createRSCHandler<
469
474
 
470
475
  if (cacheConfig.enabled !== false) {
471
476
  cacheStore = cacheConfig.store;
477
+ searchParamsFilter = compileSearchParamsFilter(
478
+ cacheConfig.searchParams,
479
+ );
472
480
  }
473
481
  }
474
482
 
@@ -526,6 +534,7 @@ export function createRSCHandler<
526
534
  url,
527
535
  variables,
528
536
  cacheStore,
537
+ searchParamsFilter,
529
538
  explicitTaggedStores,
530
539
  cacheProfiles: router.cacheProfiles,
531
540
  executionContext: executionCtx,
@@ -103,7 +103,7 @@ export async function serveResponseRouteWithCache(
103
103
  // Default key: response:{type}: + host-namespaced base (sorted search, reserved
104
104
  // _rsc*/__* params excluded). Same composition as document/segment tiers so
105
105
  // the host-namespacing and search-normalization rules cannot drift.
106
- let cacheKey = `response:${responseType}:${cacheKeyBase(url.host, url.pathname, url.searchParams)}`;
106
+ let cacheKey = `response:${responseType}:${cacheKeyBase(url.host, url.pathname, url.searchParams, undefined, reqCtx._searchParamsFilter)}`;
107
107
 
108
108
  // Priority 1: route-level key() (full override). Priority 2: store-level
109
109
  // keyGenerator (modifies the default key).
@@ -61,12 +61,22 @@ import {
61
61
  type DevShellLookup,
62
62
  } from "./shell-build-manifest.js";
63
63
  import { contextGet } from "../context-var.js";
64
+ import {
65
+ getNavigationContextHeader,
66
+ prerenderStoreShortCircuits,
67
+ } from "../router/navigation-snapshot.js";
68
+ import {
69
+ ensureFullRouteSnapshot,
70
+ type RouteSnapshot,
71
+ } from "../router/route-snapshot.js";
72
+ import { prerenderEntryExists } from "../router/match-middleware/cache-lookup.js";
64
73
  import {
65
74
  resolveSameOriginRedirect,
66
75
  safeSameOriginLanding,
67
76
  } from "../redirect-origin.js";
68
77
  import { nonce as nonceToken } from "./nonce.js";
69
78
  import { reportCacheError } from "../cache/cache-error.js";
79
+ import type { SearchParamsFilter } from "../cache/search-params-filter.js";
70
80
  import { INTERNAL_RANGO_DEBUG } from "../internal-debug.js";
71
81
  import type {
72
82
  SegmentCacheStore,
@@ -80,6 +90,10 @@ type PprReplayBypassReason =
80
90
  | "nonce"
81
91
  | "store-unavailable"
82
92
  | "passive-read-unsupported"
93
+ | "no-navigation-context"
94
+ | "prerender-store"
95
+ | "intercept"
96
+ | "cache-disabled"
83
97
  | "read-error"
84
98
  | "no-entry"
85
99
  | "invalid-version"
@@ -88,6 +102,7 @@ type PprReplayBypassReason =
88
102
  | "transition-when"
89
103
  | "no-segment-snapshot"
90
104
  | "snapshot-miss"
105
+ | "explicit-cache-hit"
91
106
  | "stale-build-entry";
92
107
 
93
108
  type PprReplayStatus =
@@ -110,8 +125,11 @@ function describePprReplayStatus(status: PprReplayStatus): string {
110
125
  : `bypass:${status.reason}`;
111
126
  }
112
127
 
113
- function buildNavigationShellKey(url: URL): string {
114
- return `${buildShellKey(url)}:navigation`;
128
+ function buildNavigationShellKey(
129
+ url: URL,
130
+ filter?: SearchParamsFilter,
131
+ ): string {
132
+ return `${buildShellKey(url, filter)}:navigation`;
115
133
  }
116
134
 
117
135
  function createShellCaptureDescriptor(
@@ -147,6 +165,26 @@ function shouldHealReplayMiss(
147
165
  );
148
166
  }
149
167
 
168
+ /**
169
+ * Post-match truth override for a pre-match BYPASS classification. The gate
170
+ * decides before matchPartial runs, but two facts only the match can settle:
171
+ * whether the prerender store ACTUALLY served (either artifact variant — the
172
+ * gate's probe reads only the non-intercept one), and whether the navigation
173
+ * resolved to an intercept (findInterceptForRoute runs during the match; the
174
+ * intercept-source header proves nothing in either direction). The resulting
175
+ * reason is stamped on the request context by withCacheLookup. A replay HIT is
176
+ * never overridden — the seeded record was demonstrably consumed, so neither
177
+ * fact can be true.
178
+ */
179
+ function reclassifyReplayStatus(
180
+ reqCtx: RequestContext<any>,
181
+ status: PprReplayStatus,
182
+ ): PprReplayStatus {
183
+ if (status.outcome === "HIT") return status;
184
+ const reason = reqCtx._pprReplayPostMatchReason;
185
+ return reason ? { outcome: "BYPASS", reason } : status;
186
+ }
187
+
150
188
  function resolveDevShellLookup(
151
189
  reqCtx: RequestContext<any>,
152
190
  pprConfig: ResolvedPprConfig,
@@ -173,21 +211,32 @@ function replayableShellSnapshot(
173
211
  if (!hasIntactShellPayload(entry)) return { reason: "corrupt-entry" };
174
212
  if (entry.handlerLiveHoles) return { reason: "handler-live-holes" };
175
213
  if (entry.transitionWhen) return { reason: "transition-when" };
214
+ // Eligibility requires the CANONICAL doc segment record (`docKey`), not just
215
+ // any segment record: captures under an explicit cache() scope also record
216
+ // that tier's reads/writes under keys a partial lookup can never resolve,
217
+ // and counting those declared entries "replayable" that then always missed
218
+ // (a timing-dependent snapshot-miss/no-segment-snapshot flip-flop). Entries
219
+ // captured before the field existed read as no-segment-snapshot and heal on
220
+ // recapture (pre-release, same treatment as the buildVersion field).
221
+ const docKey = entry.docKey;
176
222
  const snapshot = entry.snapshot;
177
- const hasSegments = snapshot?.some((record) => {
178
- if (
179
- !record ||
180
- typeof record !== "object" ||
181
- record.family !== "segment" ||
182
- typeof record.value !== "object" ||
183
- record.value === null
184
- ) {
185
- return false;
186
- }
187
- const segments = (record.value as { segments?: unknown }).segments;
188
- return Array.isArray(segments) && segments.length > 0;
189
- });
190
- return hasSegments && snapshot
223
+ const hasDocRecord =
224
+ docKey !== undefined &&
225
+ snapshot?.some((record) => {
226
+ if (
227
+ !record ||
228
+ typeof record !== "object" ||
229
+ record.family !== "segment" ||
230
+ record.key !== docKey ||
231
+ typeof record.value !== "object" ||
232
+ record.value === null
233
+ ) {
234
+ return false;
235
+ }
236
+ const segments = (record.value as { segments?: unknown }).segments;
237
+ return Array.isArray(segments) && segments.length > 0;
238
+ });
239
+ return hasDocRecord && snapshot
191
240
  ? { snapshot }
192
241
  : { reason: "no-segment-snapshot" };
193
242
  }
@@ -263,7 +312,7 @@ async function handleRscRenderingInner<TEnv>(
263
312
  // the provider-only check missed the latter (issue #656).
264
313
  const activeNonce = nonce ?? contextGet(reqCtx._variables, nonceToken);
265
314
  const store = reqCtx._cacheStore;
266
- const key = buildShellKey(url);
315
+ const key = buildShellKey(url, reqCtx._searchParamsFilter);
267
316
  // Dev Server-Timing mirror (issue #651): a capture completes AFTER its
268
317
  // triggering response committed, so its outcome can only ride a LATER
269
318
  // response's header. Read-and-clear keeps one capture = one report;
@@ -417,6 +466,7 @@ async function handleRscRenderingInner<TEnv>(
417
466
  // only (production's exact candidate set). Folded away in
418
467
  // production builds (NODE_ENV is a compile-time constant).
419
468
  resolveDevShellLookup(reqCtx, pprConfig),
469
+ reqCtx._searchParamsFilter,
420
470
  );
421
471
  if (buildHit) {
422
472
  // Past ppr.ttl: still serve the baked entry, recapture upgrades it.
@@ -671,7 +721,7 @@ async function handleRscRenderingInner<TEnv>(
671
721
  },
672
722
  createShellCaptureDescriptor(
673
723
  ctx,
674
- buildNavigationShellKey(url),
724
+ buildNavigationShellKey(url, reqCtx._searchParamsFilter),
675
725
  pprConfig,
676
726
  store,
677
727
  true,
@@ -710,10 +760,17 @@ async function matchPartialWithPprReplay<TEnv>(
710
760
  describePprReplayStatus(status),
711
761
  );
712
762
  };
763
+ const finalizeReplayStatus = (status: PprReplayStatus): PprReplayStatus => {
764
+ const finalStatus = reclassifyReplayStatus(reqCtx, status);
765
+ recordReplayStatus(finalStatus);
766
+ return finalStatus;
767
+ };
713
768
  const runMatch = async (status?: PprReplayStatus) => {
714
769
  const result = await ctx.router.matchPartial(request, { env });
715
- if (status) recordReplayStatus(status);
716
- return { result, status };
770
+ // The match may have settled a fact the pre-match gate could only guess
771
+ // at (prerender serve, intercept resolution) — report the truth.
772
+ const finalStatus = status ? finalizeReplayStatus(status) : undefined;
773
+ return { result, status: finalStatus };
717
774
  };
718
775
  const pprConfig = resolvePprConfig(reqCtx._classifiedRoute?.manifestEntry);
719
776
  const activeNonce = nonce ?? contextGet(reqCtx._variables, nonceToken);
@@ -738,9 +795,64 @@ async function matchPartialWithPprReplay<TEnv>(
738
795
  reason: "passive-read-unsupported",
739
796
  });
740
797
  }
798
+ // A partial without navigation context (curl probes, synthetic monitors)
799
+ // can never produce a partial match — createMatchContextForPartial returns
800
+ // null and the seeded record could not have been consulted, which used to
801
+ // read as a misleading `snapshot-miss` AFTER two wasted getShell reads.
802
+ // Same predicate as resolveNavigation, decided before any store I/O.
803
+ if (!getNavigationContextHeader(request)) {
804
+ return runMatch({ outcome: "BYPASS", reason: "no-navigation-context" });
805
+ }
806
+ // The prerender probe and the cache-opt-out gate below both need the
807
+ // classified snapshot; resolve (and persist) it once.
808
+ const routeSnapshot = classifiedRouteSnapshot(reqCtx);
809
+ // Prerender routes short-circuit in withCacheLookup and serve the partial
810
+ // from build-time segments — a better-than-HIT outcome. Their captures
811
+ // record no doc segment record (withCacheStore skips on the prerender hit),
812
+ // so seeding could never succeed; skip the reads and report the store that
813
+ // actually serves instead of blaming a "broken" capture. Bypass ONLY when
814
+ // the baked artifact actually exists — the trie's pr flag alone is not a
815
+ // serve guarantee: a Passthrough(Prerender()) route with an unbaked or
816
+ // ctx.passthrough()-skipped param misses the store and renders live, and
817
+ // replay (including its heal capture) must stay available for it. The
818
+ // probe goes through the same memoized store the middleware serves from.
819
+ // Shared predicate with the middleware (it declines on dev HMR — such
820
+ // partials fall through to the ordinary replay decision here too).
821
+ //
822
+ // The probe is a PRE-match fast path, not the truth: it reads only the
823
+ // non-intercept artifact, and whether the navigation IS an intercept (and
824
+ // therefore whether tryPrerenderLookup reads `paramHash` or
825
+ // `paramHash + "/i"`) is resolved during the match by match-api's
826
+ // findInterceptForRoute — an intercept-source header proves nothing in
827
+ // either direction. runMatch reclassifies every BYPASS from the stamped
828
+ // post-match facts (reclassifyReplayStatus), so a wrong guess here can
829
+ // skip the two getShell reads but never mis-report or mis-heal.
830
+ if (
831
+ prerenderStoreShortCircuits(routeSnapshot?.matched?.pr, request) &&
832
+ (await prerenderEntryExists(
833
+ routeSnapshot?.matched?.routeKey,
834
+ routeSnapshot?.params ?? {},
835
+ url.pathname,
836
+ routeSnapshot?.entries ?? [],
837
+ ))
838
+ ) {
839
+ return runMatch({ outcome: "BYPASS", reason: "prerender-store" });
840
+ }
841
+ // Consumer cache opt-outs are absolute: a STATICALLY disabled scope
842
+ // (cache(false)) bypasses before any shell read — no heal capture (its
843
+ // snapshot would be equally unusable). A `condition()` predicate is
844
+ // request-time state and must NOT be pre-decided here: evaluating it at the
845
+ // gate and again at the lookup lets a false-then-true flap report
846
+ // cache-disabled while the explicit tier serves. The lookup's own
847
+ // evaluation governs (withCacheLookup fires the marker's onExplicitBypass,
848
+ // reported as cache-disabled post-match).
849
+ const routeCacheScope = routeSnapshot?.cacheScope ?? null;
850
+ if (routeCacheScope && !routeCacheScope.enabled) {
851
+ return runMatch({ outcome: "BYPASS", reason: "cache-disabled" });
852
+ }
741
853
 
742
- const key = buildShellKey(url);
743
- const navigationKey = buildNavigationShellKey(url);
854
+ const key = buildShellKey(url, reqCtx._searchParamsFilter);
855
+ const navigationKey = `${key}:navigation`;
744
856
  let cached: Awaited<ReturnType<typeof store.getShell>> = null;
745
857
  try {
746
858
  cached = await store.getShell(key, { claimRevalidation: false });
@@ -794,7 +906,13 @@ async function matchPartialWithPprReplay<TEnv>(
794
906
  // Production build manifests are local module data. In dev, resolving a
795
907
  // missing build shell would foreground-fetch /__rsc_shell and block an
796
908
  // otherwise ordinary navigation on capture, so replay remains runtime-only.
797
- const buildHit = await lookupBuildShell(url, ctx.version, store);
909
+ const buildHit = await lookupBuildShell(
910
+ url,
911
+ ctx.version,
912
+ store,
913
+ undefined,
914
+ reqCtx._searchParamsFilter,
915
+ );
798
916
  if (buildHit?.stale) {
799
917
  bypassReason ??= "stale-build-entry";
800
918
  } else if (buildHit) {
@@ -811,15 +929,78 @@ async function matchPartialWithPprReplay<TEnv>(
811
929
  }
812
930
 
813
931
  if (!snapshot) {
932
+ // Report-only marker for routes with an ENABLED route-derived scope: the
933
+ // lookup's own outcome must stay reportable even without a replayable
934
+ // snapshot. An always-false condition() route never produces a doc
935
+ // record (the consumer's write refusal is absolute — see
936
+ // recordShellCaptureDocRecord), so without this its lookup-time refusal
937
+ // would be misreported as the eligibility reason and heal captures would
938
+ // be scheduled for snapshots that can never become consumable. The
939
+ // marker carries NO store: the seeded fallback in withCacheLookup
940
+ // requires one, so nothing can be served through it — it only reports.
941
+ // Bare routes never see it (an installed marker would otherwise mint an
942
+ // implicit scope over the REAL doc: partition in
943
+ // resolveShellImplicitCacheScope).
944
+ if (routeCacheScope?.enabled) {
945
+ let explicitCacheHit = false;
946
+ let explicitCacheBypass = false;
947
+ const previousImplicitCache = reqCtx._shellImplicitCache;
948
+ reqCtx._shellImplicitCache = {
949
+ onExplicitHit: () => {
950
+ explicitCacheHit = true;
951
+ },
952
+ onExplicitBypass: () => {
953
+ explicitCacheBypass = true;
954
+ },
955
+ };
956
+ try {
957
+ const result = await ctx.router.matchPartial(request, { env });
958
+ const provisionalStatus: PprReplayStatus = explicitCacheBypass
959
+ ? { outcome: "BYPASS", reason: "cache-disabled" }
960
+ : explicitCacheHit
961
+ ? { outcome: "BYPASS", reason: "explicit-cache-hit" }
962
+ : { outcome: "BYPASS", reason: bypassReason ?? "no-entry" };
963
+ const status = finalizeReplayStatus(provisionalStatus);
964
+ return {
965
+ result,
966
+ status,
967
+ // A lookup-time opt-out makes every heal snapshot unusable
968
+ // (recordShellCaptureDocRecord refuses under the same predicate),
969
+ // and a prerender-served or intercept match never consults a heal
970
+ // snapshot at all. Otherwise heal the shouldHealReplayMiss set PLUS
971
+ // `no-segment-snapshot`: an entry captured while condition() was
972
+ // false legitimately lacks a snapshot, and a later request whose
973
+ // lookup did NOT refuse (condition true now) can heal it — the
974
+ // capture derives from THIS request's context, so its doc record
975
+ // records. Excluding it left replay dead until the document
976
+ // recaptured. The always-false route stays protected: its every
977
+ // lookup refuses, so explicitCacheBypass suppresses the heal.
978
+ captureNeeded:
979
+ !explicitCacheBypass &&
980
+ reqCtx._pprReplayPostMatchReason === undefined &&
981
+ (shouldHealReplayMiss(bypassReason) ||
982
+ bypassReason === "no-segment-snapshot"),
983
+ };
984
+ } finally {
985
+ reqCtx._shellImplicitCache = previousImplicitCache;
986
+ }
987
+ }
814
988
  const match = await runMatch({
815
989
  outcome: "BYPASS",
816
990
  reason: bypassReason ?? "no-entry",
817
991
  });
818
- return { ...match, captureNeeded: shouldHealReplayMiss(bypassReason) };
992
+ return {
993
+ ...match,
994
+ captureNeeded:
995
+ reqCtx._pprReplayPostMatchReason === undefined &&
996
+ shouldHealReplayMiss(bypassReason),
997
+ };
819
998
  }
820
999
 
821
1000
  const previousImplicitCache = reqCtx._shellImplicitCache;
822
1001
  let segmentReplayHit = false;
1002
+ let explicitCacheHit = false;
1003
+ let explicitCacheBypass = false;
823
1004
  reqCtx._shellImplicitCache = {
824
1005
  ttl: pprConfig.ttl,
825
1006
  swr: pprConfig.swr,
@@ -830,20 +1011,64 @@ async function matchPartialWithPprReplay<TEnv>(
830
1011
  onHit: () => {
831
1012
  segmentReplayHit = true;
832
1013
  },
1014
+ // Arms the explicit-scope composition in withCacheLookup: a route-derived
1015
+ // cache() scope stays authoritative, the seeded doc record supplies the
1016
+ // match only on its miss. An explicit-tier hit must NOT report a replay
1017
+ // HIT — it served under the consumer's own semantics.
1018
+ onExplicitHit: () => {
1019
+ explicitCacheHit = true;
1020
+ },
1021
+ // Lookup-time condition() refusal (or a scope with no store): the gate
1022
+ // deliberately does not pre-decide predicates, so the truthful
1023
+ // cache-disabled report comes from the lookup that actually refused.
1024
+ onExplicitBypass: () => {
1025
+ explicitCacheBypass = true;
1026
+ },
833
1027
  };
834
1028
 
835
1029
  try {
836
1030
  const result = await ctx.router.matchPartial(request, { env });
837
- const status: PprReplayStatus = segmentReplayHit
1031
+ const provisionalStatus: PprReplayStatus = segmentReplayHit
838
1032
  ? { outcome: "HIT", freshness }
839
- : { outcome: "BYPASS", reason: "snapshot-miss" };
840
- recordReplayStatus(status);
1033
+ : explicitCacheHit
1034
+ ? { outcome: "BYPASS", reason: "explicit-cache-hit" }
1035
+ : explicitCacheBypass
1036
+ ? { outcome: "BYPASS", reason: "cache-disabled" }
1037
+ : { outcome: "BYPASS", reason: "snapshot-miss" };
1038
+ // A prerender serve or intercept resolution leaves the seeded record
1039
+ // unconsulted (prerender short-circuits before the scope; intercepts
1040
+ // keep snapshot.cacheScope) — the "snapshot-miss" guess would blame the
1041
+ // capture for a lane that was never in play.
1042
+ const status = finalizeReplayStatus(provisionalStatus);
841
1043
  return { result, status };
842
1044
  } finally {
843
1045
  reqCtx._shellImplicitCache = previousImplicitCache;
844
1046
  }
845
1047
  }
846
1048
 
1049
+ /**
1050
+ * The full route snapshot for the classified route, or null when
1051
+ * classification is unavailable (the gates then fall open to the ordinary
1052
+ * replay decision). Persists the enriched snapshot back onto
1053
+ * `_classifiedRoute` so the manifest-chain walk runs once per request:
1054
+ * matchPartial's createMatchContextForPartial re-reads `_classifiedRoute` and
1055
+ * calls ensureFullRouteSnapshot again, and the write-back lets that call hit
1056
+ * the entries-already-built fast path and reuse this same scope chain instead
1057
+ * of rebuilding it.
1058
+ */
1059
+ function classifiedRouteSnapshot(
1060
+ reqCtx: RequestContext<any>,
1061
+ ): RouteSnapshot<any> | null {
1062
+ const classified = reqCtx._classifiedRoute;
1063
+ if (!classified?.manifestEntry) return null;
1064
+ const full = ensureFullRouteSnapshot({
1065
+ ...classified,
1066
+ entries: classified.entries ?? [],
1067
+ });
1068
+ reqCtx._classifiedRoute = full;
1069
+ return full;
1070
+ }
1071
+
847
1072
  /**
848
1073
  * Neutralize the shell-HIT degradation redirect target. The inline
849
1074
  * `location.replace` in a committed 200 body bypasses the 3xx chokepoint