@rangojs/router 0.0.0-experimental.135c6902 → 0.0.0-experimental.136

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 (404) hide show
  1. package/AGENTS.md +8 -0
  2. package/README.md +245 -49
  3. package/dist/bin/rango.js +440 -133
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +3386 -1111
  6. package/dist/vite/index.js.bak +5448 -0
  7. package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  8. package/package.json +78 -25
  9. package/skills/api-client/SKILL.md +211 -0
  10. package/skills/breadcrumbs/SKILL.md +64 -2
  11. package/skills/bundle-analysis/SKILL.md +159 -0
  12. package/skills/cache-guide/SKILL.md +247 -23
  13. package/skills/caching/SKILL.md +281 -11
  14. package/skills/composability/SKILL.md +27 -3
  15. package/skills/css/SKILL.md +76 -0
  16. package/skills/debug-manifest/SKILL.md +4 -2
  17. package/skills/document-cache/SKILL.md +78 -55
  18. package/skills/handler-use/SKILL.md +364 -0
  19. package/skills/hooks/SKILL.md +250 -30
  20. package/skills/host-router/SKILL.md +83 -23
  21. package/skills/i18n/SKILL.md +276 -0
  22. package/skills/intercept/SKILL.md +87 -18
  23. package/skills/layout/SKILL.md +35 -9
  24. package/skills/links/SKILL.md +249 -17
  25. package/skills/loader/SKILL.md +289 -53
  26. package/skills/middleware/SKILL.md +52 -13
  27. package/skills/migrate-nextjs/SKILL.md +584 -0
  28. package/skills/migrate-react-router/SKILL.md +914 -0
  29. package/skills/mime-routes/SKILL.md +28 -1
  30. package/skills/observability/SKILL.md +172 -0
  31. package/skills/parallel/SKILL.md +144 -7
  32. package/skills/prerender/SKILL.md +172 -125
  33. package/skills/rango/SKILL.md +251 -22
  34. package/skills/react-compiler/SKILL.md +168 -0
  35. package/skills/response-routes/SKILL.md +123 -48
  36. package/skills/route/SKILL.md +101 -5
  37. package/skills/router-setup/SKILL.md +117 -10
  38. package/skills/scripts/SKILL.md +179 -0
  39. package/skills/server-actions/SKILL.md +775 -0
  40. package/skills/streams-and-websockets/SKILL.md +283 -0
  41. package/skills/tailwind/SKILL.md +27 -3
  42. package/skills/testing/SKILL.md +130 -0
  43. package/skills/testing/bindings.md +103 -0
  44. package/skills/testing/cache-prerender.md +127 -0
  45. package/skills/testing/client-components.md +124 -0
  46. package/skills/testing/e2e-parity.md +125 -0
  47. package/skills/testing/flight.md +91 -0
  48. package/skills/testing/handles.md +129 -0
  49. package/skills/testing/loader.md +128 -0
  50. package/skills/testing/middleware.md +99 -0
  51. package/skills/testing/render-handler.md +122 -0
  52. package/skills/testing/response-routes.md +95 -0
  53. package/skills/testing/reverse-and-types.md +84 -0
  54. package/skills/testing/server-actions.md +107 -0
  55. package/skills/testing/server-tree.md +128 -0
  56. package/skills/testing/setup.md +123 -0
  57. package/skills/typesafety/SKILL.md +332 -29
  58. package/skills/use-cache/SKILL.md +57 -14
  59. package/skills/view-transitions/SKILL.md +337 -0
  60. package/src/__augment-tests__/augment.ts +81 -0
  61. package/src/__augment-tests__/augmented.check.ts +116 -0
  62. package/src/__internal.ts +1 -66
  63. package/src/browser/action-coordinator.ts +53 -36
  64. package/src/browser/action-fence.ts +47 -0
  65. package/src/browser/app-shell.ts +39 -0
  66. package/src/browser/app-version.ts +14 -0
  67. package/src/browser/connection-warmup.ts +134 -0
  68. package/src/browser/cookie-name.ts +140 -0
  69. package/src/browser/event-controller.ts +192 -150
  70. package/src/browser/history-state.ts +21 -0
  71. package/src/browser/index.ts +3 -3
  72. package/src/browser/invalidate-client-cache.ts +52 -0
  73. package/src/browser/navigation-bridge.ts +131 -30
  74. package/src/browser/navigation-client.ts +199 -86
  75. package/src/browser/navigation-store-handle.ts +38 -0
  76. package/src/browser/navigation-store.ts +157 -74
  77. package/src/browser/navigation-transaction.ts +9 -59
  78. package/src/browser/network-error-handler.ts +34 -7
  79. package/src/browser/partial-update.ts +174 -109
  80. package/src/browser/prefetch/cache.ts +222 -69
  81. package/src/browser/prefetch/fetch.ts +347 -39
  82. package/src/browser/prefetch/queue.ts +113 -32
  83. package/src/browser/prefetch/resource-ready.ts +77 -0
  84. package/src/browser/rango-state.ts +158 -76
  85. package/src/browser/react/Link.tsx +102 -15
  86. package/src/browser/react/NavigationProvider.tsx +300 -122
  87. package/src/browser/react/ScrollRestoration.tsx +10 -6
  88. package/src/browser/react/context.ts +7 -2
  89. package/src/browser/react/deferred-handle-resolution.ts +75 -0
  90. package/src/browser/react/filter-segment-order.ts +66 -7
  91. package/src/browser/react/index.ts +0 -48
  92. package/src/browser/react/location-state-shared.ts +178 -8
  93. package/src/browser/react/location-state.ts +39 -14
  94. package/src/browser/react/use-action.ts +6 -15
  95. package/src/browser/react/use-handle.ts +23 -69
  96. package/src/browser/react/use-href.tsx +8 -1
  97. package/src/browser/react/use-link-status.ts +33 -8
  98. package/src/browser/react/use-navigation.ts +32 -7
  99. package/src/browser/react/use-params.ts +20 -10
  100. package/src/browser/react/use-reverse.ts +106 -0
  101. package/src/browser/react/use-router.ts +46 -11
  102. package/src/browser/react/use-search-params.ts +0 -5
  103. package/src/browser/react/use-segments.ts +11 -21
  104. package/src/browser/response-adapter.ts +99 -8
  105. package/src/browser/rsc-router.tsx +125 -28
  106. package/src/browser/scroll-restoration.ts +37 -22
  107. package/src/browser/segment-reconciler.ts +36 -14
  108. package/src/browser/segment-structure-assert.ts +2 -2
  109. package/src/browser/server-action-bridge.ts +222 -61
  110. package/src/browser/types.ts +115 -12
  111. package/src/browser/validate-redirect-origin.ts +43 -16
  112. package/src/build/collect-fallback-refs.ts +107 -0
  113. package/src/build/generate-manifest.ts +65 -40
  114. package/src/build/generate-route-types.ts +5 -1
  115. package/src/build/index.ts +8 -2
  116. package/src/build/prefix-tree-utils.ts +123 -0
  117. package/src/build/route-trie.ts +165 -36
  118. package/src/build/route-types/ast-route-extraction.ts +15 -8
  119. package/src/build/route-types/codegen.ts +16 -5
  120. package/src/build/route-types/include-resolution.ts +125 -24
  121. package/src/build/route-types/param-extraction.ts +6 -3
  122. package/src/build/route-types/per-module-writer.ts +22 -6
  123. package/src/build/route-types/router-processing.ts +260 -94
  124. package/src/build/route-types/scan-filter.ts +9 -2
  125. package/src/build/route-types/source-scan.ts +216 -0
  126. package/src/build/runtime-discovery.ts +9 -20
  127. package/src/cache/cache-error.ts +104 -0
  128. package/src/cache/cache-key-utils.ts +29 -13
  129. package/src/cache/cache-policy.ts +108 -34
  130. package/src/cache/cache-runtime.ts +239 -52
  131. package/src/cache/cache-scope.ts +234 -87
  132. package/src/cache/cache-tag.ts +103 -0
  133. package/src/cache/cf/cf-base64.ts +33 -0
  134. package/src/cache/cf/cf-cache-constants.ts +127 -0
  135. package/src/cache/cf/cf-cache-store.ts +1989 -378
  136. package/src/cache/cf/cf-cache-types.ts +349 -0
  137. package/src/cache/cf/cf-kv-utils.ts +46 -0
  138. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  139. package/src/cache/cf/index.ts +6 -16
  140. package/src/cache/document-cache.ts +89 -21
  141. package/src/cache/handle-snapshot.ts +70 -0
  142. package/src/cache/index.ts +10 -20
  143. package/src/cache/memory-segment-store.ts +136 -37
  144. package/src/cache/profile-registry.ts +46 -31
  145. package/src/cache/read-through-swr.ts +56 -12
  146. package/src/cache/segment-codec.ts +9 -17
  147. package/src/cache/tag-invalidation.ts +230 -0
  148. package/src/cache/taint.ts +55 -0
  149. package/src/cache/types.ts +37 -100
  150. package/src/client.rsc.tsx +44 -21
  151. package/src/client.tsx +119 -290
  152. package/src/cloudflare/index.ts +11 -0
  153. package/src/cloudflare/tracing.ts +109 -0
  154. package/src/component-utils.ts +19 -0
  155. package/src/components/DefaultDocument.tsx +8 -2
  156. package/src/context-var.ts +84 -2
  157. package/src/decode-loader-results.ts +52 -0
  158. package/src/defer.ts +196 -0
  159. package/src/deps/ssr.ts +0 -1
  160. package/src/encode-kv.ts +49 -0
  161. package/src/errors.ts +30 -4
  162. package/src/escape-script.ts +52 -0
  163. package/src/handle.ts +70 -22
  164. package/src/handles/MetaTags.tsx +62 -19
  165. package/src/handles/Scripts.tsx +183 -0
  166. package/src/handles/breadcrumbs.ts +37 -8
  167. package/src/handles/is-thenable.ts +19 -0
  168. package/src/handles/meta.ts +51 -40
  169. package/src/handles/script.ts +244 -0
  170. package/src/host/cookie-handler.ts +9 -60
  171. package/src/host/errors.ts +0 -24
  172. package/src/host/index.ts +8 -2
  173. package/src/host/pattern-matcher.ts +23 -52
  174. package/src/host/router.ts +107 -99
  175. package/src/host/testing.ts +40 -27
  176. package/src/host/types.ts +37 -4
  177. package/src/host/utils.ts +1 -1
  178. package/src/href-client.ts +137 -22
  179. package/src/index.rsc.ts +99 -13
  180. package/src/index.ts +139 -19
  181. package/src/internal-debug.ts +11 -10
  182. package/src/loader-store.ts +500 -0
  183. package/src/loader.rsc.ts +20 -13
  184. package/src/loader.ts +12 -11
  185. package/src/missing-id-error.ts +68 -0
  186. package/src/outlet-context.ts +1 -1
  187. package/src/outlet-provider.tsx +1 -5
  188. package/src/prerender/param-hash.ts +16 -16
  189. package/src/prerender/store.ts +37 -41
  190. package/src/prerender.ts +198 -82
  191. package/src/redirect-origin.ts +100 -0
  192. package/src/regex-escape.ts +8 -0
  193. package/src/render-error-thrower.tsx +20 -0
  194. package/src/response-utils.ts +62 -0
  195. package/src/reverse.ts +65 -15
  196. package/src/root-error-boundary.tsx +1 -19
  197. package/src/route-content-wrapper.tsx +19 -77
  198. package/src/route-definition/dsl-helpers.ts +461 -304
  199. package/src/route-definition/helper-factories.ts +28 -140
  200. package/src/route-definition/helpers-types.ts +149 -74
  201. package/src/route-definition/index.ts +4 -2
  202. package/src/route-definition/redirect.ts +51 -10
  203. package/src/route-definition/resolve-handler-use.ts +160 -0
  204. package/src/route-definition/use-item-types.ts +29 -0
  205. package/src/route-map-builder.ts +0 -16
  206. package/src/route-types.ts +37 -46
  207. package/src/router/basename.ts +14 -0
  208. package/src/router/content-negotiation.ts +164 -17
  209. package/src/router/error-handling.ts +45 -18
  210. package/src/router/find-match.ts +44 -23
  211. package/src/router/handler-context.ts +83 -39
  212. package/src/router/instrument.ts +350 -0
  213. package/src/router/intercept-resolution.ts +48 -24
  214. package/src/router/lazy-includes.ts +15 -52
  215. package/src/router/loader-resolution.ts +274 -56
  216. package/src/router/logging.ts +0 -6
  217. package/src/router/manifest.ts +40 -42
  218. package/src/router/match-api.ts +124 -204
  219. package/src/router/match-context.ts +0 -22
  220. package/src/router/match-handlers.ts +58 -58
  221. package/src/router/match-middleware/background-revalidation.ts +54 -25
  222. package/src/router/match-middleware/cache-lookup.ts +205 -271
  223. package/src/router/match-middleware/cache-store.ts +81 -50
  224. package/src/router/match-middleware/intercept-resolution.ts +0 -22
  225. package/src/router/match-middleware/segment-resolution.ts +45 -14
  226. package/src/router/match-pipelines.ts +1 -42
  227. package/src/router/match-result.ts +93 -39
  228. package/src/router/metrics.ts +5 -34
  229. package/src/router/middleware-types.ts +13 -142
  230. package/src/router/middleware.ts +268 -171
  231. package/src/router/navigation-snapshot.ts +131 -0
  232. package/src/router/params-util.ts +23 -0
  233. package/src/router/pattern-matching.ts +132 -90
  234. package/src/router/prefetch-cache-ttl.ts +51 -0
  235. package/src/router/prefetch-limits.ts +37 -0
  236. package/src/router/prerender-match.ts +195 -56
  237. package/src/router/preview-match.ts +32 -102
  238. package/src/router/request-classification.ts +276 -0
  239. package/src/router/revalidation.ts +123 -73
  240. package/src/router/route-snapshot.ts +244 -0
  241. package/src/router/router-context.ts +3 -27
  242. package/src/router/router-interfaces.ts +129 -35
  243. package/src/router/router-options.ts +202 -15
  244. package/src/router/router-registry.ts +2 -5
  245. package/src/router/segment-resolution/fresh.ts +197 -92
  246. package/src/router/segment-resolution/helpers.ts +115 -30
  247. package/src/router/segment-resolution/loader-cache.ts +76 -39
  248. package/src/router/segment-resolution/revalidation.ts +392 -338
  249. package/src/router/segment-resolution/static-store.ts +19 -5
  250. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  251. package/src/router/segment-resolution/view-transition-default.ts +56 -0
  252. package/src/router/segment-resolution.ts +5 -1
  253. package/src/router/segment-wrappers.ts +6 -5
  254. package/src/router/state-cookie-name.ts +33 -0
  255. package/src/router/substitute-pattern-params.ts +56 -0
  256. package/src/router/telemetry-otel.ts +161 -199
  257. package/src/router/telemetry.ts +96 -19
  258. package/src/router/timeout.ts +0 -20
  259. package/src/router/tracing.ts +206 -0
  260. package/src/router/trie-matching.ts +163 -59
  261. package/src/router/types.ts +10 -63
  262. package/src/router/url-params.ts +44 -0
  263. package/src/router.ts +174 -54
  264. package/src/rsc/handler-context.ts +3 -2
  265. package/src/rsc/handler.ts +660 -518
  266. package/src/rsc/helpers.ts +168 -46
  267. package/src/rsc/index.ts +2 -5
  268. package/src/rsc/json-route-result.ts +38 -0
  269. package/src/rsc/loader-fetch.ts +127 -31
  270. package/src/rsc/manifest-init.ts +33 -42
  271. package/src/rsc/origin-guard.ts +39 -25
  272. package/src/rsc/progressive-enhancement.ts +133 -13
  273. package/src/rsc/redirect-guard.ts +99 -0
  274. package/src/rsc/response-cache-serve.ts +238 -0
  275. package/src/rsc/response-error.ts +79 -12
  276. package/src/rsc/response-route-handler.ts +99 -189
  277. package/src/rsc/rsc-rendering.ts +115 -73
  278. package/src/rsc/runtime-warnings.ts +23 -10
  279. package/src/rsc/server-action.ts +287 -113
  280. package/src/rsc/ssr-setup.ts +18 -2
  281. package/src/rsc/transition-gate.ts +89 -0
  282. package/src/rsc/types.ts +36 -6
  283. package/src/runtime-env.ts +18 -0
  284. package/src/search-params.ts +35 -30
  285. package/src/segment-content-promise.ts +67 -0
  286. package/src/segment-loader-promise.ts +149 -0
  287. package/src/segment-system.tsx +269 -202
  288. package/src/serialize.ts +243 -0
  289. package/src/server/context.ts +235 -51
  290. package/src/server/cookie-parse.ts +32 -0
  291. package/src/server/cookie-store.ts +80 -5
  292. package/src/server/handle-store.ts +40 -38
  293. package/src/server/loader-registry.ts +38 -46
  294. package/src/server/request-context.ts +442 -173
  295. package/src/ssr/index.tsx +24 -16
  296. package/src/static-handler.ts +27 -18
  297. package/src/testing/cache-status.ts +162 -0
  298. package/src/testing/collect-handle.ts +40 -0
  299. package/src/testing/dispatch.ts +701 -0
  300. package/src/testing/dom.entry.ts +22 -0
  301. package/src/testing/e2e/fixture.ts +188 -0
  302. package/src/testing/e2e/index.ts +128 -0
  303. package/src/testing/e2e/matchers.ts +35 -0
  304. package/src/testing/e2e/page-helpers.ts +272 -0
  305. package/src/testing/e2e/parity.ts +387 -0
  306. package/src/testing/e2e/server.ts +195 -0
  307. package/src/testing/flight-matchers.ts +97 -0
  308. package/src/testing/flight-normalize.ts +11 -0
  309. package/src/testing/flight-runtime.d.ts +57 -0
  310. package/src/testing/flight-tree.ts +682 -0
  311. package/src/testing/flight.entry.ts +52 -0
  312. package/src/testing/flight.ts +257 -0
  313. package/src/testing/generated-routes.ts +183 -0
  314. package/src/testing/index.ts +105 -0
  315. package/src/testing/internal/context.ts +371 -0
  316. package/src/testing/internal/flight-client-globals.ts +30 -0
  317. package/src/testing/internal/seed-vars.ts +54 -0
  318. package/src/testing/render-handler.ts +357 -0
  319. package/src/testing/render-route.tsx +581 -0
  320. package/src/testing/run-loader.ts +385 -0
  321. package/src/testing/run-middleware.ts +205 -0
  322. package/src/testing/run-transition-when.ts +164 -0
  323. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  324. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  325. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  326. package/src/testing/vitest-stubs/version.ts +5 -0
  327. package/src/testing/vitest.ts +305 -0
  328. package/src/theme/ThemeProvider.tsx +20 -58
  329. package/src/theme/ThemeScript.tsx +7 -9
  330. package/src/theme/constants.ts +52 -13
  331. package/src/theme/index.ts +0 -7
  332. package/src/theme/theme-context.ts +1 -5
  333. package/src/theme/theme-script.ts +22 -21
  334. package/src/theme/use-theme.ts +0 -3
  335. package/src/types/boundaries.ts +0 -35
  336. package/src/types/cache-types.ts +17 -8
  337. package/src/types/error-types.ts +30 -90
  338. package/src/types/global-namespace.ts +54 -41
  339. package/src/types/handler-context.ts +234 -82
  340. package/src/types/index.ts +3 -10
  341. package/src/types/loader-types.ts +44 -15
  342. package/src/types/request-scope.ts +112 -0
  343. package/src/types/route-config.ts +6 -50
  344. package/src/types/route-entry.ts +12 -7
  345. package/src/types/segments.ts +136 -15
  346. package/src/urls/include-helper.ts +33 -70
  347. package/src/urls/index.ts +1 -11
  348. package/src/urls/path-helper-types.ts +68 -18
  349. package/src/urls/path-helper.ts +57 -111
  350. package/src/urls/pattern-types.ts +48 -19
  351. package/src/urls/response-types.ts +25 -22
  352. package/src/urls/type-extraction.ts +58 -139
  353. package/src/urls/urls-function.ts +1 -19
  354. package/src/use-loader.tsx +346 -89
  355. package/src/vite/debug.ts +185 -0
  356. package/src/vite/discovery/bundle-postprocess.ts +36 -38
  357. package/src/vite/discovery/discover-routers.ts +130 -85
  358. package/src/vite/discovery/discovery-errors.ts +194 -0
  359. package/src/vite/discovery/gate-state.ts +171 -0
  360. package/src/vite/discovery/prerender-collection.ts +214 -132
  361. package/src/vite/discovery/route-types-writer.ts +40 -84
  362. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  363. package/src/vite/discovery/state.ts +57 -4
  364. package/src/vite/discovery/virtual-module-codegen.ts +14 -34
  365. package/src/vite/index.ts +6 -0
  366. package/src/vite/inject-client-debug.ts +36 -0
  367. package/src/vite/plugin-types.ts +178 -5
  368. package/src/vite/plugins/cjs-to-esm.ts +16 -19
  369. package/src/vite/plugins/client-ref-dedup.ts +16 -11
  370. package/src/vite/plugins/client-ref-hashing.ts +28 -15
  371. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  372. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  373. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  374. package/src/vite/plugins/expose-action-id.ts +48 -95
  375. package/src/vite/plugins/expose-id-utils.ts +96 -51
  376. package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
  377. package/src/vite/plugins/expose-ids/handler-transform.ts +15 -64
  378. package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
  379. package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
  380. package/src/vite/plugins/expose-internal-ids.ts +553 -317
  381. package/src/vite/plugins/performance-tracks.ts +89 -0
  382. package/src/vite/plugins/refresh-cmd.ts +89 -27
  383. package/src/vite/plugins/use-cache-transform.ts +73 -83
  384. package/src/vite/plugins/version-injector.ts +40 -29
  385. package/src/vite/plugins/version-plugin.ts +37 -40
  386. package/src/vite/plugins/virtual-entries.ts +39 -25
  387. package/src/vite/rango.ts +119 -111
  388. package/src/vite/router-discovery.ts +941 -142
  389. package/src/vite/utils/ast-handler-extract.ts +26 -35
  390. package/src/vite/utils/banner.ts +1 -1
  391. package/src/vite/utils/bundle-analysis.ts +10 -15
  392. package/src/vite/utils/client-chunks.ts +184 -0
  393. package/src/vite/utils/directive-prologue.ts +40 -0
  394. package/src/vite/utils/forward-user-plugins.ts +171 -0
  395. package/src/vite/utils/manifest-utils.ts +4 -59
  396. package/src/vite/utils/package-resolution.ts +20 -52
  397. package/src/vite/utils/prerender-utils.ts +81 -34
  398. package/src/vite/utils/shared-utils.ts +92 -42
  399. package/src/browser/action-response-classifier.ts +0 -99
  400. package/src/browser/react/use-client-cache.ts +0 -58
  401. package/src/browser/shallow.ts +0 -40
  402. package/src/handles/index.ts +0 -7
  403. package/src/network-error-thrower.tsx +0 -23
  404. package/src/router/middleware-cookies.ts +0 -55
@@ -1,5 +1,6 @@
1
1
  import { parseAst, type Plugin } from "vite";
2
2
  import { VIRTUAL_IDS, getVirtualVersionContent } from "./virtual-entries.js";
3
+ import { hasUseClientDirective } from "../utils/directive-prologue.js";
3
4
 
4
5
  interface ClientModuleSignature {
5
6
  key: string;
@@ -16,30 +17,17 @@ function normalizeModuleId(id: string): string {
16
17
  function getClientModuleSignature(
17
18
  source: string,
18
19
  ): ClientModuleSignature | undefined {
20
+ // Same leading-directive sniff the rango HMR plugin uses (shared helper, so the
21
+ // two agree on what counts as a client module). A parse failure yields false.
22
+ if (!hasUseClientDirective(source)) return undefined;
23
+
19
24
  let program: any;
20
25
  try {
21
- program = parseAst(source, { jsx: true });
26
+ program = parseAst(source, { lang: "tsx" });
22
27
  } catch {
23
28
  return undefined;
24
29
  }
25
30
 
26
- let isUseClient = false;
27
- for (const node of program.body ?? []) {
28
- if (
29
- node?.type === "ExpressionStatement" &&
30
- node.expression?.type === "Literal" &&
31
- typeof node.expression.value === "string"
32
- ) {
33
- if (node.expression.value === "use client") {
34
- isUseClient = true;
35
- }
36
- continue;
37
- }
38
- break;
39
- }
40
-
41
- if (!isUseClient) return undefined;
42
-
43
31
  const exports = new Set<string>();
44
32
  let hasDefault = false;
45
33
  let hasExportAll = false;
@@ -133,14 +121,13 @@ export function createVersionPlugin(): Plugin {
133
121
  let currentVersion = buildVersion;
134
122
  let isDev = false;
135
123
  let server: any = null;
124
+ let resolvedCacheDir: string | undefined;
136
125
  const clientModuleSignatures = new Map<string, ClientModuleSignature>();
137
126
 
138
127
  let versionCounter = 0;
139
128
  const bumpVersion = (reason: string) => {
140
- // Use timestamp + counter to guarantee uniqueness even when multiple
141
- // bumps happen within the same millisecond (e.g. cascading HMR events).
142
129
  currentVersion = Date.now().toString(16) + String(++versionCounter);
143
- console.log(`[rsc-router] ${reason}, version updated: ${currentVersion}`);
130
+ console.log(`[rango] ${reason}, version updated: ${currentVersion}`);
144
131
 
145
132
  const rscEnv = server?.environments?.rsc;
146
133
  const versionMod = rscEnv?.moduleGraph?.getModuleById(
@@ -157,6 +144,9 @@ export function createVersionPlugin(): Plugin {
157
144
 
158
145
  configResolved(config) {
159
146
  isDev = config.command === "serve";
147
+ resolvedCacheDir = config.cacheDir
148
+ ? String(config.cacheDir).replace(/\\/g, "/")
149
+ : undefined;
160
150
  },
161
151
 
162
152
  configureServer(devServer) {
@@ -203,19 +193,15 @@ export function createVersionPlugin(): Plugin {
203
193
  return null;
204
194
  },
205
195
 
206
- // Track RSC module changes and update version
207
196
  async hotUpdate(ctx) {
208
197
  if (!isDev) return;
209
198
 
210
- // Check if this is an RSC environment update (not client/ssr)
211
- // RSC modules affect server-rendered content and cached payloads
212
- // In Vite 6, environment is accessed via `this.environment`
213
199
  const isRscModule = this.environment?.name === "rsc";
214
200
 
215
201
  if (!isRscModule) return;
216
202
 
217
- // Skip re-bumping when the version virtual module itself is invalidated
218
- // (our own bumpVersion() invalidates it, which re-triggers hotUpdate).
203
+ if (isViteDepCachePath(ctx.file, resolvedCacheDir)) return;
204
+
219
205
  if (
220
206
  ctx.modules.length === 1 &&
221
207
  ctx.modules[0].id === "\0" + VIRTUAL_IDS.version
@@ -230,9 +216,6 @@ export function createVersionPlugin(): Plugin {
230
216
  const source = await ctx.read();
231
217
  const nextSignature = getClientModuleSignature(source);
232
218
  if (nextSignature) {
233
- // "use client" file — compare export signatures.
234
- // client-component-hmr may have cleared ctx.modules, so we
235
- // cannot rely on ctx.modules.length for these files.
236
219
  clientModuleSignatures.set(filePath, nextSignature);
237
220
  if (
238
221
  previousSignature &&
@@ -243,20 +226,11 @@ export function createVersionPlugin(): Plugin {
243
226
  } else {
244
227
  clientModuleSignatures.delete(filePath);
245
228
  if (!previousSignature) {
246
- // Not and never was "use client" — use module graph check.
247
- // ctx.modules is reliable for pure server files (only
248
- // client-component-hmr clears it for "use client" modules).
249
229
  if (ctx.modules.length === 0) return;
250
230
  }
251
- // Was "use client" but directive removed — boundary changed,
252
- // bump below.
253
231
  }
254
- } catch {
255
- // Fail open: if we can't read or parse the update, invalidate.
256
- }
232
+ } catch {}
257
233
  } else {
258
- // Non-code file (json, css, etc.) — only bump if it's actually
259
- // referenced by the RSC module graph.
260
234
  if (ctx.modules.length === 0) return;
261
235
  }
262
236
 
@@ -264,3 +238,26 @@ export function createVersionPlugin(): Plugin {
264
238
  },
265
239
  };
266
240
  }
241
+
242
+ export function isViteDepCachePath(
243
+ filePath: string | undefined,
244
+ cacheDir?: string,
245
+ ): boolean {
246
+ if (!filePath) return false;
247
+ const normalized = filePath.replace(/\\/g, "/");
248
+
249
+ if (cacheDir) {
250
+ const normalizedCacheDir = cacheDir.replace(/\\/g, "/").replace(/\/+$/, "");
251
+ if (
252
+ normalized === normalizedCacheDir ||
253
+ normalized.startsWith(normalizedCacheDir + "/")
254
+ ) {
255
+ return true;
256
+ }
257
+ }
258
+
259
+ return (
260
+ /\/node_modules\/\.vite[^/]*\//.test(normalized) ||
261
+ normalized.includes("/.vite-isolated/")
262
+ );
263
+ }
@@ -1,8 +1,3 @@
1
- /**
2
- * Default virtual entry file contents for rsc-router.
3
- * These are used when users don't provide their own entry files.
4
- */
5
-
6
1
  export const VIRTUAL_ENTRY_BROWSER: string = `
7
2
  import {
8
3
  createFromReadableStream,
@@ -14,7 +9,7 @@ import {
14
9
  import { createElement, StrictMode } from "react";
15
10
  import { hydrateRoot } from "react-dom/client";
16
11
  import { rscStream } from "@rangojs/router/internal/deps/html-stream-client";
17
- import { initBrowserApp, RSCRouter } from "@rangojs/router/browser";
12
+ import { initBrowserApp, Rango } from "@rangojs/router/browser";
18
13
 
19
14
  async function initializeApp() {
20
15
  const deps = {
@@ -25,11 +20,16 @@ async function initializeApp() {
25
20
  createTemporaryReferenceSet,
26
21
  };
27
22
 
28
- await initBrowserApp({ rscStream, deps });
23
+ // initBrowserApp resolves the initial payload and returns the browser app
24
+ // context, including strictMode (default true) from createRouter. StrictMode
25
+ // is the default; createRouter({ strictMode: false }) ships the opt-out in the
26
+ // payload metadata. StrictMode emits no DOM, so toggling never changes markup.
27
+ const { strictMode } = await initBrowserApp({ rscStream, deps });
29
28
 
29
+ const app = createElement(Rango);
30
30
  hydrateRoot(
31
31
  document,
32
- createElement(StrictMode, null, createElement(RSCRouter))
32
+ strictMode === false ? app : createElement(StrictMode, null, app)
33
33
  );
34
34
  }
35
35
 
@@ -52,9 +52,31 @@ export const renderHTML = createSSRHandler({
52
52
  `.trim();
53
53
 
54
54
  /**
55
- * Generate the RSC entry content with the specified router path
55
+ * Virtual modules an RSC entry must import at startup to register the data the
56
+ * request handler needs before the first request arrives:
57
+ *
58
+ * - routes-manifest: the pre-generated route map so href()/matching work on a
59
+ * cold start (full map in build, in-memory no-op in dev).
60
+ * - loader-manifest: setLoaderImports() for fetchable loaders. Critical for
61
+ * serverless/multi-process deployments and for fetchable loaders reachable
62
+ * only through a client component — without it those loaders are never
63
+ * registered for the _rsc_loader endpoint and fail in production.
64
+ *
65
+ * Single source of truth: both the generated virtual RSC entry below and the
66
+ * custom-entry injector (version-injector) consume this list, so a new
67
+ * bootstrap manifest cannot be added to one path and forgotten on the other.
68
+ * That exact drift (loader-manifest present here but missing from the injector)
69
+ * is what left fetchable loaders unresolved on custom worker entries.
56
70
  */
71
+ export const RSC_ENTRY_BOOTSTRAP_IMPORTS: readonly string[] = [
72
+ "virtual:rsc-router/routes-manifest",
73
+ "virtual:rsc-router/loader-manifest",
74
+ ];
75
+
57
76
  export function getVirtualEntryRSC(routerPath: string): string {
77
+ const bootstrapImports = RSC_ENTRY_BOOTSTRAP_IMPORTS.map(
78
+ (id) => `import "${id}";`,
79
+ ).join("\n");
58
80
  return `
59
81
  import {
60
82
  renderToReadableStream,
@@ -68,15 +90,9 @@ import { router } from "${routerPath}";
68
90
  import { createRSCHandler } from "@rangojs/router/internal/rsc-handler";
69
91
  import { VERSION } from "@rangojs/router:version";
70
92
 
71
- // Import loader manifest to ensure all fetchable loaders are registered at startup
72
- // This is critical for serverless/multi-process deployments where the loader module
73
- // might not be imported before a GET request arrives
74
- import "virtual:rsc-router/loader-manifest";
75
-
76
- // Import pre-generated route manifest so href() works immediately on cold start.
77
- // In build mode, this contains the full route map generated at build time.
78
- // In dev mode, this is a no-op (manifest is populated in-memory by the discovery plugin).
79
- import "virtual:rsc-router/routes-manifest";
93
+ // Startup bootstrap imports (routes + loader manifests). See
94
+ // RSC_ENTRY_BOOTSTRAP_IMPORTS — the same list the custom-entry injector uses.
95
+ ${bootstrapImports}
80
96
 
81
97
  // Lazily create the handler on first request so that ESM live bindings
82
98
  // have resolved by the time we read \`router\`. During HMR the module may
@@ -87,6 +103,11 @@ export default function handler(request, env) {
87
103
  _handler = createRSCHandler({
88
104
  router,
89
105
  version: VERSION,
106
+ // Forward the router's CSP nonce provider. createRSCHandler reads the
107
+ // provider only from options.nonce; without this, createRouter({ nonce })
108
+ // is silently dropped on the Node preset (the Cloudflare path wires it via
109
+ // router.fetch). router.nonce is undefined when unconfigured, a safe no-op.
110
+ nonce: router.nonce,
90
111
  deps: {
91
112
  renderToReadableStream,
92
113
  decodeReply,
@@ -104,9 +125,6 @@ export default function handler(request, env) {
104
125
  `.trim();
105
126
  }
106
127
 
107
- /**
108
- * Virtual module IDs
109
- */
110
128
  export const VIRTUAL_IDS = {
111
129
  browser: "virtual:rsc-router/entry.browser.js",
112
130
  ssr: "virtual:rsc-router/entry.ssr.js",
@@ -114,10 +132,6 @@ export const VIRTUAL_IDS = {
114
132
  version: "@rangojs/router:version",
115
133
  } as const;
116
134
 
117
- /**
118
- * Virtual module content for version.
119
- * Exports VERSION - a timestamp that changes on server restart (dev) or at build time (production).
120
- */
121
135
  export function getVirtualVersionContent(version: string): string {
122
136
  return `export const VERSION = ${JSON.stringify(version)};`;
123
137
  }