@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
@@ -1,9 +1,5 @@
1
1
  import type MagicString from "magic-string";
2
- import { hashInlineId, buildExportMap } from "./expose-id-utils.ts";
3
-
4
- // ---------------------------------------------------------------------------
5
- // Types
6
- // ---------------------------------------------------------------------------
2
+ import { hashInlineId, buildExportMap } from "../plugins/expose-id-utils.js";
7
3
 
8
4
  /** Minimal ESTree Program node — avoids importing from `rollup` (not a direct dep). */
9
5
  interface ProgramNode {
@@ -27,14 +23,14 @@ export interface HandlerCallSite {
27
23
  export interface VirtualHandlerEntry {
28
24
  originalModuleId: string;
29
25
  imports: string[];
26
+ declarations: string[];
30
27
  handlerCode: string;
31
28
  exportName: string;
32
29
  }
33
30
 
34
31
  function isDirectivePrologueStatement(node: any): boolean {
35
32
  return (
36
- node?.type === "ExpressionStatement" &&
37
- typeof node.directive === "string"
33
+ node?.type === "ExpressionStatement" && typeof node.directive === "string"
38
34
  );
39
35
  }
40
36
 
@@ -48,7 +44,7 @@ function findImportInsertionPos(
48
44
  ): number {
49
45
  let program: ProgramNode;
50
46
  try {
51
- program = parseAst(code, { jsx: true });
47
+ program = parseAst(code, { lang: "tsx" });
52
48
  } catch {
53
49
  return 0;
54
50
  }
@@ -70,10 +66,6 @@ function findImportInsertionPos(
70
66
  return insertionPos;
71
67
  }
72
68
 
73
- // ---------------------------------------------------------------------------
74
- // AST walking helper
75
- // ---------------------------------------------------------------------------
76
-
77
69
  /**
78
70
  * Recursively walk an ESTree AST node, calling `enter` on each node.
79
71
  * Parent is passed for context.
@@ -99,7 +91,11 @@ function walkNode(
99
91
  walkNode(item, node, ancestors, enter);
100
92
  }
101
93
  }
102
- } else if (child && typeof child === "object" && typeof child.type === "string") {
94
+ } else if (
95
+ child &&
96
+ typeof child === "object" &&
97
+ typeof child.type === "string"
98
+ ) {
103
99
  walkNode(child, node, ancestors, enter);
104
100
  }
105
101
  }
@@ -107,10 +103,6 @@ function walkNode(
107
103
  ancestors.pop();
108
104
  }
109
105
 
110
- // ---------------------------------------------------------------------------
111
- // AST analysis
112
- // ---------------------------------------------------------------------------
113
-
114
106
  /**
115
107
  * Parse the file with Vite's parseAst and find all calls to `fnName`.
116
108
  * Distinguishes between `export const X = fnName(...)` (exportInfo set)
@@ -123,7 +115,7 @@ export function findHandlerCalls(
123
115
  ): HandlerCallSite[] {
124
116
  let program: ProgramNode;
125
117
  try {
126
- program = parseAst(code, { jsx: true });
118
+ program = parseAst(code, { lang: "tsx" });
127
119
  } catch {
128
120
  return [];
129
121
  }
@@ -158,8 +150,10 @@ export function findHandlerCalls(
158
150
 
159
151
  if (parent?.type === "VariableDeclarator" && parent.init === node) {
160
152
  // ancestors: [..., ExportNamedDecl, VarDecl, VarDeclarator, CallExpr]
161
- const grandParent = ancestors.length >= 3 ? ancestors[ancestors.length - 3] : null;
162
- const greatGrandParent = ancestors.length >= 4 ? ancestors[ancestors.length - 4] : null;
153
+ const grandParent =
154
+ ancestors.length >= 3 ? ancestors[ancestors.length - 3] : null;
155
+ const greatGrandParent =
156
+ ancestors.length >= 4 ? ancestors[ancestors.length - 4] : null;
163
157
 
164
158
  if (
165
159
  grandParent?.type === "VariableDeclaration" &&
@@ -233,7 +227,7 @@ export function getImportedLocalNames(
233
227
  parseAst: (code: string, options?: any) => ProgramNode,
234
228
  ): Set<string> {
235
229
  try {
236
- const program = parseAst(code, { jsx: true });
230
+ const program = parseAst(code, { lang: "tsx" });
237
231
  return getImportedLocalNamesFromProgram(program, importedName);
238
232
  } catch {
239
233
  return new Set<string>();
@@ -250,7 +244,7 @@ export function extractImportDeclarations(
250
244
  ): string[] {
251
245
  let program: ProgramNode;
252
246
  try {
253
- program = parseAst(code, { jsx: true });
247
+ program = parseAst(code, { lang: "tsx" });
254
248
  } catch {
255
249
  return [];
256
250
  }
@@ -264,9 +258,168 @@ export function extractImportDeclarations(
264
258
  return imports;
265
259
  }
266
260
 
267
- // ---------------------------------------------------------------------------
268
- // Transform
269
- // ---------------------------------------------------------------------------
261
+ /**
262
+ * Check if an expression AST subtree is "inert" -- safe to evaluate eagerly
263
+ * without referencing import bindings. Inert expressions contain only literals,
264
+ * arrays/objects of inert values, template literals with inert expressions,
265
+ * and unary/binary operators on inert operands.
266
+ *
267
+ * Function/arrow expressions are NOT inert (they're lazy -- handled separately).
268
+ * Identifiers and member expressions are NOT inert (may reference imports).
269
+ *
270
+ * This check prevents TDZ errors when declarations are moved to virtual
271
+ * modules that end up in separate Rollup chunks with circular dependencies.
272
+ */
273
+ function isInertExpression(node: any): boolean {
274
+ if (!node) return false;
275
+ switch (node.type) {
276
+ case "Literal":
277
+ return true;
278
+ case "TemplateLiteral":
279
+ return (node.expressions ?? []).every((e: any) => isInertExpression(e));
280
+ case "ArrayExpression":
281
+ return (node.elements ?? []).every(
282
+ (e: any) => e === null || isInertExpression(e),
283
+ );
284
+ case "ObjectExpression":
285
+ return (node.properties ?? []).every((p: any) => {
286
+ // A spread inside an object (`{ ...x }`) is inert iff `x` is inert.
287
+ if (p.type === "SpreadElement" || p.type === "RestElement") {
288
+ return isInertExpression(p.argument);
289
+ }
290
+ return (
291
+ p.type === "Property" &&
292
+ (!p.computed || isInertExpression(p.key)) &&
293
+ isInertExpression(p.value)
294
+ );
295
+ });
296
+ case "UnaryExpression":
297
+ return isInertExpression(node.argument);
298
+ case "BinaryExpression":
299
+ return isInertExpression(node.left) && isInertExpression(node.right);
300
+ case "LogicalExpression":
301
+ return isInertExpression(node.left) && isInertExpression(node.right);
302
+ case "ConditionalExpression":
303
+ return (
304
+ isInertExpression(node.test) &&
305
+ isInertExpression(node.consequent) &&
306
+ isInertExpression(node.alternate)
307
+ );
308
+ case "SpreadElement":
309
+ return isInertExpression(node.argument);
310
+ default:
311
+ return false;
312
+ }
313
+ }
314
+
315
+ /**
316
+ * Check if a variable declarator's init is safe for inclusion in a virtual
317
+ * module. Safe initializers are:
318
+ * 1. Function/arrow expressions (body is lazy, no TDZ risk)
319
+ * 2. Inert expressions (no identifier references, no TDZ risk)
320
+ *
321
+ * Declarations that reference identifiers at the top level (e.g.
322
+ * `const VT = React.Fragment`) are NOT safe -- when the virtual module
323
+ * is bundled into a separate Rollup chunk, circular chunk dependencies
324
+ * can cause "Cannot access X before initialization" TDZ errors.
325
+ */
326
+ function isSafeDeclaratorInit(init: any): boolean {
327
+ if (!init) return true; // `let x;` with no init is safe
328
+ if (
329
+ init.type === "ArrowFunctionExpression" ||
330
+ init.type === "FunctionExpression"
331
+ ) {
332
+ return true;
333
+ }
334
+ return isInertExpression(init);
335
+ }
336
+
337
+ /**
338
+ * Check if all declarators in a VariableDeclaration have safe initializers
339
+ * and none is a handler call (Static/Prerender).
340
+ */
341
+ function isSafeVariableDeclaration(
342
+ node: any,
343
+ handlerNames: Set<string>,
344
+ ): boolean {
345
+ if (node.type !== "VariableDeclaration") return false;
346
+ return node.declarations.every(
347
+ (d: any) =>
348
+ isSafeDeclaratorInit(d.init) &&
349
+ !(
350
+ d.init?.type === "CallExpression" &&
351
+ d.init.callee?.type === "Identifier" &&
352
+ handlerNames.has(d.init.callee.name)
353
+ ),
354
+ );
355
+ }
356
+
357
+ /**
358
+ * Extract module-level declarations that are safe for inclusion in virtual
359
+ * modules. "Safe" means the declaration can be eagerly evaluated without
360
+ * referencing import bindings, preventing TDZ errors in separate chunks.
361
+ *
362
+ * Included: function declarations, arrow/function expression inits, and
363
+ * variable inits that are inert (pure literals, arrays, objects).
364
+ * Excluded: declarations that reference identifiers at init time (may
365
+ * reference imports causing TDZ), handler call declarations (circular),
366
+ * class declarations (field initializers can reference imports).
367
+ *
368
+ * Strips export keywords so declarations work as plain locals.
369
+ * Rollup tree-shakes unused declarations from virtual modules.
370
+ */
371
+ export function extractModuleLevelDeclarations(
372
+ code: string,
373
+ parseAst: (code: string, options?: any) => ProgramNode,
374
+ handlerNames: Set<string>,
375
+ ): string[] {
376
+ let program: ProgramNode;
377
+ try {
378
+ program = parseAst(code, { lang: "tsx" });
379
+ } catch {
380
+ return [];
381
+ }
382
+
383
+ const declarations: string[] = [];
384
+ for (const node of program.body as any[]) {
385
+ // Skip imports (handled by extractImportDeclarations)
386
+ if (node.type === "ImportDeclaration") continue;
387
+
388
+ // VariableDeclaration -- include only if all declarators are safe
389
+ if (node.type === "VariableDeclaration") {
390
+ if (isSafeVariableDeclaration(node, handlerNames)) {
391
+ declarations.push(code.slice(node.start, node.end));
392
+ }
393
+ continue;
394
+ }
395
+
396
+ // FunctionDeclaration -- always safe (body is lazy)
397
+ if (node.type === "FunctionDeclaration") {
398
+ declarations.push(code.slice(node.start, node.end));
399
+ continue;
400
+ }
401
+
402
+ // ExportNamedDeclaration with a declaration inside -- strip the export
403
+ if (node.type === "ExportNamedDeclaration" && node.declaration) {
404
+ const decl = node.declaration;
405
+ if (decl.type === "VariableDeclaration") {
406
+ if (isSafeVariableDeclaration(decl, handlerNames)) {
407
+ declarations.push(code.slice(decl.start, decl.end));
408
+ }
409
+ } else if (decl.type === "FunctionDeclaration") {
410
+ declarations.push(code.slice(decl.start, decl.end));
411
+ }
412
+ continue;
413
+ }
414
+
415
+ // Skip: ClassDeclaration (field initializers can reference imports),
416
+ // ExportDefaultDeclaration, ExportAllDeclaration,
417
+ // ExportNamedDeclaration without declaration (re-exports),
418
+ // ExpressionStatement (side effects), etc.
419
+ }
420
+
421
+ return declarations;
422
+ }
270
423
 
271
424
  /**
272
425
  * Transform inline handler calls by extracting them into virtual modules.
@@ -295,19 +448,30 @@ export function transformInlineHandlers(
295
448
 
296
449
  const imports = extractImportDeclarations(code, parseAst);
297
450
 
298
- // Track line occurrences for same-line collision handling
299
- const lineCounts = new Map<number, number>();
451
+ // Collect local names for both Static and Prerender to exclude their
452
+ // declarations from virtual modules (avoids circular extraction).
453
+ const staticNames = getImportedLocalNames(code, "Static", parseAst);
454
+ const prerenderNames = getImportedLocalNames(code, "Prerender", parseAst);
455
+ const handlerNames = new Set([...staticNames, ...prerenderNames]);
456
+ const declarations = extractModuleLevelDeclarations(
457
+ code,
458
+ parseAst,
459
+ handlerNames,
460
+ );
300
461
 
301
462
  // Collect all import statements to prepend
302
463
  const importStatements: string[] = [];
303
464
 
304
- for (const site of inlineSites) {
305
- const lineCount = lineCounts.get(site.lineNumber) ?? 0;
306
- lineCounts.set(site.lineNumber, lineCount + 1);
307
-
308
- const hash = hashInlineId(filePath, site.lineNumber, lineCount);
465
+ for (const [siteIndex, site] of inlineSites.entries()) {
466
+ // Key the extracted handler on its source-order index (per fnName), NOT its
467
+ // line number. The id flows into BOTH the export name and the virtual module
468
+ // path (which hashId hashes for the runtime $$id), and line numbers shift
469
+ // between the prerender and production build contexts. The index is invariant
470
+ // to those shifts, keeping the prerender manifest key == the runtime id.
471
+ const hash = hashInlineId(filePath, fnName, siteIndex);
309
472
  const exportName = `__sh_${hash}`;
310
- const virtualId = `\0${virtualPrefix}${filePath}:${site.lineNumber}${lineCount > 0 ? `:${lineCount}` : ""}`;
473
+ const idSuffix = `${filePath}:${fnName}:${siteIndex}`;
474
+ const virtualId = `\0${virtualPrefix}${idSuffix}`;
311
475
 
312
476
  // Extract the full handler call expression text
313
477
  const handlerCode = code.slice(site.callStart, site.callEnd);
@@ -316,6 +480,7 @@ export function transformInlineHandlers(
316
480
  virtualRegistry.set(virtualId, {
317
481
  originalModuleId: moduleId,
318
482
  imports,
483
+ declarations,
319
484
  handlerCode,
320
485
  exportName,
321
486
  });
@@ -324,10 +489,8 @@ export function transformInlineHandlers(
324
489
  s.overwrite(site.callStart, site.callEnd, exportName);
325
490
 
326
491
  // Build the import specifier for this virtual module
327
- const importId = `${virtualPrefix}${filePath}:${site.lineNumber}${lineCount > 0 ? `:${lineCount}` : ""}`;
328
- importStatements.push(
329
- `import { ${exportName} } from "${importId}";`,
330
- );
492
+ const importId = `${virtualPrefix}${idSuffix}`;
493
+ importStatements.push(`import { ${exportName} } from "${importId}";`);
331
494
  }
332
495
 
333
496
  // Insert imports after directive prologue + existing import block
@@ -0,0 +1,36 @@
1
+ import packageJson from "../../../package.json";
2
+
3
+ export const rangoVersion: string = packageJson.version;
4
+
5
+ let _bannerPrinted = false;
6
+
7
+ export function printBanner(
8
+ mode: "dev" | "build" | "preview",
9
+ preset: string,
10
+ version: string,
11
+ ): void {
12
+ if (_bannerPrinted) return;
13
+ _bannerPrinted = true;
14
+
15
+ // ANSI codes
16
+ const dim = "\x1b[2m";
17
+ const bold = "\x1b[1m";
18
+ const reset = "\x1b[0m";
19
+
20
+ const banner = `
21
+ ${dim} ✦ ✦ ✧. . .${reset}
22
+ ${dim} ╱${reset} ${bold}╔═╗${reset}${dim} * ╱ ✦ *${reset}
23
+ ${dim} ${reset}${bold}║ ║${reset} ${bold}╔═╗${reset}${dim} * ✧. ╱${reset}
24
+ ${dim} ${reset}${bold}╔╗ ║ ║ ║ ║${reset}${dim} * ╱${reset}
25
+ ${dim} ${reset}${bold}║║ ║ ║ ║ ║ ╦═╗╔═╗╔╗╔╔═╗╔═╗${reset}${dim} ✧ ✦${reset}
26
+ ${dim} ${reset}${bold}║║ ║ ╠═╝ ║ ╠╦╝╠═╣║║║║ ╦║ ║${reset}${dim} * ✧${reset}
27
+ ${dim} ${reset}${bold}║╚═╝ ╔═══╝ ╩╚═╩ ╩╝╚╝╚═╝╚═╝${reset}${dim} ✦ . *${reset}
28
+ ${dim} ${reset}${bold}╚══╗ ║${reset}${dim} * RSC Wrangler ✧ ✦${reset}
29
+ ${dim} * ${reset}${bold}║ ║${reset}${dim} * ✧. ╱${reset}
30
+ ${dim} ${reset}${bold}═══╝ ╚════${reset}${dim} ✦ *${reset}
31
+
32
+ v${version} · ${preset} · ${mode}
33
+ `;
34
+
35
+ console.log(banner);
36
+ }
@@ -0,0 +1,132 @@
1
+ import {
2
+ skipStringOrComment,
3
+ escapeRegExp,
4
+ } from "../plugins/expose-id-utils.js";
5
+
6
+ /**
7
+ * Find matching close paren in bundled code using depth counting.
8
+ * Uses skipStringOrComment to correctly handle template literals, comments, and nested strings.
9
+ * @internal Exported for testing only.
10
+ */
11
+ export function findMatchingParenInBundle(
12
+ code: string,
13
+ openParenPos: number,
14
+ ): number {
15
+ let depth = 1;
16
+ let pos = openParenPos;
17
+ while (pos < code.length && depth > 0) {
18
+ const skipped = skipStringOrComment(code, pos);
19
+ if (skipped > pos) {
20
+ pos = skipped;
21
+ continue;
22
+ }
23
+ if (code[pos] === "(") depth++;
24
+ else if (code[pos] === ")") depth--;
25
+ pos++;
26
+ }
27
+ return depth === 0 ? pos : -1;
28
+ }
29
+
30
+ /**
31
+ * Scan a bundled chunk for handler exports and extract their names + $$id values.
32
+ * Optionally detects passthrough flag. @internal Exported for testing only.
33
+ */
34
+ export function extractHandlerExportsFromChunk(
35
+ chunkCode: string,
36
+ handlerModules: Map<string, string[]>,
37
+ fnName: string,
38
+ detectPassthrough: boolean,
39
+ ): Array<{ name: string; handlerId: string; passthrough: boolean }> {
40
+ const handlers: Array<{
41
+ name: string;
42
+ handlerId: string;
43
+ passthrough: boolean;
44
+ }> = [];
45
+
46
+ for (const [, handlerNames] of handlerModules) {
47
+ for (const name of handlerNames) {
48
+ const eName = escapeRegExp(name);
49
+ const idPattern = new RegExp(
50
+ `(?<![a-zA-Z0-9_])${eName}\\.\\$\\$id\\s*=\\s*"([^"]+)"`,
51
+ );
52
+ const match = chunkCode.match(idPattern);
53
+ if (!match) continue;
54
+
55
+ let isPassthrough = false;
56
+ if (detectPassthrough) {
57
+ const eFnName = escapeRegExp(fnName);
58
+ const callStartRe = new RegExp(
59
+ `(?:const|let|var)\\s+${eName}\\s*=\\s*${eFnName}\\s*(?:<[^>]*>)?\\s*\\(`,
60
+ );
61
+ const callStart = callStartRe.exec(chunkCode);
62
+ if (callStart) {
63
+ const afterOpen = callStart.index + callStart[0].length;
64
+ const closePos = findMatchingParenInBundle(chunkCode, afterOpen);
65
+ if (closePos !== -1) {
66
+ const callBody = chunkCode.slice(callStart.index, closePos);
67
+ isPassthrough = /passthrough\s*:\s*(!0|true)/.test(callBody); // !0 is minified true
68
+ }
69
+ }
70
+ }
71
+ handlers.push({ name, handlerId: match[1], passthrough: isPassthrough });
72
+ }
73
+ }
74
+
75
+ return handlers;
76
+ }
77
+
78
+ /**
79
+ * Evict handler code from a bundled chunk, replacing full call expressions with stubs.
80
+ * Returns the modified code and bytes saved, or null if no changes were made.
81
+ * @internal Exported for testing only.
82
+ */
83
+ export function evictHandlerCode(
84
+ code: string,
85
+ exports: Array<{ name: string; handlerId: string; passthrough?: boolean }>,
86
+ fnName: string,
87
+ brand: string,
88
+ ): { code: string; savedBytes: number } | null {
89
+ const originalSize = Buffer.byteLength(code);
90
+ let modified = code;
91
+
92
+ const eFnName = escapeRegExp(fnName);
93
+ for (const { name, handlerId, passthrough } of exports) {
94
+ if (passthrough) continue;
95
+
96
+ const eName = escapeRegExp(name);
97
+ // Match const/let/var: Rolldown (Vite 8) emits top-level bindings in the
98
+ // non-minified RSC bundle as `var`, whereas Rollup used `const`.
99
+ const callStartRe = new RegExp(
100
+ `(?:const|let|var)\\s+${eName}\\s*=\\s*${eFnName}\\s*(?:<[^>]*>)?\\s*\\(`,
101
+ );
102
+ const startMatch = callStartRe.exec(modified);
103
+ if (!startMatch) continue;
104
+
105
+ const afterOpen = startMatch.index + startMatch[0].length;
106
+ const closePos = findMatchingParenInBundle(modified, afterOpen);
107
+ if (closePos === -1) continue;
108
+
109
+ let rangeEnd = closePos;
110
+ while (rangeEnd < modified.length && /\s/.test(modified[rangeEnd]))
111
+ rangeEnd++;
112
+ if (modified[rangeEnd] === ";") rangeEnd++;
113
+
114
+ const matched = modified.slice(startMatch.index, rangeEnd);
115
+ if (!matched.includes(handlerId)) continue;
116
+
117
+ const stub = `const ${name} = { __brand: "${brand}", $$id: "${handlerId}" };`;
118
+ modified =
119
+ modified.slice(0, startMatch.index) + stub + modified.slice(rangeEnd);
120
+
121
+ modified = modified.replace(
122
+ new RegExp(`\\n${eName}\\.\\$\\$id\\s*=\\s*"[^"]+";`),
123
+ "",
124
+ );
125
+ }
126
+
127
+ if (modified === code) return null;
128
+ return {
129
+ code: modified,
130
+ savedBytes: originalSize - Buffer.byteLength(modified),
131
+ };
132
+ }