@rangojs/router 0.0.0-experimental.b9cb8739 → 0.0.0-experimental.bdaf10aa

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 (449) hide show
  1. package/AGENTS.md +8 -4
  2. package/README.md +303 -741
  3. package/dist/bin/rango.js +730 -184
  4. package/dist/testing/vitest.js +82 -0
  5. package/dist/vite/index.js +4344 -1335
  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 +86 -15
  9. package/skills/api-client/SKILL.md +211 -0
  10. package/skills/breadcrumbs/SKILL.md +85 -6
  11. package/skills/bundle-analysis/SKILL.md +159 -0
  12. package/skills/cache-guide/SKILL.md +251 -24
  13. package/skills/caching/SKILL.md +375 -17
  14. package/skills/catalog.json +271 -0
  15. package/skills/comparison/SKILL.md +50 -0
  16. package/skills/comparison/agents/openai.yaml +4 -0
  17. package/skills/comparison/references/framework-comparison.md +837 -0
  18. package/skills/composability/SKILL.md +110 -4
  19. package/skills/css/SKILL.md +76 -0
  20. package/skills/debug-manifest/SKILL.md +5 -3
  21. package/skills/defer-hydration/SKILL.md +235 -0
  22. package/skills/document-cache/SKILL.md +87 -56
  23. package/skills/fonts/SKILL.md +1 -1
  24. package/skills/handler-use/SKILL.md +364 -0
  25. package/skills/hooks/SKILL.md +73 -691
  26. package/skills/hooks/data.md +273 -0
  27. package/skills/hooks/handle-and-actions.md +103 -0
  28. package/skills/hooks/navigation.md +110 -0
  29. package/skills/hooks/outlets.md +41 -0
  30. package/skills/hooks/state.md +228 -0
  31. package/skills/hooks/urls.md +135 -0
  32. package/skills/host-router/SKILL.md +129 -27
  33. package/skills/i18n/SKILL.md +276 -0
  34. package/skills/intercept/SKILL.md +94 -18
  35. package/skills/layout/SKILL.md +62 -19
  36. package/skills/links/SKILL.md +249 -17
  37. package/skills/loader/SKILL.md +302 -54
  38. package/skills/middleware/SKILL.md +59 -16
  39. package/skills/migrate-nextjs/SKILL.md +745 -0
  40. package/skills/migrate-react-router/SKILL.md +153 -0
  41. package/skills/migrate-react-router/cloudflare-workers.md +129 -0
  42. package/skills/migrate-react-router/component-migration.md +196 -0
  43. package/skills/migrate-react-router/data-and-actions.md +225 -0
  44. package/skills/migrate-react-router/route-mapping.md +271 -0
  45. package/skills/mime-routes/SKILL.md +29 -2
  46. package/skills/observability/SKILL.md +202 -0
  47. package/skills/parallel/SKILL.md +225 -10
  48. package/skills/ppr/SKILL.md +622 -0
  49. package/skills/prerender/SKILL.md +178 -124
  50. package/skills/rango/SKILL.md +318 -24
  51. package/skills/react-compiler/SKILL.md +168 -0
  52. package/skills/response-routes/SKILL.md +138 -49
  53. package/skills/route/SKILL.md +172 -9
  54. package/skills/router-setup/SKILL.md +131 -11
  55. package/skills/scripts/SKILL.md +179 -0
  56. package/skills/server-actions/SKILL.md +776 -0
  57. package/skills/shell-manifest/SKILL.md +185 -0
  58. package/skills/streams-and-websockets/SKILL.md +283 -0
  59. package/skills/tailwind/SKILL.md +28 -4
  60. package/skills/testing/SKILL.md +130 -0
  61. package/skills/testing/bindings.md +103 -0
  62. package/skills/testing/cache-prerender.md +127 -0
  63. package/skills/testing/client-components.md +124 -0
  64. package/skills/testing/e2e-parity.md +125 -0
  65. package/skills/testing/flight.md +91 -0
  66. package/skills/testing/handles.md +131 -0
  67. package/skills/testing/loader.md +128 -0
  68. package/skills/testing/middleware.md +99 -0
  69. package/skills/testing/render-handler.md +122 -0
  70. package/skills/testing/response-routes.md +95 -0
  71. package/skills/testing/reverse-and-types.md +85 -0
  72. package/skills/testing/server-actions.md +107 -0
  73. package/skills/testing/server-tree.md +128 -0
  74. package/skills/testing/setup.md +123 -0
  75. package/skills/theme/SKILL.md +1 -1
  76. package/skills/typesafety/SKILL.md +45 -616
  77. package/skills/typesafety/env-and-bindings.md +254 -0
  78. package/skills/typesafety/generated-files-and-cli.md +335 -0
  79. package/skills/typesafety/params-and-search.md +153 -0
  80. package/skills/typesafety/route-types.md +209 -0
  81. package/skills/use-cache/SKILL.md +74 -15
  82. package/skills/vercel/SKILL.md +128 -0
  83. package/skills/view-transitions/SKILL.md +337 -0
  84. package/src/__augment-tests__/augment.ts +81 -0
  85. package/src/__augment-tests__/augmented.check.ts +116 -0
  86. package/src/__internal.ts +1 -66
  87. package/src/browser/action-coordinator.ts +53 -36
  88. package/src/browser/action-fence.ts +47 -0
  89. package/src/browser/app-shell.ts +39 -0
  90. package/src/browser/app-version.ts +14 -0
  91. package/src/browser/connection-warmup.ts +134 -0
  92. package/src/browser/cookie-name.ts +140 -0
  93. package/src/browser/event-controller.ts +257 -158
  94. package/src/browser/history-state.ts +21 -0
  95. package/src/browser/index.ts +3 -3
  96. package/src/browser/invalidate-client-cache.ts +52 -0
  97. package/src/browser/logging.ts +28 -0
  98. package/src/browser/merge-segment-loaders.ts +6 -4
  99. package/src/browser/navigation-bridge.ts +132 -33
  100. package/src/browser/navigation-client.ts +218 -68
  101. package/src/browser/navigation-store-handle.ts +38 -0
  102. package/src/browser/navigation-store.ts +203 -80
  103. package/src/browser/navigation-transaction.ts +18 -66
  104. package/src/browser/network-error-handler.ts +34 -7
  105. package/src/browser/partial-update.ts +241 -127
  106. package/src/browser/prefetch/cache.ts +271 -44
  107. package/src/browser/prefetch/fetch.ts +367 -40
  108. package/src/browser/prefetch/queue.ts +144 -23
  109. package/src/browser/prefetch/resource-ready.ts +77 -0
  110. package/src/browser/rango-state.ts +158 -76
  111. package/src/browser/react/Link.tsx +121 -16
  112. package/src/browser/react/NavigationProvider.tsx +240 -122
  113. package/src/browser/react/ScrollRestoration.tsx +10 -6
  114. package/src/browser/react/context.ts +7 -2
  115. package/src/browser/react/filter-segment-order.ts +66 -7
  116. package/src/browser/react/index.ts +0 -48
  117. package/src/browser/react/location-state-shared.ts +178 -8
  118. package/src/browser/react/location-state.ts +39 -14
  119. package/src/browser/react/use-action.ts +6 -15
  120. package/src/browser/react/use-handle.ts +23 -69
  121. package/src/browser/react/use-href.tsx +8 -1
  122. package/src/browser/react/use-link-status.ts +33 -8
  123. package/src/browser/react/use-navigation.ts +32 -7
  124. package/src/browser/react/use-params.ts +20 -10
  125. package/src/browser/react/use-reverse.ts +106 -0
  126. package/src/browser/react/use-router.ts +46 -11
  127. package/src/browser/react/use-search-params.ts +0 -5
  128. package/src/browser/react/use-segments.ts +11 -21
  129. package/src/browser/response-adapter.ts +99 -8
  130. package/src/browser/rsc-router.tsx +272 -80
  131. package/src/browser/scroll-restoration.ts +56 -22
  132. package/src/browser/segment-reconciler.ts +44 -7
  133. package/src/browser/segment-structure-assert.ts +2 -2
  134. package/src/browser/server-action-bridge.ts +244 -71
  135. package/src/browser/types.ts +136 -12
  136. package/src/browser/validate-redirect-origin.ts +43 -16
  137. package/src/build/collect-fallback-refs.ts +107 -0
  138. package/src/build/generate-manifest.ts +207 -158
  139. package/src/build/generate-route-types.ts +6 -1
  140. package/src/build/index.ts +11 -3
  141. package/src/build/prefix-tree-utils.ts +123 -0
  142. package/src/build/route-trie.ts +198 -41
  143. package/src/build/route-types/ast-route-extraction.ts +15 -8
  144. package/src/build/route-types/codegen.ts +16 -5
  145. package/src/build/route-types/include-resolution.ts +464 -63
  146. package/src/build/route-types/param-extraction.ts +6 -3
  147. package/src/build/route-types/per-module-writer.ts +22 -6
  148. package/src/build/route-types/router-processing.ts +336 -110
  149. package/src/build/route-types/scan-filter.ts +9 -2
  150. package/src/build/route-types/source-scan.ts +216 -0
  151. package/src/build/runtime-discovery.ts +13 -21
  152. package/src/cache/cache-error.ts +104 -0
  153. package/src/cache/cache-key-utils.ts +58 -13
  154. package/src/cache/cache-policy.ts +108 -34
  155. package/src/cache/cache-runtime.ts +454 -97
  156. package/src/cache/cache-scope.ts +235 -103
  157. package/src/cache/cache-tag.ts +149 -0
  158. package/src/cache/cf/cf-base64.ts +33 -0
  159. package/src/cache/cf/cf-cache-constants.ts +127 -0
  160. package/src/cache/cf/cf-cache-store.ts +2446 -170
  161. package/src/cache/cf/cf-cache-types.ts +349 -0
  162. package/src/cache/cf/cf-kv-utils.ts +46 -0
  163. package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
  164. package/src/cache/cf/index.ts +11 -17
  165. package/src/cache/document-cache.ts +144 -49
  166. package/src/cache/handle-snapshot.ts +70 -0
  167. package/src/cache/index.ts +24 -20
  168. package/src/cache/memory-segment-store.ts +243 -37
  169. package/src/cache/profile-registry.ts +46 -31
  170. package/src/cache/read-through-swr.ts +56 -12
  171. package/src/cache/segment-codec.ts +13 -21
  172. package/src/cache/shell-snapshot.ts +417 -0
  173. package/src/cache/tag-invalidation.ts +230 -0
  174. package/src/cache/taint.ts +55 -0
  175. package/src/cache/types.ts +194 -99
  176. package/src/cache/vercel/index.ts +11 -0
  177. package/src/cache/vercel/vercel-cache-store.ts +1132 -0
  178. package/src/client.rsc.tsx +41 -21
  179. package/src/client.tsx +116 -290
  180. package/src/cloudflare/index.ts +11 -0
  181. package/src/cloudflare/tracing.ts +108 -0
  182. package/src/component-utils.ts +19 -0
  183. package/src/components/DefaultDocument.tsx +8 -2
  184. package/src/context-var.ts +84 -2
  185. package/src/debug.ts +2 -2
  186. package/src/decode-loader-results.ts +52 -0
  187. package/src/defer.ts +185 -0
  188. package/src/deps/ssr.ts +0 -1
  189. package/src/encode-kv.ts +49 -0
  190. package/src/errors.ts +30 -4
  191. package/src/escape-script.ts +52 -0
  192. package/src/handle.ts +104 -34
  193. package/src/handles/MetaTags.tsx +24 -53
  194. package/src/handles/Scripts.tsx +183 -0
  195. package/src/handles/breadcrumbs.ts +35 -8
  196. package/src/handles/deferred-resolution.ts +127 -0
  197. package/src/handles/is-thenable.ts +18 -0
  198. package/src/handles/meta.ts +14 -40
  199. package/src/handles/script.ts +244 -0
  200. package/src/host/cookie-handler.ts +9 -60
  201. package/src/host/errors.ts +13 -22
  202. package/src/host/index.ts +9 -2
  203. package/src/host/pattern-matcher.ts +23 -52
  204. package/src/host/router.ts +107 -99
  205. package/src/host/testing.ts +40 -27
  206. package/src/host/types.ts +37 -4
  207. package/src/host/utils.ts +1 -1
  208. package/src/href-client.ts +137 -22
  209. package/src/index.rsc.ts +100 -13
  210. package/src/index.ts +143 -19
  211. package/src/internal-debug.ts +11 -10
  212. package/src/loader-store.ts +500 -0
  213. package/src/loader.rsc.ts +20 -13
  214. package/src/loader.ts +12 -11
  215. package/src/missing-id-error.ts +68 -0
  216. package/src/outlet-context.ts +1 -1
  217. package/src/outlet-provider.tsx +1 -5
  218. package/src/prerender/param-hash.ts +16 -16
  219. package/src/prerender/store.ts +37 -41
  220. package/src/prerender.ts +215 -86
  221. package/src/redirect-origin.ts +114 -0
  222. package/src/regex-escape.ts +8 -0
  223. package/src/render-error-thrower.tsx +20 -0
  224. package/src/response-utils.ts +62 -0
  225. package/src/reverse.ts +65 -15
  226. package/src/root-error-boundary.tsx +1 -19
  227. package/src/route-content-wrapper.tsx +19 -77
  228. package/src/route-definition/dsl-helpers.ts +485 -303
  229. package/src/route-definition/helper-factories.ts +28 -140
  230. package/src/route-definition/helpers-types.ts +153 -77
  231. package/src/route-definition/index.ts +4 -2
  232. package/src/route-definition/redirect.ts +53 -12
  233. package/src/route-definition/resolve-handler-use.ts +160 -0
  234. package/src/route-definition/use-item-types.ts +29 -0
  235. package/src/route-map-builder.ts +48 -21
  236. package/src/route-types.ts +37 -46
  237. package/src/router/basename.ts +14 -0
  238. package/src/router/content-negotiation.ts +164 -17
  239. package/src/router/error-handling.ts +45 -18
  240. package/src/router/find-match.ts +130 -29
  241. package/src/router/handler-context.ts +83 -39
  242. package/src/router/instrument.ts +355 -0
  243. package/src/router/intercept-resolution.ts +50 -24
  244. package/src/router/lazy-includes.ts +89 -63
  245. package/src/router/loader-resolution.ts +286 -56
  246. package/src/router/logging.ts +5 -8
  247. package/src/router/manifest.ts +105 -56
  248. package/src/router/match-api.ts +178 -218
  249. package/src/router/match-context.ts +0 -22
  250. package/src/router/match-handlers.ts +211 -165
  251. package/src/router/match-middleware/background-revalidation.ts +66 -22
  252. package/src/router/match-middleware/cache-lookup.ts +214 -263
  253. package/src/router/match-middleware/cache-store.ts +105 -50
  254. package/src/router/match-middleware/intercept-resolution.ts +8 -28
  255. package/src/router/match-middleware/segment-resolution.ts +52 -18
  256. package/src/router/match-pipelines.ts +1 -42
  257. package/src/router/match-result.ts +128 -44
  258. package/src/router/metrics.ts +5 -34
  259. package/src/router/middleware-types.ts +13 -142
  260. package/src/router/middleware.ts +301 -177
  261. package/src/router/navigation-snapshot.ts +133 -0
  262. package/src/router/params-util.ts +23 -0
  263. package/src/router/parse-pattern.ts +115 -0
  264. package/src/router/pattern-matching.ts +181 -150
  265. package/src/router/prefetch-cache-ttl.ts +51 -0
  266. package/src/router/prefetch-limits.ts +37 -0
  267. package/src/router/prerender-match.ts +203 -58
  268. package/src/router/preview-match.ts +35 -103
  269. package/src/router/request-classification.ts +291 -0
  270. package/src/router/revalidation.ts +123 -73
  271. package/src/router/route-snapshot.ts +256 -0
  272. package/src/router/router-context.ts +11 -29
  273. package/src/router/router-interfaces.ts +146 -35
  274. package/src/router/router-options.ts +202 -15
  275. package/src/router/router-registry.ts +2 -5
  276. package/src/router/segment-resolution/fresh.ts +301 -78
  277. package/src/router/segment-resolution/helpers.ts +115 -30
  278. package/src/router/segment-resolution/loader-cache.ts +156 -39
  279. package/src/router/segment-resolution/loader-mask.ts +60 -0
  280. package/src/router/segment-resolution/loader-snapshot.ts +259 -0
  281. package/src/router/segment-resolution/mask-nested.ts +83 -0
  282. package/src/router/segment-resolution/revalidation.ts +477 -385
  283. package/src/router/segment-resolution/static-store.ts +19 -5
  284. package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
  285. package/src/router/segment-resolution/view-transition-default.ts +56 -0
  286. package/src/router/segment-resolution.ts +5 -1
  287. package/src/router/segment-wrappers.ts +8 -5
  288. package/src/router/state-cookie-name.ts +33 -0
  289. package/src/router/substitute-pattern-params.ts +75 -0
  290. package/src/router/telemetry-otel.ts +160 -200
  291. package/src/router/telemetry.ts +105 -20
  292. package/src/router/timeout.ts +0 -20
  293. package/src/router/tracing.ts +215 -0
  294. package/src/router/trie-matching.ts +171 -59
  295. package/src/router/types.ts +10 -63
  296. package/src/router/url-params.ts +57 -0
  297. package/src/router.ts +210 -71
  298. package/src/rsc/full-payload.ts +70 -0
  299. package/src/rsc/handler-context.ts +3 -2
  300. package/src/rsc/handler.ts +682 -508
  301. package/src/rsc/helpers.ts +168 -46
  302. package/src/rsc/index.ts +2 -5
  303. package/src/rsc/json-route-result.ts +38 -0
  304. package/src/rsc/loader-fetch.ts +127 -31
  305. package/src/rsc/manifest-init.ts +33 -42
  306. package/src/rsc/nonce.ts +10 -1
  307. package/src/rsc/origin-guard.ts +39 -25
  308. package/src/rsc/progressive-enhancement.ts +138 -15
  309. package/src/rsc/redirect-guard.ts +100 -0
  310. package/src/rsc/response-cache-serve.ts +238 -0
  311. package/src/rsc/response-error.ts +79 -12
  312. package/src/rsc/response-route-handler.ts +99 -189
  313. package/src/rsc/rsc-rendering.ts +509 -73
  314. package/src/rsc/runtime-warnings.ts +23 -10
  315. package/src/rsc/server-action.ts +287 -113
  316. package/src/rsc/shell-capture.ts +1190 -0
  317. package/src/rsc/shell-serve.ts +181 -0
  318. package/src/rsc/ssr-setup.ts +18 -2
  319. package/src/rsc/transition-gate.ts +89 -0
  320. package/src/rsc/types.ts +62 -6
  321. package/src/runtime-env.ts +18 -0
  322. package/src/search-params.ts +35 -30
  323. package/src/segment-content-promise.ts +67 -0
  324. package/src/segment-loader-promise.ts +167 -0
  325. package/src/segment-system.tsx +449 -132
  326. package/src/serialize.ts +243 -0
  327. package/src/server/context.ts +367 -61
  328. package/src/server/cookie-parse.ts +32 -0
  329. package/src/server/cookie-store.ts +152 -5
  330. package/src/server/handle-store.ts +40 -38
  331. package/src/server/loader-registry.ts +38 -46
  332. package/src/server/request-context.ts +558 -173
  333. package/src/ssr/index.tsx +491 -174
  334. package/src/ssr/inject-rsc-eager.ts +167 -0
  335. package/src/ssr/ssr-root.tsx +228 -0
  336. package/src/static-handler.ts +27 -18
  337. package/src/testing/cache-status.ts +162 -0
  338. package/src/testing/collect-handle.ts +46 -0
  339. package/src/testing/dispatch.ts +813 -0
  340. package/src/testing/dom.entry.ts +22 -0
  341. package/src/testing/e2e/fixture.ts +188 -0
  342. package/src/testing/e2e/index.ts +128 -0
  343. package/src/testing/e2e/matchers.ts +35 -0
  344. package/src/testing/e2e/page-helpers.ts +272 -0
  345. package/src/testing/e2e/parity.ts +387 -0
  346. package/src/testing/e2e/server.ts +195 -0
  347. package/src/testing/flight-matchers.ts +97 -0
  348. package/src/testing/flight-normalize.ts +11 -0
  349. package/src/testing/flight-runtime.d.ts +57 -0
  350. package/src/testing/flight-tree.ts +682 -0
  351. package/src/testing/flight.entry.ts +52 -0
  352. package/src/testing/flight.ts +257 -0
  353. package/src/testing/generated-routes.ts +199 -0
  354. package/src/testing/index.ts +105 -0
  355. package/src/testing/internal/context.ts +371 -0
  356. package/src/testing/internal/flight-client-globals.ts +30 -0
  357. package/src/testing/internal/seed-vars.ts +54 -0
  358. package/src/testing/render-handler.ts +357 -0
  359. package/src/testing/render-route.tsx +584 -0
  360. package/src/testing/run-loader.ts +385 -0
  361. package/src/testing/run-middleware.ts +205 -0
  362. package/src/testing/run-transition-when.ts +164 -0
  363. package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
  364. package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
  365. package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
  366. package/src/testing/vitest-stubs/version.ts +5 -0
  367. package/src/testing/vitest.ts +305 -0
  368. package/src/theme/ThemeProvider.tsx +56 -84
  369. package/src/theme/ThemeScript.tsx +7 -9
  370. package/src/theme/constants.ts +52 -13
  371. package/src/theme/index.ts +0 -7
  372. package/src/theme/theme-context.ts +1 -5
  373. package/src/theme/theme-script.ts +22 -21
  374. package/src/theme/use-theme.ts +0 -3
  375. package/src/types/boundaries.ts +0 -35
  376. package/src/types/cache-types.ts +17 -8
  377. package/src/types/error-types.ts +30 -90
  378. package/src/types/global-namespace.ts +54 -41
  379. package/src/types/handler-context.ts +234 -82
  380. package/src/types/index.ts +3 -10
  381. package/src/types/loader-types.ts +44 -15
  382. package/src/types/request-scope.ts +112 -0
  383. package/src/types/route-config.ts +20 -52
  384. package/src/types/route-entry.ts +19 -7
  385. package/src/types/segments.ts +137 -14
  386. package/src/urls/include-helper.ts +40 -75
  387. package/src/urls/include-provider.ts +71 -0
  388. package/src/urls/index.ts +2 -11
  389. package/src/urls/path-helper-types.ts +102 -23
  390. package/src/urls/path-helper.ts +62 -111
  391. package/src/urls/pattern-types.ts +84 -19
  392. package/src/urls/response-types.ts +25 -22
  393. package/src/urls/type-extraction.ts +98 -154
  394. package/src/urls/urls-function.ts +1 -19
  395. package/src/use-loader.tsx +346 -89
  396. package/src/vercel/index.ts +11 -0
  397. package/src/vercel/tracing.ts +88 -0
  398. package/src/vite/debug.ts +185 -0
  399. package/src/vite/discovery/bundle-postprocess.ts +36 -38
  400. package/src/vite/discovery/dev-prerender-cache.ts +117 -0
  401. package/src/vite/discovery/discover-routers.ts +130 -85
  402. package/src/vite/discovery/discovery-errors.ts +255 -0
  403. package/src/vite/discovery/gate-state.ts +171 -0
  404. package/src/vite/discovery/prerender-collection.ts +214 -132
  405. package/src/vite/discovery/route-types-writer.ts +40 -84
  406. package/src/vite/discovery/self-gen-tracking.ts +27 -1
  407. package/src/vite/discovery/state.ts +57 -6
  408. package/src/vite/discovery/virtual-module-codegen.ts +14 -34
  409. package/src/vite/index.ts +15 -0
  410. package/src/vite/inject-client-debug.ts +88 -0
  411. package/src/vite/plugin-types.ts +234 -62
  412. package/src/vite/plugins/cjs-to-esm.ts +16 -19
  413. package/src/vite/plugins/client-ref-dedup.ts +16 -11
  414. package/src/vite/plugins/client-ref-hashing.ts +28 -15
  415. package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
  416. package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
  417. package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
  418. package/src/vite/plugins/expose-action-id.ts +49 -98
  419. package/src/vite/plugins/expose-id-utils.ts +96 -51
  420. package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
  421. package/src/vite/plugins/expose-ids/handler-transform.ts +15 -64
  422. package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
  423. package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
  424. package/src/vite/plugins/expose-internal-ids.ts +553 -317
  425. package/src/vite/plugins/performance-tracks.ts +89 -0
  426. package/src/vite/plugins/refresh-cmd.ts +89 -27
  427. package/src/vite/plugins/use-cache-transform.ts +73 -83
  428. package/src/vite/plugins/vercel-output.ts +384 -0
  429. package/src/vite/plugins/version-injector.ts +40 -29
  430. package/src/vite/plugins/version-plugin.ts +46 -37
  431. package/src/vite/plugins/virtual-entries.ts +138 -27
  432. package/src/vite/rango.ts +353 -303
  433. package/src/vite/router-discovery.ts +1090 -166
  434. package/src/vite/utils/ast-handler-extract.ts +26 -35
  435. package/src/vite/utils/banner.ts +4 -4
  436. package/src/vite/utils/bundle-analysis.ts +10 -15
  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 +4 -59
  441. package/src/vite/utils/package-resolution.ts +20 -52
  442. package/src/vite/utils/prerender-utils.ts +98 -38
  443. package/src/vite/utils/shared-utils.ts +144 -44
  444. package/src/browser/action-response-classifier.ts +0 -99
  445. package/src/browser/react/use-client-cache.ts +0 -58
  446. package/src/browser/shallow.ts +0 -40
  447. package/src/handles/index.ts +0 -7
  448. package/src/network-error-thrower.tsx +0 -23
  449. package/src/router/middleware-cookies.ts +0 -55
@@ -0,0 +1,76 @@
1
+ // Node ESM loader hook that resolves `cloudflare:*` imports to the same
2
+ // stub ESM the Vite transform produces for rewritten specifiers.
3
+ //
4
+ // Why both? The Vite transform (cloudflare-protocol-stub.ts) catches
5
+ // imports in modules that flow through Vite's plugin pipeline — covers
6
+ // user source and any node_modules package Vite fetches and transforms.
7
+ // But Vite/Rollup externalize certain packages (e.g. `partyserver`,
8
+ // which has `import { DurableObject, env } from "cloudflare:workers"`
9
+ // at its top level, and similar "workerd-native" libraries). Externalized
10
+ // modules bypass the transform: Rollup hands their resolution to Node's
11
+ // native ESM loader, which rejects URL-scheme specifiers. This loader
12
+ // hook registers via `module.register()` from `createTempRscServer` and
13
+ // intercepts `cloudflare:*` at Node's resolve layer — before the default
14
+ // loader throws ERR_UNSUPPORTED_ESM_URL_SCHEME.
15
+ //
16
+ // Lifecycle: the hook runs in a dedicated worker thread (Node ESM loader
17
+ // architecture) with its own globalThis. It cannot see the main thread's
18
+ // `__rango_build_env__` bridge, so the `env` export here is always `{}`.
19
+ // That's fine in practice — externalized libraries don't typically touch
20
+ // `env` at module top level; they read it at request time in workerd
21
+ // where the real module exists. Build-time prerender handlers in user
22
+ // source DO read `env`, but they flow through the Vite transform (which
23
+ // does bridge `env` from `getPlatformProxy()`), not through this loader.
24
+ //
25
+ // Keep STUBS in sync with cloudflare-protocol-stub.ts — both paths need
26
+ // to hand out the same base classes.
27
+
28
+ const CF_PREFIX = "cloudflare:";
29
+
30
+ const STUBS = {
31
+ "cloudflare:workers": `
32
+ export class DurableObject { constructor(_ctx, _env) {} }
33
+ export class WorkerEntrypoint { constructor(_ctx, _env) {} }
34
+ export class WorkflowEntrypoint { constructor(_ctx, _env) {} }
35
+ export class RpcTarget {}
36
+ export const env = {};
37
+ export default {};
38
+ `,
39
+ "cloudflare:email": `
40
+ export class EmailMessage { constructor(_from, _to, _raw) {} }
41
+ export default {};
42
+ `,
43
+ "cloudflare:sockets": `
44
+ export function connect() { return {}; }
45
+ export default {};
46
+ `,
47
+ "cloudflare:workflows": `
48
+ export class NonRetryableError extends Error {
49
+ constructor(message, name) { super(message); this.name = name ?? "NonRetryableError"; }
50
+ }
51
+ export default {};
52
+ `,
53
+ };
54
+
55
+ // Policy: unknown `cloudflare:*` specifiers resolve permissively to an
56
+ // empty default export rather than throwing. Same reasoning as
57
+ // cloudflare-protocol-stub.ts's FALLBACK_STUB — we prioritize
58
+ // dependency-graph resilience over strict validation, because third-party
59
+ // packages can pull `cloudflare:*` modules we haven't curated.
60
+ const FALLBACK_STUB = `export default {};\n`;
61
+
62
+ function dataUrlFor(specifier) {
63
+ const body = STUBS[specifier] ?? FALLBACK_STUB;
64
+ return "data:text/javascript;base64," + Buffer.from(body).toString("base64");
65
+ }
66
+
67
+ export async function resolve(specifier, context, nextResolve) {
68
+ if (specifier.startsWith(CF_PREFIX)) {
69
+ return {
70
+ shortCircuit: true,
71
+ url: dataUrlFor(specifier),
72
+ format: "module",
73
+ };
74
+ }
75
+ return nextResolve(specifier, context);
76
+ }
@@ -0,0 +1,194 @@
1
+ import type { Plugin } from "vite";
2
+
3
+ const VIRTUAL_PREFIX = "virtual:rango-cloudflare-stub-";
4
+ const NULL_PREFIX = "\0" + VIRTUAL_PREFIX;
5
+ const CF_PREFIX = "cloudflare:";
6
+
7
+ /**
8
+ * `globalThis` key the `cloudflare:workers` stub reads to populate its
9
+ * `env` export. Router discovery sets this to the resolved `buildEnv`
10
+ * proxy (from `wrangler.getPlatformProxy()` when `buildEnv: "auto"` is
11
+ * configured, or a user-supplied object otherwise) before importing the
12
+ * worker entry, and clears it after discovery disposes the proxy. When
13
+ * unset, the stub's `env` falls back to `{}`.
14
+ *
15
+ * Using `globalThis` is the only cross-module bridge that works here:
16
+ * the stub's `load` hook returns source text, not a live closure, but
17
+ * the stub module is evaluated in the same Node process as the
18
+ * discovery plugin — so reading a global at module-evaluation time
19
+ * reaches whatever the plugin assigned there. A symbol key would be
20
+ * cleaner in-process but awkward to name from the stub source.
21
+ *
22
+ * @internal
23
+ */
24
+ export const BUILD_ENV_GLOBAL_KEY = "__rango_build_env__";
25
+
26
+ const SOURCE_EXT_RE = /\.[mc]?[jt]sx?$/;
27
+
28
+ const IMPORT_NODE_TYPES = new Set([
29
+ "ImportDeclaration",
30
+ "ImportExpression",
31
+ "ExportNamedDeclaration",
32
+ "ExportAllDeclaration",
33
+ ]);
34
+
35
+ const STUBS: Record<string, string> = {
36
+ "cloudflare:workers": `
37
+ export class DurableObject { constructor(_ctx, _env) {} }
38
+ export class WorkerEntrypoint { constructor(_ctx, _env) {} }
39
+ export class WorkflowEntrypoint { constructor(_ctx, _env) {} }
40
+ export class RpcTarget {}
41
+ export const env = globalThis[${JSON.stringify(BUILD_ENV_GLOBAL_KEY)}] ?? {};
42
+ export default {};
43
+ `,
44
+ "cloudflare:email": `
45
+ export class EmailMessage { constructor(_from, _to, _raw) {} }
46
+ export default {};
47
+ `,
48
+ "cloudflare:sockets": `
49
+ export function connect() { return {}; }
50
+ export default {};
51
+ `,
52
+ "cloudflare:workflows": `
53
+ export class NonRetryableError extends Error {
54
+ constructor(message, name) { super(message); this.name = name ?? "NonRetryableError"; }
55
+ }
56
+ export default {};
57
+ `,
58
+ };
59
+
60
+ const FALLBACK_STUB = `export default {};\n`;
61
+
62
+ interface AstNode {
63
+ type: string;
64
+ start?: number;
65
+ end?: number;
66
+ source?: AstNode | null;
67
+ value?: unknown;
68
+ [key: string]: unknown;
69
+ }
70
+
71
+ /**
72
+ * Stubs `cloudflare:*` imports for the discovery-time Node Vite server.
73
+ *
74
+ * Discovery only evaluates user module top-level code — it never invokes
75
+ * DurableObject / WorkerEntrypoint / Workflow handlers — so empty base
76
+ * classes are enough for `class X extends DurableObject {}` declarations
77
+ * to load in Node, where `cloudflare:*` is otherwise unresolvable.
78
+ *
79
+ * Interception point: a transform hook parses source with Rollup's
80
+ * plugin-context parser (`this.parse`) and rewrites only real import
81
+ * specifier spans (`import ... from "cloudflare:xxx"`,
82
+ * `import("cloudflare:xxx")`, `export ... from "cloudflare:xxx"`) to a
83
+ * plain virtual module name (`virtual:rango-cloudflare-stub-xxx`).
84
+ * This must be done in transform because Vite's module runner routes
85
+ * URL-scheme specifiers straight to Node's native ESM loader without
86
+ * consulting plugin `resolveId` hooks. Using the AST (instead of a
87
+ * text regex or a permissive lexer) guarantees that strings,
88
+ * comments, and template literals that merely contain import-like
89
+ * text are never mutated — the walker only looks at the four import
90
+ * node types.
91
+ *
92
+ * The transform runs on user source AND on compiled node_modules
93
+ * output: real-world CF packages (e.g. the Cloudflare Agents SDK)
94
+ * ship compiled JS that contains `import ... from "cloudflare:email"`
95
+ * and similar, so excluding node_modules would leave those imports
96
+ * unrewritten. Cost is small because the early exit (`code.includes`)
97
+ * skips files with no cloudflare: mention.
98
+ *
99
+ * The plugin intentionally runs at Vite's default ordering (no
100
+ * `enforce: "pre"`) so TS/JSX has already been compiled to plain JS
101
+ * by the time `this.parse` runs — acorn doesn't understand
102
+ * non-standard syntax.
103
+ *
104
+ * `cloudflare:workers`, `cloudflare:email`, `cloudflare:sockets`, and
105
+ * `cloudflare:workflows` each get curated stubs with the well-known
106
+ * symbols that appear in top-level `extends` positions. Any other
107
+ * `cloudflare:*` specifier falls back to an empty default export —
108
+ * discovery never executes the handlers, so an empty module is safe
109
+ * for anything the graph pulls in transitively.
110
+ *
111
+ * Only registered in the discovery temp server, not the user's runtime
112
+ * config.
113
+ * @internal
114
+ */
115
+ export function createCloudflareProtocolStubPlugin(): Plugin {
116
+ return {
117
+ name: "@rangojs/router:cloudflare-protocol-stub",
118
+ transform(code, id) {
119
+ const cleanId = id.split("?")[0] ?? id;
120
+ if (!SOURCE_EXT_RE.test(cleanId)) return null;
121
+ if (!code.includes(CF_PREFIX)) return null;
122
+
123
+ let ast: AstNode;
124
+ try {
125
+ ast = this.parse(code, { lang: "tsx" }) as unknown as AstNode;
126
+ } catch {
127
+ // Malformed source — let a downstream plugin surface the parse error.
128
+ return null;
129
+ }
130
+
131
+ const hits: Array<{ start: number; end: number; value: string }> = [];
132
+ walk(ast, (node) => {
133
+ if (!IMPORT_NODE_TYPES.has(node.type)) return;
134
+ const source = node.source;
135
+ if (!source || source.type !== "Literal") return;
136
+ if (typeof source.value !== "string") return;
137
+ if (!source.value.startsWith(CF_PREFIX)) return;
138
+ if (typeof source.start !== "number" || typeof source.end !== "number")
139
+ return;
140
+ hits.push({
141
+ start: source.start,
142
+ end: source.end,
143
+ value: source.value,
144
+ });
145
+ });
146
+
147
+ if (hits.length === 0) return null;
148
+
149
+ hits.sort((a, b) => b.start - a.start);
150
+ let out = code;
151
+ for (const hit of hits) {
152
+ const submodule = hit.value.slice(CF_PREFIX.length);
153
+ const quote = code[hit.start] === "'" ? "'" : '"';
154
+ out =
155
+ out.slice(0, hit.start) +
156
+ quote +
157
+ VIRTUAL_PREFIX +
158
+ submodule +
159
+ quote +
160
+ out.slice(hit.end);
161
+ }
162
+ return { code: out, map: null };
163
+ },
164
+ resolveId(id) {
165
+ if (id.startsWith(VIRTUAL_PREFIX)) {
166
+ return "\0" + id;
167
+ }
168
+ return null;
169
+ },
170
+ load(id) {
171
+ if (!id.startsWith(NULL_PREFIX)) return null;
172
+ const submodule = id.slice(NULL_PREFIX.length);
173
+ const specifier = CF_PREFIX + submodule;
174
+ return STUBS[specifier] ?? FALLBACK_STUB;
175
+ },
176
+ };
177
+ }
178
+
179
+ function walk(node: unknown, visit: (n: AstNode) => void): void {
180
+ if (!node || typeof node !== "object") return;
181
+ if (Array.isArray(node)) {
182
+ for (const child of node) walk(child, visit);
183
+ return;
184
+ }
185
+ const n = node as AstNode;
186
+ if (typeof n.type !== "string") return;
187
+ visit(n);
188
+ for (const key in n) {
189
+ if (key === "loc" || key === "start" || key === "end" || key === "range") {
190
+ continue;
191
+ }
192
+ walk(n[key], visit);
193
+ }
194
+ }
@@ -3,10 +3,10 @@ import MagicString from "magic-string";
3
3
  import path from "node:path";
4
4
  import fs from "node:fs";
5
5
  import { normalizePath } from "./expose-id-utils.js";
6
+ import { createRangoDebugger, createCounter, NS } from "../debug.js";
7
+
8
+ const debug = createRangoDebugger(NS.transform);
6
9
 
7
- /**
8
- * Type for the RSC plugin's manager API
9
- */
10
10
  interface RscPluginManager {
11
11
  serverReferenceMetaMap: Record<
12
12
  string,
@@ -23,14 +23,9 @@ interface RscPluginApi {
23
23
  manager: RscPluginManager;
24
24
  }
25
25
 
26
- /**
27
- * Get the RSC plugin's API from Vite config
28
- */
29
26
  function getRscPluginApi(config: ResolvedConfig): RscPluginApi | undefined {
30
- // Try by name first
31
27
  let plugin = config.plugins.find((p) => p.name === "rsc:minimal");
32
28
 
33
- // Fallback: find by API structure if name lookup fails
34
29
  if (!plugin) {
35
30
  plugin = config.plugins.find(
36
31
  (p) =>
@@ -39,7 +34,7 @@ function getRscPluginApi(config: ResolvedConfig): RscPluginApi | undefined {
39
34
  );
40
35
  if (plugin) {
41
36
  console.warn(
42
- `[rsc-router:expose-action-id] RSC plugin found by API structure (name: "${plugin.name}"). ` +
37
+ `[rango:expose-action-id] RSC plugin found by API structure (name: "${plugin.name}"). ` +
43
38
  `Consider updating the name lookup if the plugin was renamed.`,
44
39
  );
45
40
  }
@@ -59,13 +54,11 @@ function getRscPluginApi(config: ResolvedConfig): RscPluginApi | undefined {
59
54
  function isUseServerModule(filePath: string): boolean {
60
55
  try {
61
56
  const content = fs.readFileSync(filePath, "utf-8");
62
- // Remove leading comments and whitespace to find the first meaningful content
63
57
  const trimmed = content
64
- .replace(/^\s*\/\/[^\n]*\n/gm, "") // Remove single-line comments
65
- .replace(/^\s*\/\*[\s\S]*?\*\/\s*/gm, "") // Remove multi-line comments
58
+ .replace(/^\s*\/\/[^\n]*\n/gm, "")
59
+ .replace(/^\s*\/\*[\s\S]*?\*\/\s*/gm, "")
66
60
  .trimStart();
67
61
 
68
- // Check if the file starts with "use server" directive
69
62
  return (
70
63
  trimmed.startsWith('"use server"') || trimmed.startsWith("'use server'")
71
64
  );
@@ -74,18 +67,6 @@ function isUseServerModule(filePath: string): boolean {
74
67
  }
75
68
  }
76
69
 
77
- /**
78
- * Transform code to expose action IDs on createServerReference calls.
79
- * Wraps each call with an IIFE that attaches $id to the returned function.
80
- *
81
- * @param code - The source code to transform
82
- * @param sourceId - The source file identifier (for sourcemap)
83
- * @param hashToFileMap - Optional mapping from hash to file path (for server bundles)
84
- */
85
- /**
86
- * Apply createServerReference wrapping to a MagicString instance.
87
- * Returns true if any changes were made.
88
- */
89
70
  function applyServerReferenceWrapping(
90
71
  code: string,
91
72
  s: MagicString,
@@ -95,11 +76,6 @@ function applyServerReferenceWrapping(
95
76
  return false;
96
77
  }
97
78
 
98
- // Match: createServerReference("hash#actionName", ...) or $$ReactClient.createServerReference(...)
99
- // The RSC plugin uses $$ReactClient namespace in transformed code.
100
- // Note: [^)]* cannot handle nested parens in trailing args. This is safe in practice
101
- // because the RSC plugin always generates simple variable references (e.g., callServer)
102
- // as the second argument, never nested function calls.
103
79
  const pattern =
104
80
  /((?:\$\$\w+\.)?createServerReference)\(("[^"]+#[^"]+")([^)]*)\)/g;
105
81
 
@@ -112,23 +88,19 @@ function applyServerReferenceWrapping(
112
88
  const start = match.index;
113
89
  const end = start + fullMatch.length;
114
90
 
115
- // Parse the ID to potentially replace hash with file path
116
91
  let finalIdArg = idArg;
117
92
  if (hashToFileMap) {
118
- // idArg is like '"hash#actionName"', extract the parts
119
93
  const idValue = idArg.slice(1, -1); // Remove quotes
120
94
  const hashMatch = idValue.match(/^([^#]+)#(.+)$/);
121
95
  if (hashMatch) {
122
96
  const [, hash, actionName] = hashMatch;
123
97
  const filePath = hashToFileMap.get(hash);
124
98
  if (filePath) {
125
- // Replace hash with file path for server-side
126
99
  finalIdArg = `"${filePath}#${actionName}"`;
127
100
  }
128
101
  }
129
102
  }
130
103
 
131
- // Wrap the createServerReference call to attach $$id to the returned function
132
104
  const replacement = `(function(fn) { fn.$$id = ${finalIdArg}; return fn; })(${fnCall}(${idArg}${rest}))`;
133
105
  s.overwrite(start, end, replacement);
134
106
  }
@@ -152,29 +124,6 @@ function transformServerReferences(
152
124
  };
153
125
  }
154
126
 
155
- /**
156
- * Transform registerServerReference calls in server bundles to use file paths instead of hashes.
157
- * Pattern: registerServerReference(fn, "hash", "exportName")
158
- * React's registerServerReference sets $$id = hash + "#" + exportName
159
- * By replacing the hash with file path, $$id will contain the file path for revalidation matching.
160
- *
161
- * Only actions from module-level "use server" files are transformed.
162
- * Inline actions (defined in RSC components with "use server" inside a function) are NOT in
163
- * hashToFileMap and keep their hashed IDs. This is intentional for client security:
164
- * - Module-level "use server" files: shared action modules, file path helps revalidation
165
- * - Inline actions: one-off actions in RSC, hash ID prevents file path exposure to client
166
- *
167
- * @param code - The source code to transform
168
- * @param sourceId - The source file identifier (for sourcemap)
169
- * @param hashToFileMap - Mapping from hash to file path (only module-level "use server" files)
170
- */
171
- /**
172
- * Apply registerServerReference wrapping to a MagicString instance.
173
- * Returns true if any changes were made.
174
- *
175
- * Only actions from module-level "use server" files are transformed.
176
- * Inline actions keep their hashed IDs for client security.
177
- */
178
127
  function applyRegisterReferenceWrapping(
179
128
  code: string,
180
129
  s: MagicString,
@@ -184,8 +133,6 @@ function applyRegisterReferenceWrapping(
184
133
  return false;
185
134
  }
186
135
 
187
- // Match: registerServerReference(fn, "hash", "exportName")
188
- // The hash is the second argument, exportName is the third
189
136
  const pattern =
190
137
  /registerServerReference\(([^,]+),\s*"([^"]+)",\s*"([^"]+)"\)/g;
191
138
 
@@ -197,15 +144,9 @@ function applyRegisterReferenceWrapping(
197
144
  const start = match.index;
198
145
  const end = start + fullMatch.length;
199
146
 
200
- // Look up the file path for this hash
201
147
  const filePath = hashToFileMap.get(hash);
202
148
  if (filePath) {
203
149
  hasChanges = true;
204
- // WRAP the call to add $id property with file path
205
- // Keep the original hash for React's action registry (so loadServerAction works)
206
- // Add $id (single dollar) with file path for revalidation matching
207
- // Note: We use $id instead of $$id because React's registerServerReference
208
- // sets $$id as a non-writable property
209
150
  const filePathId = `${filePath}#${exportName}`;
210
151
  const replacement = `(function(fn) { fn.$id = "${filePathId}"; return fn; })(registerServerReference(${fnArg}, "${hash}", "${exportName}"))`;
211
152
  s.overwrite(start, end, replacement);
@@ -254,6 +195,8 @@ export function exposeActionId(): Plugin {
254
195
  let isBuild = false;
255
196
  let hashToFileMap: Map<string, string> | undefined;
256
197
  let rscPluginApi: RscPluginApi | undefined;
198
+ const counterTransform = createCounter(debug, "expose-action-id transform");
199
+ const counterRender = createCounter(debug, "expose-action-id renderChunk");
257
200
 
258
201
  return {
259
202
  name: "@rangojs/router:expose-action-id",
@@ -268,6 +211,11 @@ export function exposeActionId(): Plugin {
268
211
  rscPluginApi = getRscPluginApi(config);
269
212
  },
270
213
 
214
+ buildEnd() {
215
+ counterTransform?.flush();
216
+ counterRender?.flush();
217
+ },
218
+
271
219
  buildStart() {
272
220
  // Verify RSC plugin is present at build start (after all config hooks have run)
273
221
  // This allows rsc-router:rsc-integration to dynamically add the RSC plugin
@@ -277,10 +225,8 @@ export function exposeActionId(): Plugin {
277
225
 
278
226
  if (!rscPluginApi) {
279
227
  throw new Error(
280
- "[rsc-router] Could not find @vitejs/plugin-rsc. " +
281
- "@rangojs/router requires the Vite RSC plugin.\n" +
282
- "The RSC plugin should be included automatically. If you disabled it with\n" +
283
- "rango({ rsc: false }), add rsc() before rango() in your config.",
228
+ "[rango] Could not find @vitejs/plugin-rsc. " +
229
+ "@rangojs/router requires the Vite RSC plugin, which is included automatically by rango().",
284
230
  );
285
231
  }
286
232
 
@@ -326,40 +272,45 @@ export function exposeActionId(): Plugin {
326
272
  return;
327
273
  }
328
274
 
329
- // Dev mode: no hash-to-file mapping needed (IDs are already file paths)
330
- return transformServerReferences(code, id);
275
+ const start = counterTransform ? performance.now() : 0;
276
+ try {
277
+ return transformServerReferences(code, id);
278
+ } finally {
279
+ counterTransform?.record(id, performance.now() - start);
280
+ }
331
281
  },
332
282
 
333
- // Build mode: renderChunk runs after all transforms and bundling complete
334
283
  renderChunk(code, chunk) {
335
- // Only RSC bundle should get file paths for revalidation matching
336
- // SSR bundle must NOT use file paths because client components run there
337
- // and need to match the client bundle during hydration (otherwise: error #418)
338
- const isRscEnv = this.environment?.name === "rsc";
339
-
340
- // Only use file path mapping for RSC environment
341
- const effectiveMap = isRscEnv ? hashToFileMap : undefined;
342
-
343
- // For RSC bundles, both createServerReference and registerServerReference
344
- // may need transforming. Use a single MagicString for correct sourcemaps.
345
- if (isRscEnv && hashToFileMap) {
346
- const s = new MagicString(code);
347
- const changed1 = applyServerReferenceWrapping(code, s, effectiveMap);
348
- const changed2 = applyRegisterReferenceWrapping(code, s, hashToFileMap);
349
- if (changed1 || changed2) {
350
- return {
351
- code: s.toString(),
352
- map: s.generateMap({
353
- source: chunk.fileName,
354
- includeContent: true,
355
- }),
356
- };
284
+ const start = counterRender ? performance.now() : 0;
285
+ try {
286
+ const isRscEnv = this.environment?.name === "rsc";
287
+
288
+ const effectiveMap = isRscEnv ? hashToFileMap : undefined;
289
+
290
+ if (isRscEnv && hashToFileMap) {
291
+ const s = new MagicString(code);
292
+ const changed1 = applyServerReferenceWrapping(code, s, effectiveMap);
293
+ const changed2 = applyRegisterReferenceWrapping(
294
+ code,
295
+ s,
296
+ hashToFileMap,
297
+ );
298
+ if (changed1 || changed2) {
299
+ return {
300
+ code: s.toString(),
301
+ map: s.generateMap({
302
+ source: chunk.fileName,
303
+ includeContent: true,
304
+ }),
305
+ };
306
+ }
307
+ return null;
357
308
  }
358
- return null;
359
- }
360
309
 
361
- // Non-RSC environments: only transform createServerReference calls
362
- return transformServerReferences(code, chunk.fileName, effectiveMap);
310
+ return transformServerReferences(code, chunk.fileName, effectiveMap);
311
+ } finally {
312
+ counterRender?.record(chunk.fileName, performance.now() - start);
313
+ }
363
314
  },
364
315
  };
365
316
  }