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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (460) hide show
  1. package/AGENTS.md +17 -0
  2. package/README.md +432 -7
  3. package/dist/bin/rango.js +2073 -213
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +7258 -2714
  6. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  7. package/package.json +140 -67
  8. package/skills/api-client/SKILL.md +211 -0
  9. package/skills/breadcrumbs/SKILL.md +329 -0
  10. package/skills/bundle-analysis/SKILL.md +159 -0
  11. package/skills/cache-guide/SKILL.md +487 -0
  12. package/skills/caching/SKILL.md +357 -25
  13. package/skills/comparison/SKILL.md +50 -0
  14. package/skills/comparison/agents/openai.yaml +4 -0
  15. package/skills/comparison/references/framework-comparison.md +837 -0
  16. package/skills/composability/SKILL.md +246 -0
  17. package/skills/css/SKILL.md +76 -0
  18. package/skills/debug-manifest/SKILL.md +16 -10
  19. package/skills/document-cache/SKILL.md +87 -62
  20. package/skills/fonts/SKILL.md +6 -4
  21. package/skills/handler-use/SKILL.md +364 -0
  22. package/skills/hooks/SKILL.md +557 -79
  23. package/skills/host-router/SKILL.md +320 -0
  24. package/skills/i18n/SKILL.md +276 -0
  25. package/skills/intercept/SKILL.md +207 -15
  26. package/skills/layout/SKILL.md +146 -6
  27. package/skills/links/SKILL.md +304 -25
  28. package/skills/loader/SKILL.md +616 -54
  29. package/skills/middleware/SKILL.md +217 -37
  30. package/skills/migrate-nextjs/SKILL.md +611 -0
  31. package/skills/migrate-react-router/SKILL.md +927 -0
  32. package/skills/mime-routes/SKILL.md +42 -11
  33. package/skills/observability/SKILL.md +194 -0
  34. package/skills/parallel/SKILL.md +284 -3
  35. package/skills/ppr/SKILL.md +293 -0
  36. package/skills/prerender/SKILL.md +437 -52
  37. package/skills/rango/SKILL.md +369 -22
  38. package/skills/react-compiler/SKILL.md +168 -0
  39. package/skills/response-routes/SKILL.md +263 -121
  40. package/skills/route/SKILL.md +350 -21
  41. package/skills/router-setup/SKILL.md +246 -33
  42. package/skills/scripts/SKILL.md +179 -0
  43. package/skills/server-actions/SKILL.md +775 -0
  44. package/skills/shell-manifest/SKILL.md +185 -0
  45. package/skills/streams-and-websockets/SKILL.md +283 -0
  46. package/skills/tailwind/SKILL.md +27 -3
  47. package/skills/testing/SKILL.md +126 -222
  48. package/skills/testing/bindings.md +103 -0
  49. package/skills/testing/cache-prerender.md +127 -0
  50. package/skills/testing/client-components.md +124 -0
  51. package/skills/testing/e2e-parity.md +125 -0
  52. package/skills/testing/flight.md +91 -0
  53. package/skills/testing/handles.md +131 -0
  54. package/skills/testing/loader.md +128 -0
  55. package/skills/testing/middleware.md +99 -0
  56. package/skills/testing/render-handler.md +122 -0
  57. package/skills/testing/response-routes.md +95 -0
  58. package/skills/testing/reverse-and-types.md +85 -0
  59. package/skills/testing/server-actions.md +107 -0
  60. package/skills/testing/server-tree.md +128 -0
  61. package/skills/testing/setup.md +123 -0
  62. package/skills/theme/SKILL.md +9 -8
  63. package/skills/typesafety/SKILL.md +532 -103
  64. package/skills/use-cache/SKILL.md +367 -0
  65. package/skills/vercel/SKILL.md +128 -0
  66. package/skills/view-transitions/SKILL.md +337 -0
  67. package/src/__augment-tests__/augment.ts +81 -0
  68. package/src/__augment-tests__/augmented.check.ts +116 -0
  69. package/src/__internal.ts +77 -44
  70. package/src/bin/rango.ts +312 -15
  71. package/src/browser/action-coordinator.ts +114 -0
  72. package/src/browser/action-fence.ts +47 -0
  73. package/src/browser/app-shell.ts +39 -0
  74. package/src/browser/app-version.ts +14 -0
  75. package/src/browser/connection-warmup.ts +134 -0
  76. package/src/browser/cookie-name.ts +140 -0
  77. package/src/browser/event-controller.ts +293 -202
  78. package/src/browser/history-state.ts +101 -0
  79. package/src/browser/index.ts +3 -3
  80. package/src/browser/intercept-utils.ts +52 -0
  81. package/src/browser/invalidate-client-cache.ts +52 -0
  82. package/src/browser/link-interceptor.ts +24 -4
  83. package/src/browser/logging.ts +11 -0
  84. package/src/browser/merge-segment-loaders.ts +20 -12
  85. package/src/browser/navigation-bridge.ts +385 -576
  86. package/src/browser/navigation-client.ts +245 -75
  87. package/src/browser/navigation-store-handle.ts +38 -0
  88. package/src/browser/navigation-store.ts +184 -118
  89. package/src/browser/navigation-transaction.ts +247 -0
  90. package/src/browser/network-error-handler.ts +88 -0
  91. package/src/browser/partial-update.ts +412 -364
  92. package/src/browser/prefetch/cache.ts +359 -0
  93. package/src/browser/prefetch/fetch.ts +452 -0
  94. package/src/browser/prefetch/observer.ts +65 -0
  95. package/src/browser/prefetch/policy.ts +48 -0
  96. package/src/browser/prefetch/queue.ts +209 -0
  97. package/src/browser/prefetch/resource-ready.ts +77 -0
  98. package/src/browser/rango-state.ts +194 -0
  99. package/src/browser/react/Link.tsx +275 -68
  100. package/src/browser/react/NavigationProvider.tsx +265 -109
  101. package/src/browser/react/ScrollRestoration.tsx +10 -6
  102. package/src/browser/react/context.ts +11 -0
  103. package/src/browser/react/filter-segment-order.ts +70 -0
  104. package/src/browser/react/index.ts +0 -48
  105. package/src/browser/react/location-state-shared.ts +272 -60
  106. package/src/browser/react/location-state.ts +90 -20
  107. package/src/browser/react/mount-context.ts +6 -1
  108. package/src/browser/react/nonce-context.ts +23 -0
  109. package/src/browser/react/shallow-equal.ts +27 -0
  110. package/src/browser/react/use-action.ts +35 -66
  111. package/src/browser/react/use-handle.ts +39 -126
  112. package/src/browser/react/use-href.tsx +8 -1
  113. package/src/browser/react/use-link-status.ts +39 -13
  114. package/src/browser/react/use-navigation.ts +53 -69
  115. package/src/browser/react/use-params.ts +75 -0
  116. package/src/browser/react/use-pathname.ts +47 -0
  117. package/src/browser/react/use-reverse.ts +106 -0
  118. package/src/browser/react/use-router.ts +98 -0
  119. package/src/browser/react/use-search-params.ts +51 -0
  120. package/src/browser/react/use-segments.ts +72 -99
  121. package/src/browser/response-adapter.ts +164 -0
  122. package/src/browser/rsc-router.tsx +300 -72
  123. package/src/browser/scroll-restoration.ts +138 -50
  124. package/src/browser/segment-reconciler.ts +243 -0
  125. package/src/browser/segment-structure-assert.ts +17 -1
  126. package/src/browser/server-action-bridge.ts +668 -613
  127. package/src/browser/types.ts +223 -51
  128. package/src/browser/validate-redirect-origin.ts +56 -0
  129. package/src/build/collect-fallback-refs.ts +107 -0
  130. package/src/build/generate-manifest.ts +252 -161
  131. package/src/build/generate-route-types.ts +41 -1038
  132. package/src/build/index.ts +12 -7
  133. package/src/build/prefix-tree-utils.ts +123 -0
  134. package/src/build/route-trie.ts +225 -42
  135. package/src/build/route-types/ast-helpers.ts +25 -0
  136. package/src/build/route-types/ast-route-extraction.ts +105 -0
  137. package/src/build/route-types/codegen.ts +113 -0
  138. package/src/build/route-types/include-resolution.ts +812 -0
  139. package/src/build/route-types/param-extraction.ts +51 -0
  140. package/src/build/route-types/per-module-writer.ts +144 -0
  141. package/src/build/route-types/router-processing.ts +695 -0
  142. package/src/build/route-types/scan-filter.ts +85 -0
  143. package/src/build/route-types/source-scan.ts +216 -0
  144. package/src/build/runtime-discovery.ts +223 -0
  145. package/src/cache/background-task.ts +34 -0
  146. package/src/cache/cache-error.ts +104 -0
  147. package/src/cache/cache-key-utils.ts +60 -0
  148. package/src/cache/cache-policy.ts +199 -0
  149. package/src/cache/cache-runtime.ts +525 -0
  150. package/src/cache/cache-scope.ts +298 -332
  151. package/src/cache/cache-tag.ts +103 -0
  152. package/src/cache/cf/cf-base64.ts +33 -0
  153. package/src/cache/cf/cf-cache-constants.ts +127 -0
  154. package/src/cache/cf/cf-cache-store.ts +2508 -158
  155. package/src/cache/cf/cf-cache-types.ts +349 -0
  156. package/src/cache/cf/cf-kv-utils.ts +46 -0
  157. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  158. package/src/cache/cf/index.ts +17 -17
  159. package/src/cache/document-cache.ts +199 -92
  160. package/src/cache/handle-capture.ts +81 -0
  161. package/src/cache/handle-snapshot.ts +111 -0
  162. package/src/cache/index.ts +24 -35
  163. package/src/cache/memory-segment-store.ts +363 -30
  164. package/src/cache/profile-registry.ts +88 -0
  165. package/src/cache/read-through-swr.ts +178 -0
  166. package/src/cache/segment-codec.ts +248 -0
  167. package/src/cache/shell-snapshot.ts +368 -0
  168. package/src/cache/tag-invalidation.ts +230 -0
  169. package/src/cache/taint.ts +153 -0
  170. package/src/cache/types.ts +222 -211
  171. package/src/cache/vercel/index.ts +11 -0
  172. package/src/cache/vercel/vercel-cache-store.ts +1113 -0
  173. package/src/client.rsc.tsx +43 -21
  174. package/src/client.tsx +131 -347
  175. package/src/cloudflare/index.ts +11 -0
  176. package/src/cloudflare/tracing.ts +109 -0
  177. package/src/component-utils.ts +23 -4
  178. package/src/components/DefaultDocument.tsx +13 -3
  179. package/src/context-var.ts +168 -0
  180. package/src/debug.ts +19 -9
  181. package/src/decode-loader-results.ts +52 -0
  182. package/src/defer.ts +185 -0
  183. package/src/deps/ssr.ts +0 -1
  184. package/src/encode-kv.ts +49 -0
  185. package/src/errors.ts +106 -10
  186. package/src/escape-script.ts +52 -0
  187. package/src/handle.ts +110 -35
  188. package/src/handles/MetaTags.tsx +83 -59
  189. package/src/handles/Scripts.tsx +183 -0
  190. package/src/handles/breadcrumbs.ts +93 -0
  191. package/src/handles/deferred-resolution.ts +127 -0
  192. package/src/handles/is-thenable.ts +18 -0
  193. package/src/handles/meta.ts +44 -53
  194. package/src/handles/script.ts +244 -0
  195. package/src/host/cookie-handler.ts +20 -65
  196. package/src/host/errors.ts +21 -30
  197. package/src/host/index.ts +13 -9
  198. package/src/host/pattern-matcher.ts +50 -79
  199. package/src/host/router.ts +151 -121
  200. package/src/host/testing.ts +45 -32
  201. package/src/host/types.ts +52 -11
  202. package/src/host/utils.ts +2 -2
  203. package/src/href-client.ts +192 -57
  204. package/src/index.rsc.ts +173 -35
  205. package/src/index.ts +241 -73
  206. package/src/internal-debug.ts +9 -2
  207. package/src/loader-store.ts +500 -0
  208. package/src/loader.rsc.ts +31 -99
  209. package/src/loader.ts +30 -12
  210. package/src/missing-id-error.ts +68 -0
  211. package/src/outlet-context.ts +1 -1
  212. package/src/outlet-provider.tsx +41 -0
  213. package/src/prerender/param-hash.ts +16 -14
  214. package/src/prerender/store.ts +121 -21
  215. package/src/prerender.ts +460 -26
  216. package/src/redirect-origin.ts +100 -0
  217. package/src/regex-escape.ts +8 -0
  218. package/src/render-error-thrower.tsx +20 -0
  219. package/src/response-utils.ts +62 -0
  220. package/src/reverse.ts +198 -128
  221. package/src/root-error-boundary.tsx +42 -48
  222. package/src/route-content-wrapper.tsx +22 -77
  223. package/src/route-definition/dsl-helpers.ts +1116 -0
  224. package/src/route-definition/helper-factories.ts +88 -0
  225. package/src/route-definition/helpers-types.ts +505 -0
  226. package/src/route-definition/index.ts +54 -0
  227. package/src/route-definition/redirect.ts +134 -0
  228. package/src/route-definition/resolve-handler-use.ts +160 -0
  229. package/src/route-definition/use-item-types.ts +29 -0
  230. package/src/route-definition.ts +1 -1481
  231. package/src/route-map-builder.ts +82 -144
  232. package/src/route-name.ts +53 -0
  233. package/src/route-types.ts +71 -45
  234. package/src/router/basename.ts +14 -0
  235. package/src/router/content-negotiation.ts +263 -0
  236. package/src/router/debug-manifest.ts +72 -0
  237. package/src/router/error-handling.ts +54 -27
  238. package/src/router/find-match.ts +245 -0
  239. package/src/router/handler-context.ts +377 -125
  240. package/src/router/instrument.ts +350 -0
  241. package/src/router/intercept-resolution.ts +59 -28
  242. package/src/router/lazy-includes.ts +254 -0
  243. package/src/router/loader-resolution.ts +421 -157
  244. package/src/router/logging.ts +106 -6
  245. package/src/router/manifest.ts +131 -57
  246. package/src/router/match-api.ts +167 -246
  247. package/src/router/match-context.ts +4 -24
  248. package/src/router/match-handlers.ts +440 -0
  249. package/src/router/match-middleware/background-revalidation.ts +117 -93
  250. package/src/router/match-middleware/cache-lookup.ts +297 -150
  251. package/src/router/match-middleware/cache-store.ts +123 -51
  252. package/src/router/match-middleware/intercept-resolution.ts +44 -43
  253. package/src/router/match-middleware/segment-resolution.ts +64 -22
  254. package/src/router/match-pipelines.ts +11 -87
  255. package/src/router/match-result.ts +121 -50
  256. package/src/router/metrics.ts +219 -28
  257. package/src/router/middleware-types.ts +93 -0
  258. package/src/router/middleware.ts +505 -441
  259. package/src/router/navigation-snapshot.ts +133 -0
  260. package/src/router/params-util.ts +23 -0
  261. package/src/router/parse-pattern.ts +115 -0
  262. package/src/router/pattern-matching.ts +311 -142
  263. package/src/router/prefetch-cache-ttl.ts +51 -0
  264. package/src/router/prefetch-limits.ts +37 -0
  265. package/src/router/prerender-match.ts +547 -0
  266. package/src/router/preview-match.ts +102 -0
  267. package/src/router/request-classification.ts +278 -0
  268. package/src/router/revalidation.ts +203 -62
  269. package/src/router/route-snapshot.ts +246 -0
  270. package/src/router/router-context.ts +45 -48
  271. package/src/router/router-interfaces.ts +554 -0
  272. package/src/router/router-options.ts +779 -0
  273. package/src/router/router-registry.ts +21 -0
  274. package/src/router/segment-resolution/fresh.ts +772 -0
  275. package/src/router/segment-resolution/helpers.ts +348 -0
  276. package/src/router/segment-resolution/loader-cache.ts +250 -0
  277. package/src/router/segment-resolution/loader-mask.ts +44 -0
  278. package/src/router/segment-resolution/revalidation.ts +1331 -0
  279. package/src/router/segment-resolution/static-store.ts +81 -0
  280. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  281. package/src/router/segment-resolution/view-transition-default.ts +56 -0
  282. package/src/router/segment-resolution.ts +25 -1354
  283. package/src/router/segment-wrappers.ts +292 -0
  284. package/src/router/state-cookie-name.ts +33 -0
  285. package/src/router/substitute-pattern-params.ts +75 -0
  286. package/src/router/telemetry-otel.ts +261 -0
  287. package/src/router/telemetry.ts +377 -0
  288. package/src/router/timeout.ts +128 -0
  289. package/src/router/tracing.ts +206 -0
  290. package/src/router/trie-matching.ts +240 -61
  291. package/src/router/types.ts +23 -70
  292. package/src/router/url-params.ts +57 -0
  293. package/src/router.ts +781 -2378
  294. package/src/rsc/full-payload.ts +70 -0
  295. package/src/rsc/handler-context.ts +46 -0
  296. package/src/rsc/handler.ts +905 -1142
  297. package/src/rsc/helpers.ts +275 -19
  298. package/src/rsc/index.ts +2 -25
  299. package/src/rsc/json-route-result.ts +38 -0
  300. package/src/rsc/loader-fetch.ts +305 -0
  301. package/src/rsc/manifest-init.ts +77 -0
  302. package/src/rsc/nonce.ts +14 -0
  303. package/src/rsc/origin-guard.ts +155 -0
  304. package/src/rsc/progressive-enhancement.ts +502 -0
  305. package/src/rsc/redirect-guard.ts +99 -0
  306. package/src/rsc/response-cache-serve.ts +238 -0
  307. package/src/rsc/response-error.ts +104 -0
  308. package/src/rsc/response-route-handler.ts +257 -0
  309. package/src/rsc/rsc-rendering.ts +527 -0
  310. package/src/rsc/runtime-warnings.ts +55 -0
  311. package/src/rsc/server-action.ts +522 -0
  312. package/src/rsc/shell-capture.ts +897 -0
  313. package/src/rsc/shell-serve.ts +124 -0
  314. package/src/rsc/ssr-setup.ts +144 -0
  315. package/src/rsc/transition-gate.ts +89 -0
  316. package/src/rsc/types.ts +95 -12
  317. package/src/runtime-env.ts +18 -0
  318. package/src/search-params.ts +99 -82
  319. package/src/segment-content-promise.ts +67 -0
  320. package/src/segment-loader-promise.ts +149 -0
  321. package/src/segment-system.tsx +349 -134
  322. package/src/serialize.ts +243 -0
  323. package/src/server/context.ts +459 -85
  324. package/src/server/cookie-parse.ts +32 -0
  325. package/src/server/cookie-store.ts +310 -0
  326. package/src/server/fetchable-loader-store.ts +11 -6
  327. package/src/server/handle-store.ts +123 -42
  328. package/src/server/loader-registry.ts +51 -100
  329. package/src/server/request-context.ts +848 -157
  330. package/src/server.ts +15 -8
  331. package/src/ssr/index.tsx +443 -135
  332. package/src/ssr/ssr-root.tsx +228 -0
  333. package/src/static-handler.ts +45 -18
  334. package/src/testing/cache-status.ts +162 -0
  335. package/src/testing/collect-handle.ts +46 -0
  336. package/src/testing/dispatch.ts +701 -0
  337. package/src/testing/dom.entry.ts +22 -0
  338. package/src/testing/e2e/fixture.ts +188 -0
  339. package/src/testing/e2e/index.ts +128 -0
  340. package/src/testing/e2e/matchers.ts +35 -0
  341. package/src/testing/e2e/page-helpers.ts +272 -0
  342. package/src/testing/e2e/parity.ts +387 -0
  343. package/src/testing/e2e/server.ts +195 -0
  344. package/src/testing/flight-matchers.ts +97 -0
  345. package/src/testing/flight-normalize.ts +11 -0
  346. package/src/testing/flight-runtime.d.ts +57 -0
  347. package/src/testing/flight-tree.ts +682 -0
  348. package/src/testing/flight.entry.ts +52 -0
  349. package/src/testing/flight.ts +257 -0
  350. package/src/testing/generated-routes.ts +199 -0
  351. package/src/testing/index.ts +105 -0
  352. package/src/testing/internal/context.ts +371 -0
  353. package/src/testing/internal/flight-client-globals.ts +30 -0
  354. package/src/testing/internal/seed-vars.ts +54 -0
  355. package/src/testing/render-handler.ts +357 -0
  356. package/src/testing/render-route.tsx +584 -0
  357. package/src/testing/run-loader.ts +385 -0
  358. package/src/testing/run-middleware.ts +205 -0
  359. package/src/testing/run-transition-when.ts +164 -0
  360. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  361. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  362. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  363. package/src/testing/vitest-stubs/version.ts +5 -0
  364. package/src/testing/vitest.ts +305 -0
  365. package/src/theme/ThemeProvider.tsx +76 -98
  366. package/src/theme/ThemeScript.tsx +12 -14
  367. package/src/theme/constants.ts +57 -15
  368. package/src/theme/index.ts +3 -20
  369. package/src/theme/theme-context.ts +5 -35
  370. package/src/theme/theme-script.ts +43 -39
  371. package/src/theme/use-theme.ts +0 -3
  372. package/src/types/boundaries.ts +123 -0
  373. package/src/types/cache-types.ts +207 -0
  374. package/src/types/error-types.ts +132 -0
  375. package/src/types/global-namespace.ts +113 -0
  376. package/src/types/handler-context.ts +839 -0
  377. package/src/types/index.ts +81 -0
  378. package/src/types/loader-types.ts +212 -0
  379. package/src/types/request-scope.ts +112 -0
  380. package/src/types/route-config.ts +138 -0
  381. package/src/types/route-entry.ts +114 -0
  382. package/src/types/segments.ts +271 -0
  383. package/src/types.ts +1 -1795
  384. package/src/urls/include-helper.ts +162 -0
  385. package/src/urls/include-provider.ts +71 -0
  386. package/src/urls/index.ts +44 -0
  387. package/src/urls/path-helper-types.ts +413 -0
  388. package/src/urls/path-helper.ts +280 -0
  389. package/src/urls/pattern-types.ts +160 -0
  390. package/src/urls/response-types.ts +109 -0
  391. package/src/urls/type-extraction.ts +316 -0
  392. package/src/urls/urls-function.ts +80 -0
  393. package/src/urls.ts +1 -1341
  394. package/src/use-loader.tsx +406 -141
  395. package/src/vercel/index.ts +11 -0
  396. package/src/vercel/tracing.ts +88 -0
  397. package/src/vite/debug.ts +185 -0
  398. package/src/vite/discovery/bundle-postprocess.ts +182 -0
  399. package/src/vite/discovery/discover-routers.ts +389 -0
  400. package/src/vite/discovery/discovery-errors.ts +255 -0
  401. package/src/vite/discovery/gate-state.ts +171 -0
  402. package/src/vite/discovery/prerender-collection.ts +467 -0
  403. package/src/vite/discovery/route-types-writer.ts +214 -0
  404. package/src/vite/discovery/self-gen-tracking.ts +73 -0
  405. package/src/vite/discovery/state.ts +161 -0
  406. package/src/vite/discovery/virtual-module-codegen.ts +183 -0
  407. package/src/vite/index.ts +23 -2255
  408. package/src/vite/inject-client-debug.ts +36 -0
  409. package/src/vite/plugin-types.ts +303 -0
  410. package/src/vite/plugins/cjs-to-esm.ts +90 -0
  411. package/src/vite/plugins/client-ref-dedup.ts +120 -0
  412. package/src/vite/plugins/client-ref-hashing.ts +118 -0
  413. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  414. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  415. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  416. package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +88 -110
  417. package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +89 -79
  418. package/src/vite/plugins/expose-ids/export-analysis.ts +363 -0
  419. package/src/vite/plugins/expose-ids/handler-transform.ts +130 -0
  420. package/src/vite/plugins/expose-ids/loader-transform.ts +64 -0
  421. package/src/vite/plugins/expose-ids/router-transform.ts +199 -0
  422. package/src/vite/plugins/expose-ids/types.ts +45 -0
  423. package/src/vite/plugins/expose-internal-ids.ts +805 -0
  424. package/src/vite/plugins/performance-tracks.ts +89 -0
  425. package/src/vite/plugins/refresh-cmd.ts +127 -0
  426. package/src/vite/plugins/use-cache-transform.ts +313 -0
  427. package/src/vite/plugins/vercel-output.ts +384 -0
  428. package/src/vite/plugins/version-injector.ts +94 -0
  429. package/src/vite/plugins/version-plugin.ts +263 -0
  430. package/src/vite/plugins/virtual-entries.ts +234 -0
  431. package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
  432. package/src/vite/rango.ts +560 -0
  433. package/src/vite/router-discovery.ts +1638 -0
  434. package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +200 -37
  435. package/src/vite/utils/banner.ts +36 -0
  436. package/src/vite/utils/bundle-analysis.ts +132 -0
  437. package/src/vite/utils/client-chunks.ts +184 -0
  438. package/src/vite/utils/directive-prologue.ts +40 -0
  439. package/src/vite/utils/forward-user-plugins.ts +171 -0
  440. package/src/vite/utils/manifest-utils.ts +15 -0
  441. package/src/vite/utils/package-resolution.ts +89 -0
  442. package/src/vite/utils/prerender-utils.ts +249 -0
  443. package/src/vite/utils/shared-utils.ts +269 -0
  444. package/CLAUDE.md +0 -43
  445. package/dist/vite/index.named-routes.gen.ts +0 -103
  446. package/src/browser/lru-cache.ts +0 -69
  447. package/src/browser/react/use-client-cache.ts +0 -56
  448. package/src/browser/request-controller.ts +0 -164
  449. package/src/browser/shallow.ts +0 -35
  450. package/src/cache/memory-store.ts +0 -253
  451. package/src/handles/index.ts +0 -6
  452. package/src/href-context.ts +0 -33
  453. package/src/network-error-thrower.tsx +0 -21
  454. package/src/router.gen.ts +0 -6
  455. package/src/static-handler.gen.ts +0 -5
  456. package/src/urls.gen.ts +0 -8
  457. package/src/vite/expose-internal-ids.ts +0 -1167
  458. package/src/vite/package-resolution.ts +0 -125
  459. package/src/vite/virtual-entries.ts +0 -114
  460. /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
@@ -0,0 +1,293 @@
1
+ ---
2
+ name: ppr
3
+ description: PPR shell caching — opt a page route in with the `ppr` path option; the router serves the cached HTML shell instantly and resumes the live holes
4
+ argument-hint: "[setup]"
5
+ ---
6
+
7
+ # PPR Shell Caching
8
+
9
+ Caches the rendered HTML **shell** of a page route (React `prerender` prelude
10
+ bytes plus `postponed` state) and, on a later request, flushes those bytes
11
+ before any render work happens, then resumes fizz for just the live holes. The
12
+ browser sees one ordinary streamed document; loaders stay fresh on every
13
+ request. This is the second render axis — the default axis-1 path is untouched,
14
+ and every ineligible request falls open to it.
15
+
16
+ Compare `/document-cache`, which freezes the WHOLE response including loader
17
+ output. Shell caching is for pages that mix a stable shell with live data: the
18
+ shell is shared per host+URL, the holes are per request.
19
+
20
+ ## Setup: one path option, no middleware
21
+
22
+ PPR is a DOCUMENT-level property declared on the page route via the `ppr` path
23
+ option. Serving is **integral to the router** — there is nothing to mount. The
24
+ only prerequisite is an app-level `createRouter({ cache })` store that
25
+ implements the shell family (`getShell`/`putShell`): `MemorySegmentCacheStore`
26
+ (dev/tests), `CFCacheStore` (Cloudflare KV), or `VercelCacheStore` (runtime
27
+ cache). A ppr route on a store without the family stays on axis 1 with a
28
+ once-per-key warning.
29
+
30
+ ```typescript
31
+ import { createRouter, urls } from "@rangojs/router";
32
+ import { CFCacheStore } from "@rangojs/router/cache";
33
+
34
+ export const urlpatterns = urls(({ path, layout, loader, loading }) => [
35
+ layout(ProductShell, () => [
36
+ path(
37
+ "/products/:id",
38
+ PricePage,
39
+ // `ppr` is the whole opt-in AND the policy. `ppr: true` uses the default
40
+ // ttl (300s); an object sets ttl/swr/tags (PartialPrerenderProps).
41
+ { name: "product", ppr: { ttl: 600, swr: 120 } },
42
+ () => [
43
+ loader(LivePriceLoader),
44
+ loading(<PriceSkeleton />), // the structural hole boundary
45
+ ],
46
+ ),
47
+ ]),
48
+ ]);
49
+
50
+ const router = createRouter<AppBindings>({
51
+ document: Document,
52
+ urls: urlpatterns,
53
+ cache: (env, ctx) => ({
54
+ store: new CFCacheStore({ kv: env.CACHE_KV, ctx: ctx! }),
55
+ }),
56
+ });
57
+ export default router;
58
+ ```
59
+
60
+ A route WITHOUT the `ppr` option is pure axis 1: no store read, no capture, no
61
+ logs, zero cost. `ppr` is per page route — declaring it on a layout is not
62
+ supported (subtree inheritance is a possible follow-up).
63
+
64
+ ## Where PPR sits: the cache onion
65
+
66
+ Rango's caches layer like an onion — each ring stores a progressively more
67
+ "cooked" representation of the same page. From innermost (raw values) to
68
+ outermost (final bytes):
69
+
70
+ | Ring | Primitive | What is stored | What stays live on a hit |
71
+ | ----------------------- | ---------------------------------------- | -------------------------------------------------- | -------------------------------------- |
72
+ | 1. Function values | `"use cache"` | a function's return value | everything around the call |
73
+ | 2. Loader values | `loader(Fn, () => [cache({...})])` | one loader's result (opt-in; loaders default live) | all other loaders, handlers, rendering |
74
+ | 3. Segments (Flight) | `cache()` route / build-time `prerender` | serialized rendered segments + replayed handles | loaders, HTML render |
75
+ | 4. **HTML shell (PPR)** | `ppr` path option | rendered prelude bytes + React postponed state | the holes, hydration payload |
76
+ | 5. Whole response | `/document-cache` | final response bytes, headers included | nothing — all-or-nothing |
77
+
78
+ PPR is ORTHOGONAL to `cache()` (ring 3): a ppr route may be uncached (its
79
+ handlers run fresh on every serve and during capture), fully `cache()`d (its
80
+ segments replay), or mixed. One useful cache() property to know: the segment
81
+ codec **deep-settles promises at the ring-3 write**, so nothing inside a
82
+ `cache()` boundary can stay live — that is a cache() fact, not a ppr one.
83
+
84
+ Invalidation crosses rings: `updateTag()`/`revalidateTag()` reach segment,
85
+ shell, loader, and item entries in the same store, and shell entries
86
+ additionally self-invalidate on `React.version` change.
87
+
88
+ ## The serve pipeline: commit after ALL middleware
89
+
90
+ On a document GET to a ppr route the router runs:
91
+
92
+ 1. **match** — route identified, `ppr` config read from the matched route;
93
+ 2. **the WHOLE middleware chain** — the global `router.use()` chain AND route
94
+ DSL `middleware()`; both are guards, and the COMMIT POINT is after all of
95
+ them: any rejection/redirect/401 wins before a single shell byte, on MISS
96
+ and on a warmed HIT alike;
97
+ 3. **shell lookup** — `getShell(key)` on the app store (key =
98
+ host+pathname+sorted search);
99
+ 4. **HIT** — the composed response is committed immediately: the stored prelude
100
+ bytes flush first, while segment resolution, the fresh Flight render (the
101
+ full hydration payload — there is no Flight-side resume), and the fizz
102
+ `resume` of just the holes run BEHIND them inside the response stream;
103
+ 5. **MISS** — plain axis-1 serve, tagged `x-rango-shell: MISS`, plus a
104
+ background capture (stampede-guarded, retry-in-place, exponential backoff).
105
+
106
+ `x-rango-shell: HIT | MISS` is the observability header. Because the commit
107
+ point is after the chain, an unauthorized request NEVER sees shell bytes — put
108
+ auth middleware anywhere (global or route DSL) and it guards PPR for free.
109
+
110
+ ## The hole doctrine (encode this in your head)
111
+
112
+ Holes are **render-defined**, decided by the shape of the tree, on three rules:
113
+
114
+ | Class | What makes the hole | At capture | At serve |
115
+ | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------- |
116
+ | **STRUCTURAL** | the ENTIRE segment subtree under a `loading()` registration | loaders masked; the LoaderBoundary postpones; the fallback bakes in as route structure | loaders run fresh; resume fills it |
117
+ | **PHYSICS** | any promise NESTED in handed-over data still pending at capture, under the consumer's own `<Suspense>` — handler props, handle containers (`push({ x: promise })`), loader-carried | real I/O cannot win the task-quantized quiet window; the boundary postpones | the promise settles and streams in |
118
+ | **SHELL** | awaited handler data, TOP-LEVEL `push(promise)` (awaited before SSR), resolved promises, replayed `cache()` segments | baked into the prelude | served from the frozen prelude |
119
+
120
+ The unified rule for promises: **a promise nested inside your data is never
121
+ baked; the container settles.** The one asymmetry to remember versus loaders: a
122
+ LOADER container is a hole via `loading()` (the whole loader value is live),
123
+ while a HANDLE container is shell via root consumption (the handles generator
124
+ is drained before SSR) — only the promises nested inside it stay live.
125
+
126
+ ### Handles: "nesting = liveness"
127
+
128
+ - `ctx.use(H)(promise)` — a TOP-LEVEL pushed promise is awaited server-side
129
+ before SSR (`resolvedHandleStream`) and BAKED into the shell. The capture
130
+ gate is held open for the same await, so real latency here is safe (bounded
131
+ by the capture's 5s guard).
132
+ - `ctx.use(H)({ x: promise })` — the container passes through verbatim
133
+ (resolution is shallow); the nested promise streams to the consumer, who must
134
+ `<Suspense>` it. Under capture that boundary postpones — a hole.
135
+
136
+ ### Want a hole for already-resolved data?
137
+
138
+ Put it in a loader: `loader(() => Promise.resolve(x))` + `loading()`. Loaders
139
+ are always the live lane — masked at capture, fresh on every serve — no matter
140
+ how fast the value settles.
141
+
142
+ ### The structural negative: a loader route without loading()
143
+
144
+ The loading-less branch awaits loader data at TREE-BUILD, above every Suspense
145
+ boundary, so under capture's masked loaders the whole tree pins above `<body>`,
146
+ the prelude comes back trivial, and the sanity gate refuses to store. Observable
147
+ symptom: `x-rango-shell: MISS` forever plus a once-per-key worker warning. Add
148
+ `loading()` to the loader route and keep shell material in a layout.
149
+
150
+ ## Execution matrix
151
+
152
+ | Phase | MISS (foreground) | Background capture | HIT (foreground) |
153
+ | ---------------- | ---------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------- |
154
+ | Middleware chain | runs (full) | **NOT re-run** — inherits the request's post-middleware context | runs (full) — commit point is after it |
155
+ | `router.match` | runs | re-runs under a derived context | runs (behind the flushed prelude) |
156
+ | Handlers | run | run on UNCACHED segments; `cache()`d segments replay (mixed-chain) | run (same mixed-chain rules as any render) |
157
+ | Loaders | run **fresh** | **MASKED** (never execute) — the structural holes | run **fresh** |
158
+ | Flight render | full | full | full (hydration needs the whole payload — no Flight resume) |
159
+ | HTML production | full fizz | `prerender` + abort → prelude + postponed | `resume` only the holes — O(paths to holes) |
160
+ | Shell store | schedules a bg capture | `putShell(key, …)` | `getShell(key)`; a stale/SWR hit also schedules a recapture |
161
+ | Prelude bytes | — | — | flushed FIRST, before segment resolution starts |
162
+
163
+ Middleware is not re-run during capture because it already ran for the
164
+ triggering request — the capture's derived context inherits the
165
+ post-middleware state (`ctx` variables included, which is what makes
166
+ middleware-derived shell content photograph correctly). Guarding is
167
+ serve-time: the commit point runs the full chain on EVERY serve.
168
+
169
+ Because handlers on uncached segments EXECUTE during capture, the
170
+ `cookies()`/`headers()` capture guard is load-bearing: those reads THROW during
171
+ a capture render (`assertNotInsideShellCapture`), so identity can never leak
172
+ into a shared shell through them. Loaders are exempt (always fresh).
173
+
174
+ ## allReady: the SEO/bot story
175
+
176
+ `ssr: { resolveStreaming: ... }` returning `"allReady"` (e.g. for bot user
177
+ agents) bypasses PPR entirely — the request gets one complete, fully-buffered
178
+ axis-1 document. Crawlers that dislike streamed shells get a finished page;
179
+ regular users get the streamed shell. No configuration interaction: allReady
180
+ wins.
181
+
182
+ ## Security
183
+
184
+ Shell caching shares one shell per host+URL across all users:
185
+
186
+ **(a) Access control is sound by construction.** The commit point is after ALL
187
+ middleware on every serve. A 401/redirect short-circuit returns before any
188
+ shell byte.
189
+
190
+ **(b) Identity can't leak via cookies/headers.** `cookies()` and `headers()`
191
+ THROW during the background capture render. A shell that reads them is
192
+ PPR-ineligible by construction.
193
+
194
+ **(c) Residual hazard — middleware-derived per-user state.** A `ctx` variable
195
+ set by an upstream auth middleware and rendered by shell material is
196
+ photographed into the SHARED shell (the capture inherits post-middleware
197
+ state). That is scope fidelity working as designed — for shared values. If the
198
+ value is per-user: shell-cache only public/shared pages, put per-user content
199
+ in loaders, or key per variant at the CDN tier.
200
+
201
+ ## What always stays on axis 1
202
+
203
+ Non-GET, RSC/partial/action/loader fetches, per-request CSP nonce,
204
+ `streamMode: "allReady"`, redirects, 404s, error renders, routes without `ppr`,
205
+ and any store without the shell family. A stored shell is invalidated when
206
+ `React.version` changes (postponed state is build-coupled), so deploys
207
+ self-heal via recapture.
208
+
209
+ ## Options: PartialPrerenderProps
210
+
211
+ ```typescript
212
+ path("/products/:id", Page, { name: "product", ppr: true }, use);
213
+ path(
214
+ "/products/:id",
215
+ Page,
216
+ { name: "product", ppr: { ttl: 600, swr: 120, tags: ["catalog"] } },
217
+ use,
218
+ );
219
+ ```
220
+
221
+ | Field | Default | Notes |
222
+ | ------ | ------- | -------------------------------------------------------------------------------------------------- |
223
+ | `ttl` | `300` | shell freshness window in seconds (`ppr: true` uses the default) |
224
+ | `swr` | — | stale window: serve the stale shell + background recapture |
225
+ | `tags` | — | operational tags UNIONED with the tags the capture render auto-collects — see "Invalidation" below |
226
+
227
+ The shell store is always the app-level `createRouter({ cache })` store; the
228
+ default key is `${host}${pathname}${sortedSearch}:shell` (host-scoped so
229
+ multi-tenant shells never collide).
230
+
231
+ ## Invalidation: tags vs revalidate()
232
+
233
+ `updateTag()`/`revalidateTag()` is the ONLY lever that changes the frozen shell
234
+ HTML; `revalidate()` is a DATA lever that never touches it.
235
+
236
+ A captured shell auto-carries the UNION of the non-loader tags recorded during
237
+ the capture render — every `cacheTag(...)` from a `"use cache"` function or
238
+ `cache()` segment that ran as shell material. Loader tags never attach (the
239
+ holes are already live). `ppr.tags` adds operational tags the render cannot
240
+ know (a tenant id, a deploy marker).
241
+
242
+ | Lever | Reaches the frozen shell? | Reaches the holes? |
243
+ | --------------------------------------------- | ------------------------------------------------------------- | --------------------------------------------------- |
244
+ | `updateTag` / `revalidateTag` on a SHELL tag | YES — drops the shell → MISS → recapture | n/a (holes are already live) |
245
+ | `updateTag` / `revalidateTag` on a LOADER tag | no — loader tags never attach to a shell | drops that loader's cached value (if it `cache()`s) |
246
+ | `revalidate()` (named revalidation contract) | **no** — re-runs segments/loaders for the PAYLOAD, never HTML | yes — the hole re-renders with fresh data |
247
+
248
+ ## Pitfalls
249
+
250
+ - **Loader route without `loading()`**: eternal MISS plus a once-per-key
251
+ console warning (see "The structural negative").
252
+ - **Per-user value in shell material**: baked into the shared shell —
253
+ deterministically, not by race (handler promises deep-settle at the ring-3
254
+ write on cached chains; awaited/resolved values bake everywhere). Put
255
+ per-user data in a loader.
256
+ - **Theme on a HIT is capture-then-corrected**: the resume tree replays the
257
+ CAPTURE's `initialTheme` (resume requires it to match the frozen prelude);
258
+ the visitor's cookie theme is applied pre-paint by the FOUC script and
259
+ re-synced post-mount by ThemeProvider. Nothing to configure — but a themed
260
+ component in the shell may briefly render the captured theme's markup before
261
+ the post-mount re-sync.
262
+ - **Shell shows CAPTURE-time data for the shell's lifetime**: a `cache()`/`"use
263
+ cache"` value baked into the shell is PINNED at capture (the capture data
264
+ snapshot) and replayed on every HIT, so the shell stays byte-identical to the
265
+ frozen prelude even after that cache entry expires, gets recomputed, or is
266
+ tag-invalidated. This is deliberate — parity beats freshness inside the shell.
267
+ If a shell region needs to be fresh, put it under a `loading()` hole (holes are
268
+ never pinned) or make the SHELL itself invalidatable by adding the tag to
269
+ `ppr.tags`. Ring-1/ring-3 tag invalidation does NOT drop the shell.
270
+ - **Uncached nondeterminism in the shell is a hydration hazard**: a raw
271
+ `Date.now()` / `Math.random()` / uncached `fetch` rendered directly in shell
272
+ material (outside any cache ring) drifts between capture and hit and the
273
+ snapshot CANNOT pin it — it was never a cache read. It will mismatch the frozen
274
+ prelude and detonate hydration. Wrap it in `cache()`/`"use cache"` (then it is
275
+ pinned) or move it under a `loading()` hole.
276
+ - **Stacking with `/document-cache`**: pick one per route — the document cache
277
+ would cache the composite.
278
+ - **Dev + HMR**: works, but edits produce stale shells until TTL/recapture.
279
+ - **Dev cold-start cadence**: expect `MISS -> (in-place retry) -> HIT`. A
280
+ refused capture is negatively cached with an exponential window (1s doubling
281
+ to a 60s cap), so declaring `ppr` on an ineligible route never re-renders it
282
+ on every request.
283
+ - **HIT status is committed at the flush**: a failing hole cannot become a
284
+ 500/redirect after the first shell byte — error UI renders inline via
285
+ Suspense/error boundaries (the same property any streamed SSR page has after
286
+ its shell flushes).
287
+
288
+ ## Related
289
+
290
+ - `/document-cache` — whole-response edge caching (no live holes)
291
+ - `/caching` and `/cache-guide` — segment/function caching (axis 1 data)
292
+ - `/shell-manifest` — replayed handles as cache metadata read by live loaders
293
+ - Design doc: `docs/design/ppr-shell-resume.md` in the package