@timber-js/app 0.2.0-alpha.192 → 0.2.0-alpha.194

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 (667) hide show
  1. package/agent-skill.md +2 -0
  2. package/dist/_chunks/{actions-BjbbNRFN.js → actions-CWYtq6ii.js} +3 -3
  3. package/dist/_chunks/actions-CWYtq6ii.js.map +1 -0
  4. package/dist/_chunks/als-registry-C6kcfprT.js.map +1 -1
  5. package/dist/_chunks/als-slots-BEEIPKYm.js.map +1 -1
  6. package/dist/_chunks/{build-output-helper-C3DrfzZR.js → build-output-helper-9dqCv1pZ.js} +3 -2
  7. package/dist/_chunks/build-output-helper-9dqCv1pZ.js.map +1 -0
  8. package/dist/_chunks/{cache-api-DllJ-Lyw.js → cache-api-CQeYzA5g.js} +6 -8
  9. package/dist/_chunks/cache-api-CQeYzA5g.js.map +1 -0
  10. package/dist/_chunks/chains-h7EO-u3n.js +412 -0
  11. package/dist/_chunks/chains-h7EO-u3n.js.map +1 -0
  12. package/dist/_chunks/{cli-check-DJZDc22E.js → cli-check-BVthpfLS.js} +43 -6
  13. package/dist/_chunks/cli-check-BVthpfLS.js.map +1 -0
  14. package/dist/_chunks/{cli-schema-sync-D4_AZVUb.js → cli-schema-sync-ZwM9u_ob.js} +6 -5
  15. package/dist/_chunks/{cli-schema-sync-D4_AZVUb.js.map → cli-schema-sync-ZwM9u_ob.js.map} +1 -1
  16. package/dist/_chunks/{cloudflare-CGP6BZKO.js → cloudflare-BKJC3SC_.js} +28 -22
  17. package/dist/_chunks/{cloudflare-CGP6BZKO.js.map → cloudflare-BKJC3SC_.js.map} +1 -1
  18. package/dist/_chunks/codec-registry-oOUxugz3.js.map +1 -1
  19. package/dist/_chunks/{convention-lint-CpteIpTm.js → convention-lint-DO10_pVl.js} +93 -7
  20. package/dist/_chunks/convention-lint-DO10_pVl.js.map +1 -0
  21. package/dist/_chunks/dist-DtrJyBbw.js +386 -0
  22. package/dist/_chunks/dist-DtrJyBbw.js.map +1 -0
  23. package/dist/_chunks/error-boundary-D-ODYX41.js.map +1 -1
  24. package/dist/_chunks/{file-cache-DmX7OqZP.js → file-cache-Dw6BJPG7.js} +5 -1
  25. package/dist/_chunks/{file-cache-DmX7OqZP.js.map → file-cache-Dw6BJPG7.js.map} +1 -1
  26. package/dist/_chunks/{format-CfwjgPz9.js → format-BKclgVbk.js} +3 -3
  27. package/dist/_chunks/{format-CfwjgPz9.js.map → format-BKclgVbk.js.map} +1 -1
  28. package/dist/_chunks/graph-cache-CP4GEmf9.js +304 -0
  29. package/dist/_chunks/graph-cache-CP4GEmf9.js.map +1 -0
  30. package/dist/_chunks/href-validation-CMc5JRls.js.map +1 -1
  31. package/dist/_chunks/live-graph-Bx4HodF1.js +150 -0
  32. package/dist/_chunks/live-graph-Bx4HodF1.js.map +1 -0
  33. package/dist/_chunks/{logger-CH7IcMmg.js → logger-pumCm3Il.js} +25 -7
  34. package/dist/_chunks/{logger-CH7IcMmg.js.map → logger-pumCm3Il.js.map} +1 -1
  35. package/dist/_chunks/{mdx-file-C005ay-P.js → mdx-file-CXyHGUpS.js} +3 -3
  36. package/dist/_chunks/mdx-file-CXyHGUpS.js.map +1 -0
  37. package/dist/_chunks/{plugin-context-rCinWLiE.js → plugin-context-8idfR3UZ.js} +2 -2
  38. package/dist/_chunks/plugin-context-8idfR3UZ.js.map +1 -0
  39. package/dist/_chunks/poison-rules-DoEhbqaY.js +110 -0
  40. package/dist/_chunks/poison-rules-DoEhbqaY.js.map +1 -0
  41. package/dist/_chunks/poison-scan-BAxfTT5L.js +101 -0
  42. package/dist/_chunks/poison-scan-BAxfTT5L.js.map +1 -0
  43. package/dist/_chunks/resolve-schema-CBR6Lm4i.js.map +1 -1
  44. package/dist/_chunks/rolldown-runtime-D7D4PA-g.js +13 -0
  45. package/dist/_chunks/router-ref-DuYuV_0Q.js.map +1 -1
  46. package/dist/_chunks/{rsc-media-type-DRqE_lD_.js → rsc-media-type-DDc7duTD.js} +17 -2
  47. package/dist/_chunks/{rsc-media-type-DRqE_lD_.js.map → rsc-media-type-DDc7duTD.js.map} +1 -1
  48. package/dist/_chunks/scan-BoP17W3w.js +140 -0
  49. package/dist/_chunks/scan-BoP17W3w.js.map +1 -0
  50. package/dist/_chunks/{scanner-CAietmj4.js → scanner-BRIOmHE2.js} +43 -4
  51. package/dist/_chunks/scanner-BRIOmHE2.js.map +1 -0
  52. package/dist/_chunks/schema-bridge-C83xa9lT.js.map +1 -1
  53. package/dist/_chunks/segment-classify-C539Pa2O.js.map +1 -1
  54. package/dist/_chunks/{segment-keys-BawYuNFO.js → segment-keys-BhqoHiLc.js} +14 -2
  55. package/dist/_chunks/{segment-keys-BawYuNFO.js.map → segment-keys-BhqoHiLc.js.map} +1 -1
  56. package/dist/_chunks/slot-params-BCTmZkQB.js.map +1 -1
  57. package/dist/_chunks/ssr-data-14MXm7Pj.js.map +1 -1
  58. package/dist/_chunks/use-query-states-I3JMng6J.js.map +1 -1
  59. package/dist/_chunks/use-segment-params-C4r4BD9T.js.map +1 -1
  60. package/dist/_chunks/{walkers-BsVLmD1S.js → walkers-uCu3WW6_.js} +9 -6
  61. package/dist/_chunks/{walkers-BsVLmD1S.js.map → walkers-uCu3WW6_.js.map} +1 -1
  62. package/dist/adapters/build-output-helper.d.ts +1 -1
  63. package/dist/adapters/build-output-helper.d.ts.map +1 -1
  64. package/dist/adapters/cloudflare-dev.d.ts.map +1 -1
  65. package/dist/adapters/cloudflare-dev.js +2 -1
  66. package/dist/adapters/cloudflare-dev.js.map +1 -1
  67. package/dist/adapters/cloudflare-kv-cache.d.ts +1 -1
  68. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -1
  69. package/dist/adapters/cloudflare-kv-cache.js +7 -8
  70. package/dist/adapters/cloudflare-kv-cache.js.map +1 -1
  71. package/dist/adapters/cloudflare.d.ts +1 -1
  72. package/dist/adapters/cloudflare.d.ts.map +1 -1
  73. package/dist/adapters/cloudflare.js +1 -1
  74. package/dist/adapters/nitro-presets.d.ts +37 -0
  75. package/dist/adapters/nitro-presets.d.ts.map +1 -0
  76. package/dist/adapters/nitro-preview.d.ts +32 -0
  77. package/dist/adapters/nitro-preview.d.ts.map +1 -0
  78. package/dist/adapters/nitro.d.ts +28 -51
  79. package/dist/adapters/nitro.d.ts.map +1 -1
  80. package/dist/adapters/nitro.js +224 -171
  81. package/dist/adapters/nitro.js.map +1 -1
  82. package/dist/analyze/chains.d.ts +124 -0
  83. package/dist/analyze/chains.d.ts.map +1 -0
  84. package/dist/analyze/classify.d.ts +150 -0
  85. package/dist/analyze/classify.d.ts.map +1 -0
  86. package/dist/analyze/crawl-entry.d.ts +17 -0
  87. package/dist/analyze/crawl-entry.d.ts.map +1 -0
  88. package/dist/analyze/crawl-entry.js +313 -0
  89. package/dist/analyze/crawl-entry.js.map +1 -0
  90. package/dist/analyze/crawl.d.ts +134 -0
  91. package/dist/analyze/crawl.d.ts.map +1 -0
  92. package/dist/analyze/graph-cache.d.ts +104 -0
  93. package/dist/analyze/graph-cache.d.ts.map +1 -0
  94. package/dist/analyze/graph-command.d.ts +43 -0
  95. package/dist/analyze/graph-command.d.ts.map +1 -0
  96. package/dist/analyze/graph-command.js +472 -0
  97. package/dist/analyze/graph-command.js.map +1 -0
  98. package/dist/analyze/live-graph.d.ts +81 -0
  99. package/dist/analyze/live-graph.d.ts.map +1 -0
  100. package/dist/analyze/poison-rules.d.ts +72 -0
  101. package/dist/analyze/poison-rules.d.ts.map +1 -0
  102. package/dist/analyze/poison-scan.d.ts +48 -0
  103. package/dist/analyze/poison-scan.d.ts.map +1 -0
  104. package/dist/analyze/scan.d.ts +73 -0
  105. package/dist/analyze/scan.d.ts.map +1 -0
  106. package/dist/cache/cache-api.d.ts +2 -2
  107. package/dist/cache/cache-api.d.ts.map +1 -1
  108. package/dist/cache/index.d.ts +8 -8
  109. package/dist/cache/index.d.ts.map +1 -1
  110. package/dist/cache/index.js +1 -1
  111. package/dist/cache/redis-handler.d.ts +1 -1
  112. package/dist/cache/redis-handler.d.ts.map +1 -1
  113. package/dist/cache/stores/cloudflare-kv.d.ts +1 -1
  114. package/dist/cache/stores/cloudflare-kv.d.ts.map +1 -1
  115. package/dist/cache/stores/cloudflare-kv.js.map +1 -1
  116. package/dist/cache/stores/memory.d.ts +1 -1
  117. package/dist/cache/stores/memory.d.ts.map +1 -1
  118. package/dist/cache/stores/memory.js.map +1 -1
  119. package/dist/cache/stores/redis.d.ts +1 -1
  120. package/dist/cache/stores/redis.d.ts.map +1 -1
  121. package/dist/cache/stores/redis.js.map +1 -1
  122. package/dist/cache/stores/vercel.d.ts +1 -1
  123. package/dist/cache/stores/vercel.d.ts.map +1 -1
  124. package/dist/cache/stores/vercel.js.map +1 -1
  125. package/dist/cache/tag-aware-handler.d.ts +2 -2
  126. package/dist/cache/tag-aware-handler.d.ts.map +1 -1
  127. package/dist/cache/timber-cache.d.ts +1 -1
  128. package/dist/cache/timber-cache.d.ts.map +1 -1
  129. package/dist/cdn/cloudflare-purge.d.ts +1 -1
  130. package/dist/cdn/cloudflare-purge.d.ts.map +1 -1
  131. package/dist/cdn/cloudflare-purge.js.map +1 -1
  132. package/dist/cdn/fastly-purge.d.ts +1 -1
  133. package/dist/cdn/fastly-purge.d.ts.map +1 -1
  134. package/dist/cdn/fastly-purge.js.map +1 -1
  135. package/dist/cdn/index.d.ts +4 -4
  136. package/dist/cdn/index.d.ts.map +1 -1
  137. package/dist/cdn/workers-cache-purge.d.ts +5 -1
  138. package/dist/cdn/workers-cache-purge.d.ts.map +1 -1
  139. package/dist/cdn/workers-cache-purge.js.map +1 -1
  140. package/dist/cli-check.d.ts +10 -0
  141. package/dist/cli-check.d.ts.map +1 -1
  142. package/dist/cli.d.ts +12 -4
  143. package/dist/cli.d.ts.map +1 -1
  144. package/dist/cli.js +30 -6
  145. package/dist/cli.js.map +1 -1
  146. package/dist/client/browser-entry/hydrate.d.ts +2 -2
  147. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  148. package/dist/client/browser-entry/post-hydration.d.ts +2 -2
  149. package/dist/client/browser-entry/router-init.d.ts +2 -2
  150. package/dist/client/browser-entry/rsc-stream.d.ts +1 -1
  151. package/dist/client/form.d.ts +2 -2
  152. package/dist/client/form.d.ts.map +1 -1
  153. package/dist/client/history.d.ts +2 -2
  154. package/dist/client/index.d.ts +18 -18
  155. package/dist/client/index.d.ts.map +1 -1
  156. package/dist/client/index.js.map +1 -1
  157. package/dist/client/internal.d.ts +19 -19
  158. package/dist/client/internal.d.ts.map +1 -1
  159. package/dist/client/internal.js +11 -15
  160. package/dist/client/internal.js.map +1 -1
  161. package/dist/client/link.d.ts +3 -3
  162. package/dist/client/navigation-commit.d.ts +5 -5
  163. package/dist/client/navigation-root.d.ts +1 -1
  164. package/dist/client/navigation-root.d.ts.map +1 -1
  165. package/dist/client/params-context.d.ts +3 -3
  166. package/dist/client/router-pipeline.d.ts +7 -7
  167. package/dist/client/router-ref.d.ts +1 -1
  168. package/dist/client/router-types.d.ts +6 -6
  169. package/dist/client/router-types.d.ts.map +1 -1
  170. package/dist/client/router.d.ts +1 -1
  171. package/dist/client/rsc-fetch.d.ts +4 -4
  172. package/dist/client/rsc-fetch.d.ts.map +1 -1
  173. package/dist/client/segment-cache.d.ts +2 -2
  174. package/dist/client/slot-provider.d.ts +1 -1
  175. package/dist/client/ssr-data.d.ts +2 -2
  176. package/dist/client/state.d.ts +4 -4
  177. package/dist/client/use-query-states.d.ts +1 -1
  178. package/dist/client/use-segment-params.d.ts +3 -3
  179. package/dist/codec.d.ts +2 -2
  180. package/dist/codec.js.map +1 -1
  181. package/dist/config-validation.d.ts +1 -1
  182. package/dist/cookies/define-cookie.d.ts +3 -3
  183. package/dist/cookies/index.d.ts +3 -3
  184. package/dist/cookies/index.js +3 -4
  185. package/dist/cookies/index.js.map +1 -1
  186. package/dist/cookies/json-cookie.d.ts +1 -1
  187. package/dist/dev-tools/404-page.d.ts +2 -2
  188. package/dist/dev-tools/error-page.d.ts +2 -2
  189. package/dist/dev-tools/index.d.ts +12 -12
  190. package/dist/dev-tools/instrumentation.d.ts +1 -1
  191. package/dist/dev-tools/logs.d.ts +1 -1
  192. package/dist/dev-tools/overlay.d.ts +2 -2
  193. package/dist/dev-tools/terminal.d.ts +1 -1
  194. package/dist/fonts/ast.d.ts +4 -4
  195. package/dist/fonts/bundle.d.ts +3 -3
  196. package/dist/fonts/css.d.ts +1 -1
  197. package/dist/fonts/dev-middleware.d.ts +1 -1
  198. package/dist/fonts/google.d.ts +1 -1
  199. package/dist/fonts/local.d.ts +1 -1
  200. package/dist/fonts/pipeline.d.ts +3 -3
  201. package/dist/fonts/transform.d.ts +2 -2
  202. package/dist/fonts/types.d.ts +1 -1
  203. package/dist/fonts/virtual-modules.d.ts +1 -1
  204. package/dist/index.d.ts +3 -3
  205. package/dist/index.d.ts.map +1 -1
  206. package/dist/index.js +785 -282
  207. package/dist/index.js.map +1 -1
  208. package/dist/params/codec-registry.d.ts +1 -1
  209. package/dist/params/define-schema.d.ts +2 -2
  210. package/dist/params/index.d.ts +4 -4
  211. package/dist/params/index.js.map +1 -1
  212. package/dist/params/resolve-schema.d.ts +1 -1
  213. package/dist/plugin-context.d.ts +9 -9
  214. package/dist/plugin-context.d.ts.map +1 -1
  215. package/dist/plugins/adapter-build.d.ts +2 -2
  216. package/dist/plugins/build-manifest.d.ts +2 -2
  217. package/dist/plugins/build-report.d.ts +5 -5
  218. package/dist/plugins/cache.d.ts +1 -1
  219. package/dist/plugins/callsite-jsx.d.ts +2 -2
  220. package/dist/plugins/chunks.d.ts +1 -1
  221. package/dist/plugins/chunks.d.ts.map +1 -1
  222. package/dist/plugins/cloudflare-wasm.d.ts +1 -1
  223. package/dist/plugins/content.d.ts +1 -1
  224. package/dist/plugins/content.d.ts.map +1 -1
  225. package/dist/plugins/dev-discovery.d.ts +123 -0
  226. package/dist/plugins/dev-discovery.d.ts.map +1 -0
  227. package/dist/plugins/dev-server.d.ts +1 -1
  228. package/dist/plugins/dev-server.d.ts.map +1 -1
  229. package/dist/plugins/entries.d.ts +1 -1
  230. package/dist/plugins/fonts.d.ts +3 -3
  231. package/dist/plugins/fonts.d.ts.map +1 -1
  232. package/dist/plugins/graph-endpoint.d.ts +112 -0
  233. package/dist/plugins/graph-endpoint.d.ts.map +1 -0
  234. package/dist/plugins/mdx.d.ts +1 -1
  235. package/dist/plugins/mdx.d.ts.map +1 -1
  236. package/dist/plugins/prebuilt-capture.d.ts +2 -2
  237. package/dist/plugins/prebuilt-options-analysis.d.ts +1 -1
  238. package/dist/plugins/prebuilt.d.ts +1 -1
  239. package/dist/plugins/prerender-sugar.d.ts +11 -14
  240. package/dist/plugins/prerender-sugar.d.ts.map +1 -1
  241. package/dist/plugins/request-dep/analysis.d.ts +1 -1
  242. package/dist/plugins/request-dep/index.d.ts +5 -5
  243. package/dist/plugins/request-dep/origin.d.ts +1 -1
  244. package/dist/plugins/routing.d.ts +1 -1
  245. package/dist/plugins/routing.d.ts.map +1 -1
  246. package/dist/plugins/server-bundle.d.ts.map +1 -1
  247. package/dist/plugins/shims.d.ts +1 -1
  248. package/dist/plugins/shims.d.ts.map +1 -1
  249. package/dist/plugins/static-build.d.ts +5 -5
  250. package/dist/routing/codegen-shared.d.ts +1 -1
  251. package/dist/routing/codegen-write.d.ts +1 -1
  252. package/dist/routing/codegen.d.ts +1 -1
  253. package/dist/routing/collision-probe.d.ts +1 -1
  254. package/dist/routing/collision-spaces.d.ts +1 -1
  255. package/dist/routing/convention-lint.d.ts +1 -1
  256. package/dist/routing/convention-lint.d.ts.map +1 -1
  257. package/dist/routing/index.d.ts +13 -13
  258. package/dist/routing/index.js +3 -3
  259. package/dist/routing/interception.d.ts +1 -1
  260. package/dist/routing/interception.d.ts.map +1 -1
  261. package/dist/routing/link-codegen.d.ts +1 -1
  262. package/dist/routing/manifest-codegen.d.ts +1 -1
  263. package/dist/routing/scanner.d.ts +14 -1
  264. package/dist/routing/scanner.d.ts.map +1 -1
  265. package/dist/routing/schema-validation.d.ts +1 -1
  266. package/dist/routing/segment-classify.d.ts +1 -1
  267. package/dist/routing/segment-codegen.d.ts +1 -1
  268. package/dist/routing/segment-keys.d.ts +1 -1
  269. package/dist/routing/slot-placement.d.ts +1 -1
  270. package/dist/routing/walkers.d.ts +1 -1
  271. package/dist/rsc-runtime/transforms.d.ts +13 -0
  272. package/dist/rsc-runtime/transforms.d.ts.map +1 -0
  273. package/dist/schema-bridge.d.ts +1 -1
  274. package/dist/search-params/define.d.ts +3 -3
  275. package/dist/search-params/index.d.ts +3 -3
  276. package/dist/search-params/index.js.map +1 -1
  277. package/dist/search-params/wrappers.d.ts +1 -1
  278. package/dist/server/access-gate.d.ts +1 -1
  279. package/dist/server/action-client.d.ts +1 -1
  280. package/dist/server/action-handler.d.ts +5 -5
  281. package/dist/server/actions.d.ts +2 -2
  282. package/dist/server/als-registry.d.ts +8 -8
  283. package/dist/server/asset-headers.d.ts +1 -1
  284. package/dist/server/chain-url-parts.d.ts +3 -3
  285. package/dist/server/children-interception.d.ts +2 -2
  286. package/dist/server/cookie-context.d.ts +1 -1
  287. package/dist/server/cookie-parsing.d.ts +2 -2
  288. package/dist/server/default-logger.d.ts +1 -1
  289. package/dist/server/deny-boundary.d.ts +2 -2
  290. package/dist/server/deny-renderer.d.ts +5 -5
  291. package/dist/server/early-hints.d.ts +1 -1
  292. package/dist/server/error-boundary-wrapper.d.ts +2 -4
  293. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  294. package/dist/server/fallback-error.d.ts +5 -5
  295. package/dist/server/flight-injection-state.d.ts +1 -1
  296. package/dist/server/form-flash.d.ts +1 -1
  297. package/dist/server/html-injector-core.d.ts +2 -2
  298. package/dist/server/html-injectors.d.ts +1 -1
  299. package/dist/server/index.d.ts +18 -18
  300. package/dist/server/index.d.ts.map +1 -1
  301. package/dist/server/index.js +33 -32
  302. package/dist/server/index.js.map +1 -1
  303. package/dist/server/instrumentation.d.ts +1 -1
  304. package/dist/server/internal.d.ts +50 -50
  305. package/dist/server/internal.d.ts.map +1 -1
  306. package/dist/server/internal.js +1023 -1025
  307. package/dist/server/internal.js.map +1 -1
  308. package/dist/server/metadata-collector.d.ts +2 -2
  309. package/dist/server/metadata-platform.d.ts +2 -2
  310. package/dist/server/metadata-render.d.ts +2 -2
  311. package/dist/server/metadata-routes.d.ts +3 -3
  312. package/dist/server/metadata-social.d.ts +2 -2
  313. package/dist/server/metadata.d.ts +2 -2
  314. package/dist/server/middleware-runner.d.ts +1 -1
  315. package/dist/server/node-stream-transforms.d.ts +1 -1
  316. package/dist/server/param-coercion.d.ts +4 -4
  317. package/dist/server/pipeline-helpers.d.ts +3 -3
  318. package/dist/server/pipeline-interception.d.ts +1 -1
  319. package/dist/server/pipeline-metadata.d.ts +1 -1
  320. package/dist/server/pipeline-outcome.d.ts +2 -2
  321. package/dist/server/pipeline-phases.d.ts +3 -3
  322. package/dist/server/pipeline-phases.d.ts.map +1 -1
  323. package/dist/server/pipeline.d.ts +9 -9
  324. package/dist/server/prebuilt/cache-key.d.ts +1 -1
  325. package/dist/server/prebuilt/capture-state.d.ts +1 -1
  326. package/dist/server/prebuilt/key-discipline.d.ts +1 -1
  327. package/dist/server/prebuilt/manifest-tag-index.d.ts +1 -1
  328. package/dist/server/prebuilt/overlay.d.ts +2 -2
  329. package/dist/server/prebuilt/payload-source.d.ts +1 -1
  330. package/dist/server/prebuilt/slots.d.ts +1 -1
  331. package/dist/server/prebuilt/synthetic-store.d.ts +2 -2
  332. package/dist/server/prebuilt-builder.d.ts +2 -2
  333. package/dist/server/primitives.d.ts +2 -2
  334. package/dist/server/publish-params.d.ts +1 -1
  335. package/dist/server/request-context.d.ts +3 -3
  336. package/dist/server/route-element-builder.d.ts +16 -6
  337. package/dist/server/route-element-builder.d.ts.map +1 -1
  338. package/dist/server/route-handler.d.ts +1 -1
  339. package/dist/server/route-matcher.d.ts +4 -4
  340. package/dist/server/rsc-cache-key-guard.d.ts.map +1 -1
  341. package/dist/server/rsc-entry/action-middleware-runner.d.ts +2 -2
  342. package/dist/server/rsc-entry/api-handler.d.ts +1 -1
  343. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  344. package/dist/server/rsc-entry/deny-fallback.d.ts +3 -3
  345. package/dist/server/rsc-entry/error-renderer.d.ts +4 -4
  346. package/dist/server/rsc-entry/helpers.d.ts +6 -6
  347. package/dist/server/rsc-entry/index.d.ts +7 -6
  348. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  349. package/dist/server/rsc-entry/render-route.d.ts +4 -4
  350. package/dist/server/rsc-entry/revalidate-renderer.d.ts +4 -4
  351. package/dist/server/rsc-entry/rsc-payload.d.ts +4 -4
  352. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  353. package/dist/server/rsc-entry/rsc-stream.d.ts +3 -3
  354. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  355. package/dist/server/rsc-entry/ssr-renderer.d.ts +7 -7
  356. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +5 -5
  357. package/dist/server/sitemap-generator.d.ts +2 -2
  358. package/dist/server/sitemap-handler.d.ts +1 -1
  359. package/dist/server/skippable-prefix.d.ts +3 -3
  360. package/dist/server/slot-interception.d.ts +2 -2
  361. package/dist/server/slot-resolver.d.ts +3 -7
  362. package/dist/server/slot-resolver.d.ts.map +1 -1
  363. package/dist/server/ssr-bridge-types.d.ts +2 -2
  364. package/dist/server/ssr-entry.d.ts +1 -1
  365. package/dist/server/static-generator.d.ts +1 -1
  366. package/dist/server/static-not-found.d.ts +1 -1
  367. package/dist/server/status-code-resolver.d.ts +1 -1
  368. package/dist/server/tracing.d.ts +3 -3
  369. package/dist/server/tree-builder.d.ts +3 -3
  370. package/dist/server/tree-match.d.ts +1 -1
  371. package/dist/server/types.d.ts +2 -2
  372. package/dist/server/utils/mdx-file.d.ts +2 -0
  373. package/dist/server/utils/mdx-file.d.ts.map +1 -1
  374. package/dist/server/workers-cache-bridge.d.ts +1 -1
  375. package/dist/shared/als-slots.d.ts +1 -1
  376. package/dist/shared/payload-root.d.ts +2 -2
  377. package/dist/shared/rsc-media-type.d.ts +12 -0
  378. package/dist/shared/rsc-media-type.d.ts.map +1 -1
  379. package/dist/shared/slot-params.d.ts +1 -1
  380. package/dist/shims/font-google.d.ts +1 -1
  381. package/dist/shims/font-google.js.map +1 -1
  382. package/dist/shims/font-local.d.ts +1 -1
  383. package/dist/shims/font-local.js.map +1 -1
  384. package/dist/shims/navigation-client.d.ts +4 -4
  385. package/dist/shims/navigation.d.ts +2 -2
  386. package/docs/api/36-cli.mdx +23 -3
  387. package/docs/learn/11-error-handling.mdx +11 -0
  388. package/docs/more/01-advanced-routing.mdx +1 -0
  389. package/package.json +17 -16
  390. package/src/adapters/build-output-helper.ts +4 -4
  391. package/src/adapters/cloudflare-dev.ts +7 -1
  392. package/src/adapters/cloudflare-kv-cache.ts +11 -8
  393. package/src/adapters/cloudflare.ts +21 -15
  394. package/src/adapters/compress-module.ts +2 -2
  395. package/src/adapters/nitro-presets.ts +139 -0
  396. package/src/adapters/nitro-preview.ts +340 -0
  397. package/src/adapters/nitro.ts +100 -465
  398. package/src/adapters/shared.ts +1 -1
  399. package/src/analyze/chains.ts +411 -0
  400. package/src/analyze/classify.ts +258 -0
  401. package/src/analyze/crawl-entry.ts +68 -0
  402. package/src/analyze/crawl.ts +500 -0
  403. package/src/analyze/graph-cache.ts +332 -0
  404. package/src/analyze/graph-command.ts +762 -0
  405. package/src/analyze/live-graph.ts +232 -0
  406. package/src/analyze/poison-rules.ts +165 -0
  407. package/src/analyze/poison-scan.ts +162 -0
  408. package/src/analyze/scan.ts +149 -0
  409. package/src/cache/cache-api.ts +7 -7
  410. package/src/cache/index.ts +9 -9
  411. package/src/cache/redis-handler.ts +2 -2
  412. package/src/cache/stores/cloudflare-kv.ts +1 -1
  413. package/src/cache/stores/memory.ts +2 -2
  414. package/src/cache/stores/redis.ts +1 -1
  415. package/src/cache/stores/vercel.ts +1 -1
  416. package/src/cache/tag-aware-handler.ts +2 -2
  417. package/src/cache/timber-cache.ts +8 -8
  418. package/src/cdn/cloudflare-purge.ts +1 -1
  419. package/src/cdn/fastly-purge.ts +1 -1
  420. package/src/cdn/index.ts +10 -4
  421. package/src/cdn/workers-cache-purge.ts +6 -2
  422. package/src/cli-check.ts +53 -4
  423. package/src/cli-schema-sync.ts +3 -3
  424. package/src/cli.ts +50 -11
  425. package/src/client/browser-dev.ts +1 -1
  426. package/src/client/browser-entry/action-dispatch.ts +5 -5
  427. package/src/client/browser-entry/hmr.ts +1 -1
  428. package/src/client/browser-entry/hydrate.ts +9 -9
  429. package/src/client/browser-entry/index.ts +10 -10
  430. package/src/client/browser-entry/post-hydration.ts +5 -5
  431. package/src/client/browser-entry/router-init.ts +9 -9
  432. package/src/client/browser-entry/rsc-stream.ts +3 -3
  433. package/src/client/error-boundary.tsx +4 -4
  434. package/src/client/form.tsx +7 -2
  435. package/src/client/history.ts +2 -2
  436. package/src/client/index.ts +21 -18
  437. package/src/client/internal.ts +19 -19
  438. package/src/client/link.tsx +9 -9
  439. package/src/client/navigation-api.ts +1 -1
  440. package/src/client/navigation-commit.ts +5 -5
  441. package/src/client/navigation-context.ts +1 -1
  442. package/src/client/navigation-root.tsx +1 -1
  443. package/src/client/nuqs-adapter.tsx +2 -2
  444. package/src/client/params-context.ts +4 -4
  445. package/src/client/router-effects.ts +3 -3
  446. package/src/client/router-lifecycle.ts +2 -2
  447. package/src/client/router-pipeline.ts +10 -10
  448. package/src/client/router-ref.ts +2 -2
  449. package/src/client/router-skew.ts +2 -2
  450. package/src/client/router-types.ts +6 -6
  451. package/src/client/router.ts +13 -13
  452. package/src/client/rsc-fetch.ts +11 -16
  453. package/src/client/segment-cache.ts +2 -2
  454. package/src/client/segment-outlet.tsx +1 -1
  455. package/src/client/shallow-url.ts +1 -1
  456. package/src/client/slot-outlet.tsx +1 -1
  457. package/src/client/slot-provider.tsx +1 -1
  458. package/src/client/ssr-data.ts +3 -3
  459. package/src/client/stale-client.ts +1 -1
  460. package/src/client/state.ts +4 -4
  461. package/src/client/top-loader.tsx +1 -1
  462. package/src/client/unload-guard.ts +1 -1
  463. package/src/client/use-cookie.ts +2 -2
  464. package/src/client/use-pathname.ts +2 -2
  465. package/src/client/use-pending-navigation.ts +1 -1
  466. package/src/client/use-query-states.ts +3 -3
  467. package/src/client/use-router.ts +2 -2
  468. package/src/client/use-search-params.ts +3 -3
  469. package/src/client/use-segment-params.ts +6 -6
  470. package/src/client/use-selected-layout-segment.ts +2 -2
  471. package/src/codec.ts +2 -2
  472. package/src/config-validation.ts +1 -1
  473. package/src/cookies/define-cookie.ts +6 -6
  474. package/src/cookies/index.ts +3 -3
  475. package/src/cookies/json-cookie.ts +1 -1
  476. package/src/dev-tools/404-page.ts +4 -4
  477. package/src/dev-tools/dev-page-shell.ts +1 -1
  478. package/src/dev-tools/error-page.ts +4 -4
  479. package/src/dev-tools/index.ts +12 -12
  480. package/src/dev-tools/instrumentation.ts +1 -1
  481. package/src/dev-tools/logs.ts +1 -1
  482. package/src/dev-tools/overlay.ts +3 -3
  483. package/src/dev-tools/terminal.ts +2 -2
  484. package/src/fonts/ast.ts +5 -5
  485. package/src/fonts/bundle.ts +5 -5
  486. package/src/fonts/css.ts +1 -1
  487. package/src/fonts/dev-middleware.ts +2 -2
  488. package/src/fonts/google.ts +2 -2
  489. package/src/fonts/local.ts +4 -4
  490. package/src/fonts/pipeline.ts +8 -8
  491. package/src/fonts/transform.ts +5 -5
  492. package/src/fonts/types.ts +1 -1
  493. package/src/fonts/virtual-modules.ts +1 -1
  494. package/src/index.ts +46 -37
  495. package/src/params/codec-registry.ts +1 -1
  496. package/src/params/define-schema.ts +2 -2
  497. package/src/params/index.ts +4 -4
  498. package/src/params/resolve-schema.ts +2 -2
  499. package/src/plugin-context.ts +10 -10
  500. package/src/plugins/adapter-build.ts +5 -5
  501. package/src/plugins/build-manifest.ts +4 -4
  502. package/src/plugins/build-report.ts +6 -6
  503. package/src/plugins/cache.ts +3 -3
  504. package/src/plugins/callsite-ast.ts +1 -1
  505. package/src/plugins/callsite-jsx.ts +2 -2
  506. package/src/plugins/chunks.ts +1 -1
  507. package/src/plugins/cloudflare-wasm.ts +1 -1
  508. package/src/plugins/content.ts +5 -1
  509. package/src/plugins/dev-discovery.ts +218 -0
  510. package/src/plugins/dev-server.ts +97 -12
  511. package/src/plugins/entries.ts +1 -1
  512. package/src/plugins/fonts.ts +17 -10
  513. package/src/plugins/graph-endpoint.ts +532 -0
  514. package/src/plugins/mdx.ts +4 -3
  515. package/src/plugins/prebuilt-capture.ts +3 -3
  516. package/src/plugins/prebuilt-options-analysis.ts +1 -1
  517. package/src/plugins/prebuilt.ts +7 -7
  518. package/src/plugins/prerender-sugar.ts +11 -19
  519. package/src/plugins/request-dep/analysis.ts +1 -1
  520. package/src/plugins/request-dep/index.ts +8 -8
  521. package/src/plugins/request-dep/origin.ts +1 -1
  522. package/src/plugins/routing.ts +12 -7
  523. package/src/plugins/server-bundle.ts +9 -2
  524. package/src/plugins/shims.ts +16 -31
  525. package/src/plugins/static-build.ts +10 -10
  526. package/src/routing/codegen-shared.ts +1 -1
  527. package/src/routing/codegen-write.ts +3 -3
  528. package/src/routing/codegen.ts +14 -5
  529. package/src/routing/collision-probe.ts +3 -3
  530. package/src/routing/collision-spaces.ts +3 -3
  531. package/src/routing/convention-lint.ts +136 -6
  532. package/src/routing/export-detect.ts +1 -1
  533. package/src/routing/index.ts +13 -13
  534. package/src/routing/interception.ts +41 -4
  535. package/src/routing/link-codegen.ts +3 -3
  536. package/src/routing/manifest-codegen.ts +2 -2
  537. package/src/routing/scanner.ts +33 -9
  538. package/src/routing/schema-validation.ts +4 -4
  539. package/src/routing/segment-classify.ts +2 -2
  540. package/src/routing/segment-codegen.ts +1 -1
  541. package/src/routing/segment-keys.ts +1 -1
  542. package/src/routing/slot-placement.ts +1 -1
  543. package/src/routing/walkers.ts +1 -1
  544. package/src/rsc-runtime/transforms.ts +13 -0
  545. package/src/rsc-runtime/vendor-types.d.ts +12 -0
  546. package/src/schema-bridge.ts +1 -1
  547. package/src/search-params/define.ts +8 -8
  548. package/src/search-params/index.ts +3 -3
  549. package/src/search-params/wrappers.ts +3 -3
  550. package/src/server/access-gate.tsx +6 -6
  551. package/src/server/action-client.ts +5 -5
  552. package/src/server/action-handler.ts +16 -16
  553. package/src/server/actions.ts +5 -5
  554. package/src/server/als-registry.ts +8 -8
  555. package/src/server/asset-headers.ts +2 -2
  556. package/src/server/chain-url-parts.ts +5 -5
  557. package/src/server/children-interception.ts +4 -4
  558. package/src/server/compress.ts +1 -1
  559. package/src/server/cookie-context.ts +4 -4
  560. package/src/server/cookie-parsing.ts +2 -2
  561. package/src/server/default-logger.ts +3 -3
  562. package/src/server/deny-boundary.ts +10 -10
  563. package/src/server/deny-renderer.ts +38 -25
  564. package/src/server/early-hints-sender.ts +2 -2
  565. package/src/server/early-hints.ts +2 -2
  566. package/src/server/error-boundary-wrapper.ts +4 -12
  567. package/src/server/fallback-error.ts +13 -13
  568. package/src/server/flight-injection-state.ts +1 -1
  569. package/src/server/form-flash.ts +2 -2
  570. package/src/server/html-injector-core.ts +4 -4
  571. package/src/server/html-injectors.ts +5 -5
  572. package/src/server/index.ts +18 -18
  573. package/src/server/instrumentation.ts +1 -1
  574. package/src/server/internal.ts +50 -50
  575. package/src/server/logger.ts +4 -4
  576. package/src/server/metadata-collector.ts +7 -7
  577. package/src/server/metadata-platform.ts +2 -2
  578. package/src/server/metadata-render.ts +4 -4
  579. package/src/server/metadata-routes.ts +3 -3
  580. package/src/server/metadata-social.ts +2 -2
  581. package/src/server/metadata.ts +2 -2
  582. package/src/server/middleware-runner.ts +1 -1
  583. package/src/server/node-stream-transforms.ts +4 -4
  584. package/src/server/param-coercion.ts +8 -8
  585. package/src/server/pipeline-helpers.ts +7 -7
  586. package/src/server/pipeline-interception.ts +2 -2
  587. package/src/server/pipeline-metadata.ts +1 -1
  588. package/src/server/pipeline-outcome.ts +8 -8
  589. package/src/server/pipeline-phases.ts +24 -28
  590. package/src/server/pipeline.ts +22 -22
  591. package/src/server/prebuilt/cache-key.ts +1 -1
  592. package/src/server/prebuilt/capture-state.ts +1 -1
  593. package/src/server/prebuilt/key-discipline.ts +1 -1
  594. package/src/server/prebuilt/manifest-tag-index.ts +1 -1
  595. package/src/server/prebuilt/overlay.ts +6 -6
  596. package/src/server/prebuilt/payload-source.ts +2 -2
  597. package/src/server/prebuilt/slots.ts +5 -5
  598. package/src/server/prebuilt/synthetic-store.ts +2 -2
  599. package/src/server/prebuilt-builder.ts +16 -16
  600. package/src/server/prebuilt-runtime.ts +12 -12
  601. package/src/server/primitives.ts +7 -7
  602. package/src/server/publish-params.ts +3 -3
  603. package/src/server/request-context.ts +7 -7
  604. package/src/server/route-element-builder.ts +108 -50
  605. package/src/server/route-handler.ts +4 -4
  606. package/src/server/route-matcher.ts +5 -5
  607. package/src/server/rsc-cache-key-guard.ts +3 -5
  608. package/src/server/rsc-entry/action-middleware-runner.ts +7 -7
  609. package/src/server/rsc-entry/api-handler.ts +18 -9
  610. package/src/server/rsc-entry/deny-fallback.ts +10 -10
  611. package/src/server/rsc-entry/error-renderer.ts +27 -27
  612. package/src/server/rsc-entry/helpers.ts +10 -10
  613. package/src/server/rsc-entry/index.ts +51 -47
  614. package/src/server/rsc-entry/render-route.ts +20 -20
  615. package/src/server/rsc-entry/revalidate-renderer.ts +12 -12
  616. package/src/server/rsc-entry/rsc-payload.ts +19 -15
  617. package/src/server/rsc-entry/rsc-stream.ts +8 -8
  618. package/src/server/rsc-entry/ssr-bridge.ts +3 -3
  619. package/src/server/rsc-entry/ssr-renderer.ts +23 -23
  620. package/src/server/rsc-entry/wrap-action-dispatch.ts +9 -9
  621. package/src/server/rsc-prop-warnings.ts +1 -1
  622. package/src/server/sensitive-fields.ts +1 -1
  623. package/src/server/server-timing.ts +1 -1
  624. package/src/server/sitemap-generator.ts +3 -3
  625. package/src/server/sitemap-handler.ts +3 -3
  626. package/src/server/skippable-prefix.ts +7 -7
  627. package/src/server/slot-interception.ts +5 -5
  628. package/src/server/slot-resolver.ts +20 -28
  629. package/src/server/ssr-bridge-types.ts +2 -2
  630. package/src/server/ssr-entry.ts +18 -18
  631. package/src/server/ssr-render.ts +4 -4
  632. package/src/server/ssr-wrappers.tsx +1 -1
  633. package/src/server/state-tree-diff.ts +1 -1
  634. package/src/server/static-generator.ts +6 -6
  635. package/src/server/static-not-found.ts +3 -3
  636. package/src/server/status-code-resolver.ts +1 -1
  637. package/src/server/tracing.ts +5 -5
  638. package/src/server/tree-builder.ts +4 -4
  639. package/src/server/tree-match.ts +1 -1
  640. package/src/server/types.ts +2 -2
  641. package/src/server/utils/mdx-file.ts +2 -2
  642. package/src/server/waituntil-bridge.ts +1 -1
  643. package/src/server/workers-cache-bridge.ts +2 -2
  644. package/src/shared/als-slots.ts +1 -1
  645. package/src/shared/payload-root.ts +2 -2
  646. package/src/shared/rsc-media-type.ts +16 -0
  647. package/src/shared/slot-params.ts +1 -1
  648. package/src/shims/font-google.ts +1 -1
  649. package/src/shims/font-local.ts +1 -1
  650. package/src/shims/navigation-client.ts +5 -5
  651. package/src/shims/navigation.ts +2 -2
  652. package/LICENSE +0 -8
  653. package/dist/_chunks/actions-BjbbNRFN.js.map +0 -1
  654. package/dist/_chunks/build-output-helper-C3DrfzZR.js.map +0 -1
  655. package/dist/_chunks/cache-api-DllJ-Lyw.js.map +0 -1
  656. package/dist/_chunks/cli-check-DJZDc22E.js.map +0 -1
  657. package/dist/_chunks/convention-lint-CpteIpTm.js.map +0 -1
  658. package/dist/_chunks/dist-BA3u1z3W.js +0 -423
  659. package/dist/_chunks/dist-BA3u1z3W.js.map +0 -1
  660. package/dist/_chunks/mdx-file-C005ay-P.js.map +0 -1
  661. package/dist/_chunks/plugin-context-rCinWLiE.js.map +0 -1
  662. package/dist/_chunks/scanner-CAietmj4.js.map +0 -1
  663. package/dist/content/index.d.ts +0 -2
  664. package/dist/content/index.d.ts.map +0 -1
  665. package/dist/content/index.js +0 -0
  666. package/src/content/index.ts +0 -5
  667. package/src/shims/server-only-noop.js +0 -6
package/dist/index.js CHANGED
@@ -1,22 +1,25 @@
1
- import { a as __esmMin, o as __exportAll, s as __toCommonJS } from "./_chunks/dist-BA3u1z3W.js";
2
- import { t as RSC_CONTENT_TYPE } from "./_chunks/rsc-media-type-DRqE_lD_.js";
3
- import { a as canonicalize, d as isMetadataRouteServePath, u as isDynamicMetadataExtension } from "./_chunks/segment-keys-BawYuNFO.js";
4
- import { n as collectInterceptionRewrites, r as matchUrlParts, t as scanRoutes } from "./_chunks/scanner-CAietmj4.js";
5
- import { h as swallow } from "./_chunks/logger-CH7IcMmg.js";
6
- import { c as writeRouteCodegen, i as getPrerenderExport, l as buildDirToRouteMap, n as formatConventionWarnings, r as lintConventions, s as flushCodegenWrites, t as checkAppDirExists } from "./_chunks/convention-lint-CpteIpTm.js";
7
- import { c as resolveClientJavascript, i as mergeFileConfig, l as createNoopTimer, o as resolveAppDir, r as loadTimberConfigFile, s as resolveBuildDir, t as createPluginContext } from "./_chunks/plugin-context-rCinWLiE.js";
8
- import { r as validateSchemaAgainstRoutes, t as collectLeafRoutes } from "./_chunks/walkers-BsVLmD1S.js";
1
+ import { l as registerDevDiscovery } from "./_chunks/graph-cache-CP4GEmf9.js";
2
+ import { n as isScannableSourceFile, t as buildSourceExtensions } from "./_chunks/scan-BoP17W3w.js";
3
+ import { t as RSC_CONTENT_TYPE } from "./_chunks/rsc-media-type-DDc7duTD.js";
4
+ import { a as canonicalize, d as isMetadataRouteServePath, u as isDynamicMetadataExtension } from "./_chunks/segment-keys-BhqoHiLc.js";
5
+ import { i as matchUrlParts, n as scanRoutes, r as collectInterceptionRewrites } from "./_chunks/scanner-BRIOmHE2.js";
6
+ import { t as MDX_EXTENSIONS } from "./_chunks/mdx-file-CXyHGUpS.js";
7
+ import { h as swallow } from "./_chunks/logger-pumCm3Il.js";
8
+ import { c as writeRouteCodegen, i as getPrerenderExport, l as buildDirToRouteMap, n as formatConventionWarnings, r as lintConventions, s as flushCodegenWrites, t as checkAppDirExists } from "./_chunks/convention-lint-DO10_pVl.js";
9
+ import { c as resolveClientJavascript, i as mergeFileConfig, l as createNoopTimer, o as resolveAppDir, r as loadTimberConfigFile, s as resolveBuildDir, t as createPluginContext } from "./_chunks/plugin-context-8idfR3UZ.js";
10
+ import { r as validateSchemaAgainstRoutes, t as collectLeafRoutes } from "./_chunks/walkers-uCu3WW6_.js";
11
+ import { i as poisonPillSource, r as markerFor, t as EXPLICIT_MARKERS } from "./_chunks/poison-rules-DoEhbqaY.js";
9
12
  import { i as withBasePath, n as normalizeBasePath, t as isRelativeBase } from "./_chunks/base-path-DaQrzbez.js";
10
13
  import { t as rscPayloadPath } from "./_chunks/rsc-payload-path-B_LBodc2.js";
11
14
  import { a as REDIRECTS_FILE, n as detectFsIdentity, o as RESERVED_OUTPUT_PATHS, r as fsKey, t as EXACT_FS_IDENTITY } from "./_chunks/fs-identity-D7vb6GdI.js";
12
15
  import { t as EMPTY_BUILD_MANIFEST } from "./_chunks/build-manifest-DWppEdLB.js";
13
16
  import { t as fnv1aHash } from "./_chunks/fast-hash-C-tVYrLb.js";
14
- import { t as formatSize } from "./_chunks/format-CfwjgPz9.js";
15
- import { createLogger, parseAst } from "vite";
17
+ import { t as formatSize } from "./_chunks/format-BKclgVbk.js";
18
+ import { createLogger, normalizePath, parseAst } from "vite";
16
19
  import { basename, dirname, extname, isAbsolute, join, normalize, relative, resolve, win32 } from "node:path";
17
20
  import { builtinModules, createRequire } from "node:module";
18
21
  import react, { reactCompilerPreset } from "@vitejs/plugin-react";
19
- import { existsSync, readFileSync, statSync } from "node:fs";
22
+ import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
20
23
  import nodeHTTP from "node:http";
21
24
  import { Readable, pipeline } from "node:stream";
22
25
  import { pipeline as pipeline$1 } from "node:stream/promises";
@@ -24,9 +27,10 @@ import "node:https";
24
27
  import "node:http2";
25
28
  import { fileURLToPath, pathToFileURL } from "node:url";
26
29
  import { styleText } from "node:util";
27
- import { constants, createGzip, gzipSync } from "node:zlib";
28
30
  import { createHash, randomUUID } from "node:crypto";
29
- import { copyFile, mkdir, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
31
+ import { copyFile, mkdir, readFile, readdir, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
32
+ import { isIP } from "node:net";
33
+ import { constants, createGzip, gzipSync } from "node:zlib";
30
34
  //#region src/plugins/content.ts
31
35
  var CONFIG_FILE_NAMES$1 = [
32
36
  "content-collections.ts",
@@ -106,13 +110,14 @@ function timberContent(ctx) {
106
110
  return null;
107
111
  },
108
112
  async configureServer(server) {
113
+ if (process.env.TIMBER_ANALYZE === "1") return;
109
114
  if (!innerPlugin) return;
110
115
  if (typeof innerPlugin.configureServer === "function") await innerPlugin.configureServer.call(this, server);
111
116
  }
112
117
  };
113
118
  }
114
119
  //#endregion
115
- //#region ../../node_modules/.pnpm/srvx@0.12.0/node_modules/srvx/dist/adapters/node.mjs
120
+ //#region ../../node_modules/.pnpm/srvx@0.12.5/node_modules/srvx/dist/adapters/node.mjs
116
121
  function sendNodeResponse(nodeRes, webRes) {
117
122
  try {
118
123
  return _sendNodeResponse(nodeRes, webRes, false) || Promise.resolve();
@@ -397,7 +402,8 @@ var _traceMapping = null;
397
402
  */
398
403
  function getTraceMapping() {
399
404
  if (_traceMapping) return _traceMapping;
400
- _traceMapping = createRequire(createRequire(import.meta.url).resolve("vite"))("@jridgewell/trace-mapping");
405
+ const vitePath = createRequire(import.meta.url).resolve("vite");
406
+ _traceMapping = createRequire(vitePath)("@jridgewell/trace-mapping");
401
407
  return _traceMapping;
402
408
  }
403
409
  /** Labels for terminal output. */
@@ -1143,13 +1149,31 @@ var ERROR_CSS = `
1143
1149
  *
1144
1150
  * Design doc: 18-build-system.md
1145
1151
  */
1146
- var config_validation_exports = /* @__PURE__ */ __exportAll({
1147
- addVirtualModuleContext: () => addVirtualModuleContext,
1148
- checkPeerDependencies: () => checkPeerDependencies,
1149
- formatConfigErrors: () => formatConfigErrors,
1150
- formatMissingPeers: () => formatMissingPeers,
1151
- validateConfig: () => validateConfig
1152
- });
1152
+ var knownKeys = new Set(Object.keys({
1153
+ output: true,
1154
+ debug: true,
1155
+ clientJavascript: true,
1156
+ adapter: true,
1157
+ allowedOrigins: true,
1158
+ csrf: true,
1159
+ limits: true,
1160
+ forms: true,
1161
+ pageExtensions: true,
1162
+ slowRequestMs: true,
1163
+ renderTimeoutMs: true,
1164
+ devBrowserLogs: true,
1165
+ dev: true,
1166
+ serverTiming: true,
1167
+ appDir: true,
1168
+ mdx: true,
1169
+ actionEncryption: true,
1170
+ reactCompiler: true,
1171
+ sitemap: true,
1172
+ buildDir: true,
1173
+ clientSegmentCache: true,
1174
+ topLoader: true,
1175
+ budget: true
1176
+ }));
1153
1177
  /**
1154
1178
  * Validate a TimberUserConfig object.
1155
1179
  *
@@ -1164,29 +1188,31 @@ function validateConfig(config) {
1164
1188
  value: config.output,
1165
1189
  suggestion: "Use output: \"server\" (default) or output: \"static\" for static site generation."
1166
1190
  });
1167
- if (config.pageExtensions !== void 0) if (!Array.isArray(config.pageExtensions)) errors.push({
1168
- field: "pageExtensions",
1169
- message: "pageExtensions must be an array of strings.",
1170
- value: config.pageExtensions,
1171
- suggestion: "Example: pageExtensions: [\"tsx\", \"ts\", \"jsx\", \"js\", \"mdx\"]"
1172
- });
1173
- else for (const ext of config.pageExtensions) {
1174
- if (typeof ext !== "string") {
1175
- errors.push({
1176
- field: "pageExtensions",
1177
- message: `pageExtensions contains a non-string value: ${JSON.stringify(ext)}`,
1178
- value: ext
1179
- });
1180
- break;
1181
- }
1182
- if (ext.startsWith(".")) {
1183
- errors.push({
1184
- field: "pageExtensions",
1185
- message: `pageExtensions should not include the leading dot: "${ext}"`,
1186
- value: ext,
1187
- suggestion: `Use "${ext.slice(1)}" instead of "${ext}".`
1188
- });
1189
- break;
1191
+ if (config.pageExtensions !== void 0) {
1192
+ if (!Array.isArray(config.pageExtensions)) errors.push({
1193
+ field: "pageExtensions",
1194
+ message: "pageExtensions must be an array of strings.",
1195
+ value: config.pageExtensions,
1196
+ suggestion: "Example: pageExtensions: [\"tsx\", \"ts\", \"jsx\", \"js\", \"mdx\"]"
1197
+ });
1198
+ else for (const ext of config.pageExtensions) {
1199
+ if (typeof ext !== "string") {
1200
+ errors.push({
1201
+ field: "pageExtensions",
1202
+ message: `pageExtensions contains a non-string value: ${JSON.stringify(ext)}`,
1203
+ value: ext
1204
+ });
1205
+ break;
1206
+ }
1207
+ if (ext.startsWith(".")) {
1208
+ errors.push({
1209
+ field: "pageExtensions",
1210
+ message: `pageExtensions should not include the leading dot: "${ext}"`,
1211
+ value: ext,
1212
+ suggestion: `Use "${ext.slice(1)}" instead of "${ext}".`
1213
+ });
1214
+ break;
1215
+ }
1190
1216
  }
1191
1217
  }
1192
1218
  if (config.slowRequestMs !== void 0) {
@@ -1255,6 +1281,10 @@ function validateConfig(config) {
1255
1281
  });
1256
1282
  return errors;
1257
1283
  }
1284
+ var RED = "\x1B[31m";
1285
+ var BOLD = "\x1B[1m";
1286
+ var DIM = "\x1B[2m";
1287
+ var RESET = "\x1B[0m";
1258
1288
  /**
1259
1289
  * Format config errors for terminal output.
1260
1290
  */
@@ -1269,6 +1299,16 @@ function formatConfigErrors(errors) {
1269
1299
  }
1270
1300
  return lines.join("\n");
1271
1301
  }
1302
+ var VIRTUAL_MODULE_NAMES = {
1303
+ "virtual:timber-rsc-entry": "RSC entry (server component handler)",
1304
+ "virtual:timber-ssr-entry": "SSR entry (HTML renderer)",
1305
+ "virtual:timber-browser-entry": "Browser entry (client hydration)",
1306
+ "virtual:timber-config": "Runtime config (timber.config.ts)",
1307
+ "virtual:timber-route-manifest": "Route manifest (app/ file tree)",
1308
+ "virtual:timber-instrumentation": "Instrumentation (instrumentation.ts)",
1309
+ "virtual:timber-cache-handler": "Cache handler (timber.cache.ts)",
1310
+ "virtual:timber-build-manifest": "Build manifest (asset mapping)"
1311
+ };
1272
1312
  /**
1273
1313
  * Add timber-specific context to an error message that references virtual modules.
1274
1314
  *
@@ -1280,6 +1320,15 @@ function addVirtualModuleContext(errorMessage) {
1280
1320
  return errorMessage;
1281
1321
  }
1282
1322
  /**
1323
+ * Required (non-optional) peer dependencies that must be installed.
1324
+ */
1325
+ var REQUIRED_PEERS = [
1326
+ "react",
1327
+ "react-dom",
1328
+ "@vitejs/plugin-react",
1329
+ "@vitejs/plugin-rsc"
1330
+ ];
1331
+ /**
1283
1332
  * Check that required peer dependencies are installed.
1284
1333
  *
1285
1334
  * Uses require.resolve with a try/catch — no fs scanning.
@@ -1318,57 +1367,325 @@ function formatMissingPeers(results) {
1318
1367
  lines.push(` ${BOLD}pnpm add ${names.join(" ")}${RESET}`);
1319
1368
  return lines.join("\n");
1320
1369
  }
1321
- var knownKeys, RED, BOLD, DIM, RESET, VIRTUAL_MODULE_NAMES, REQUIRED_PEERS;
1322
- var init_config_validation = __esmMin((() => {
1323
- knownKeys = new Set(Object.keys({
1324
- output: true,
1325
- debug: true,
1326
- clientJavascript: true,
1327
- adapter: true,
1328
- allowedOrigins: true,
1329
- csrf: true,
1330
- limits: true,
1331
- forms: true,
1332
- pageExtensions: true,
1333
- slowRequestMs: true,
1334
- renderTimeoutMs: true,
1335
- devBrowserLogs: true,
1336
- dev: true,
1337
- serverTiming: true,
1338
- appDir: true,
1339
- mdx: true,
1340
- actionEncryption: true,
1341
- reactCompiler: true,
1342
- sitemap: true,
1343
- buildDir: true,
1344
- clientSegmentCache: true,
1345
- topLoader: true,
1346
- budget: true
1347
- }));
1348
- RED = "\x1B[31m";
1349
- BOLD = "\x1B[1m";
1350
- DIM = "\x1B[2m";
1351
- RESET = "\x1B[0m";
1352
- VIRTUAL_MODULE_NAMES = {
1353
- "virtual:timber-rsc-entry": "RSC entry (server component handler)",
1354
- "virtual:timber-ssr-entry": "SSR entry (HTML renderer)",
1355
- "virtual:timber-browser-entry": "Browser entry (client hydration)",
1356
- "virtual:timber-config": "Runtime config (timber.config.ts)",
1357
- "virtual:timber-route-manifest": "Route manifest (app/ file tree)",
1358
- "virtual:timber-instrumentation": "Instrumentation (instrumentation.ts)",
1359
- "virtual:timber-cache-handler": "Cache handler (timber.cache.ts)",
1360
- "virtual:timber-build-manifest": "Build manifest (asset mapping)"
1370
+ /** HMR custom event name for graph-affecting file changes. */
1371
+ var GRAPH_UPDATE_EVENT = "timber:graph-update";
1372
+ /**
1373
+ * Host-header allowlist check, ported branch-for-branch from Vite's
1374
+ * host-validation middleware (`isHostAllowedWithoutCache`) so this
1375
+ * endpoint's reachability matches the rest of the dev server:
1376
+ *
1377
+ * - `allowedHosts: true` allows everything
1378
+ * - a MISSING Host header is allowed (Vite parity — HTTP/1.0 probes)
1379
+ * - any IP-literal host is allowed (`vite --host` LAN access sends
1380
+ * `Host: 192.168.x.x:port`; rejecting it would 403 this endpoint
1381
+ * while every other dev route works)
1382
+ * - `localhost` and `*.localhost` are always allowed
1383
+ * - allowedHosts entries: exact match, or `.suffix` subdomain entries
1384
+ */
1385
+ function isAllowedGraphHost(hostHeader, allowedHosts) {
1386
+ if (allowedHosts === true) return true;
1387
+ if (hostHeader === void 0) return true;
1388
+ let host = hostHeader;
1389
+ const bracket = host.match(/^\[([^\]]+)\](?::\d+)?$/);
1390
+ if (bracket) return isIP(bracket[1]) === 6;
1391
+ const colon = host.lastIndexOf(":");
1392
+ if (colon !== -1) host = host.slice(0, colon);
1393
+ host = host.toLowerCase();
1394
+ if (isIP(host) !== 0) return true;
1395
+ if (host === "localhost" || host.endsWith(".localhost")) return true;
1396
+ for (const entry of allowedHosts ?? []) {
1397
+ const allowed = entry.toLowerCase();
1398
+ if (allowed.startsWith(".")) {
1399
+ if (host === allowed.slice(1) || host.endsWith(allowed)) return true;
1400
+ } else if (host === allowed) return true;
1401
+ }
1402
+ return false;
1403
+ }
1404
+ /**
1405
+ * Non-http(s) origins admitted without a host check: Vite's own
1406
+ * `file:` / `*-extension:` set (its host-validation regex), plus
1407
+ * `vscode-webview:` — VS Code webviews fetch with that Origin, and the
1408
+ * extension is this endpoint's primary consumer. Vite itself never
1409
+ * origin-checks plain HTTP GETs (only WebSocket upgrades), so this
1410
+ * layer is strictly additional; the additions keep it from rejecting
1411
+ * consumers Vite would serve.
1412
+ *
1413
+ * NOT admitted: `Origin: null`. Browsers serialize file:// pages'
1414
+ * opaque origin as the literal string `null` — but so do sandboxed
1415
+ * iframes and data: documents, exactly the untrusted embedders the
1416
+ * check exists to stop, and the header offers nothing to tell them
1417
+ * apart. file:// pages therefore cannot use this endpoint from a
1418
+ * browser; the `file:` scheme entry covers non-browser clients that
1419
+ * send a real scheme-form Origin (Vite admits the same set).
1420
+ */
1421
+ var TRUSTED_ORIGIN_SCHEMES = /^(?:file|vscode-webview|.+-extension):/i;
1422
+ /** Origin check: absent is fine (CLI probe); present must pass the host allowlist. */
1423
+ function isAllowedGraphOrigin(originHeader, allowedHosts) {
1424
+ if (originHeader === void 0) return true;
1425
+ if (TRUSTED_ORIGIN_SCHEMES.test(originHeader)) return true;
1426
+ let originUrl;
1427
+ try {
1428
+ originUrl = new URL(originHeader);
1429
+ } catch {
1430
+ return false;
1431
+ }
1432
+ if (originUrl.host === "") return false;
1433
+ const bareHost = originUrl.hostname.replace(/^\[|\]$/g, "");
1434
+ if (isIP(bareHost) !== 0) {
1435
+ if (bareHost === "127.0.0.1" || bareHost === "::1") return true;
1436
+ if (allowedHosts === true) return true;
1437
+ return (allowedHosts ?? []).some((entry) => entry.toLowerCase() === bareHost);
1438
+ }
1439
+ return isAllowedGraphHost(originUrl.host, allowedHosts);
1440
+ }
1441
+ function sendJson(res, status, body) {
1442
+ res.statusCode = status;
1443
+ res.setHeader("content-type", "application/json; charset=utf-8");
1444
+ res.end(JSON.stringify(body));
1445
+ }
1446
+ /**
1447
+ * Echo an ADMITTED origin back as CORS headers. A webview fetch from
1448
+ * `vscode-webview://…` passes the origin check but the browser rejects
1449
+ * the response body without `Access-Control-Allow-Origin` — the exact
1450
+ * transport design/47 specifies for the extension. Only the validated
1451
+ * origin is echoed (never `*`), with `Vary: Origin` for any cache in
1452
+ * between; unadmitted origins were already 403'd and get nothing.
1453
+ */
1454
+ function reflectCors(res, origin) {
1455
+ if (!origin) return;
1456
+ res.setHeader("Access-Control-Allow-Origin", origin);
1457
+ res.setHeader("Vary", "Origin");
1458
+ }
1459
+ /**
1460
+ * Create the Connect middleware handling GET /__timber/graph.
1461
+ *
1462
+ * Query surface: `?file=<path>` (absolute or project-root-relative) or
1463
+ * `?all=1`. Anything else is a 400 — fail loudly, like the CLI.
1464
+ */
1465
+ function createGraphEndpointMiddleware(server, ctx) {
1466
+ const sourceExtensions = buildSourceExtensions(ctx.config.pageExtensions);
1467
+ return async (req, res, next) => {
1468
+ const rawUrl = req.url;
1469
+ if (!rawUrl || !rawUrl.startsWith("/__timber/")) {
1470
+ next();
1471
+ return;
1472
+ }
1473
+ const url = new URL(rawUrl, "http://placeholder.invalid");
1474
+ if (url.pathname !== "/__timber/graph") {
1475
+ sendJson(res, 404, { error: `unknown /__timber/ endpoint: ${url.pathname}` });
1476
+ return;
1477
+ }
1478
+ if (req.method !== "GET") {
1479
+ res.setHeader("Allow", "GET");
1480
+ sendJson(res, 405, { error: "GET only" });
1481
+ return;
1482
+ }
1483
+ const origin = req.headers.origin;
1484
+ const allowedHosts = server.config.server.allowedHosts;
1485
+ if (!server.config.server.https && !isAllowedGraphHost(req.headers.host, allowedHosts)) {
1486
+ sendJson(res, 403, { error: "host not allowed" });
1487
+ return;
1488
+ }
1489
+ if (!isAllowedGraphOrigin(origin, allowedHosts)) {
1490
+ sendJson(res, 403, { error: "origin not allowed" });
1491
+ return;
1492
+ }
1493
+ reflectCors(res, origin);
1494
+ try {
1495
+ const { classifyLiveFile, classifyLiveProject } = await import("./_chunks/live-graph-Bx4HodF1.js");
1496
+ const preserveSymlinks = server.config.resolve.preserveSymlinks;
1497
+ const root = normalizePath(preserveSymlinks ? ctx.root : await realpath(ctx.root));
1498
+ const appDir = normalizePath(preserveSymlinks ? ctx.appDir : await realpath(ctx.appDir).catch(() => join(root, relative(ctx.root, ctx.appDir))));
1499
+ const liveCtx = {
1500
+ rsc: server.environments.rsc.moduleGraph,
1501
+ ssr: server.environments.ssr.moduleGraph,
1502
+ client: server.environments.client.moduleGraph,
1503
+ root,
1504
+ appDir,
1505
+ pageExtensions: ctx.config.pageExtensions
1506
+ };
1507
+ const allParam = url.searchParams.get("all");
1508
+ if (allParam !== null && allParam !== "1") {
1509
+ sendJson(res, 400, { error: `unsupported all value: ${allParam} (use ?all=1)` });
1510
+ return;
1511
+ }
1512
+ if (allParam === "1") {
1513
+ sendJson(res, 200, {
1514
+ version: 1,
1515
+ source: "dev-server",
1516
+ cached: false,
1517
+ ...await classifyLiveProject(liveCtx)
1518
+ });
1519
+ return;
1520
+ }
1521
+ const fileParam = url.searchParams.get("file");
1522
+ if (!fileParam) {
1523
+ sendJson(res, 400, { error: "missing ?file=<path> (or ?all=1)" });
1524
+ return;
1525
+ }
1526
+ const absolute = normalizePath(isAbsolute(fileParam) ? resolve(fileParam) : resolve(root, fileParam));
1527
+ let target;
1528
+ try {
1529
+ const physical = normalizePath(await realpath(absolute));
1530
+ const rootPhysical = preserveSymlinks ? normalizePath(await realpath(root)) : root;
1531
+ if (physical !== rootPhysical && !physical.startsWith(rootPhysical + "/") && !physical.startsWith(rootPhysical + "\\")) {
1532
+ sendJson(res, 404, { error: `not a project file under ${root}` });
1533
+ return;
1534
+ }
1535
+ if (preserveSymlinks) {
1536
+ if (physical !== rootPhysical + absolute.slice(root.length)) {
1537
+ sendJson(res, 404, { error: `not a project source file: ${absolute}` });
1538
+ return;
1539
+ }
1540
+ }
1541
+ target = normalizePath(preserveSymlinks ? absolute : physical);
1542
+ } catch {
1543
+ sendJson(res, 404, { error: `file not found: ${absolute}` });
1544
+ return;
1545
+ }
1546
+ if (target !== root && !target.startsWith(root + "/") && !target.startsWith(root + "\\")) {
1547
+ sendJson(res, 404, { error: `not a project file under ${root}` });
1548
+ return;
1549
+ }
1550
+ if (!(await stat(target).catch(() => null))?.isFile() || !isScannableSourceFile(normalizePath(target), normalizePath(root), sourceExtensions)) {
1551
+ sendJson(res, 404, { error: `not a project source file: ${target}` });
1552
+ return;
1553
+ }
1554
+ const errors = [];
1555
+ const module = await classifyLiveFile(target, liveCtx, void 0, errors);
1556
+ sendJson(res, 200, {
1557
+ version: 1,
1558
+ source: "dev-server",
1559
+ cached: false,
1560
+ target: {
1561
+ input: fileParam,
1562
+ resolved: target
1563
+ },
1564
+ kind: module.kind,
1565
+ pending: module.pending,
1566
+ subtreeUnknown: module.subtreeUnknown,
1567
+ envs: module.envs,
1568
+ boundary: module.boundary,
1569
+ chains: module.chains,
1570
+ poisonings: module.poisonings,
1571
+ errors
1572
+ });
1573
+ } catch (error) {
1574
+ sendJson(res, 500, { error: error instanceof Error ? error.message : String(error) });
1575
+ }
1576
+ };
1577
+ }
1578
+ /**
1579
+ * Build the push channel: `timber:graph-update` custom HMR events per
1580
+ * project-source change. Consumers (the VS Code extension) re-query
1581
+ * and debounce on their side; the channel just emits. Non-source noise
1582
+ * (build output, dotdirs) is filtered by the same extension set the
1583
+ * scanners use.
1584
+ *
1585
+ * Two phases per edit, because one is not enough (codex review, PR
1586
+ * #1057): the `invalidated` event fires from the plugin's `hotUpdate`
1587
+ * hook — after Vite clears the module's transform result, but its
1588
+ * importer EDGES are only rebuilt when the module is next transformed.
1589
+ * The `transformed` event fires for exactly the files with a pending
1590
+ * invalidation, and only once the node's `transformResult` is set
1591
+ * again — the plugin transform hook itself runs BEFORE Vite's trailing
1592
+ * `vite:import-analysis` (which rebuilds the edges), so the hook only
1593
+ * marks the file "settling" and a short bounded timer confirms
1594
+ * completion via `isTransformed` before emitting. (A module nothing
1595
+ * re-requests never re-transforms — its `transformed` event waits for
1596
+ * the next render, which is also when the graph has new information.)
1597
+ */
1598
+ function makeGraphUpdateChannel(ctx, send, isTransformed, canonicalize = (file) => file) {
1599
+ /** Files invalidated but not yet re-transformed, per environment. */
1600
+ const pending = /* @__PURE__ */ new Set();
1601
+ const key = (file, environment) => `${environment}\0${file}`;
1602
+ const root = normalizePath(canonicalize(ctx.root));
1603
+ const extensions = buildSourceExtensions(ctx.config.pageExtensions);
1604
+ const emitTransformed = (file, environment, structural) => {
1605
+ send({
1606
+ type: "custom",
1607
+ event: GRAPH_UPDATE_EVENT,
1608
+ data: structural ? {
1609
+ file,
1610
+ event: "update",
1611
+ environment,
1612
+ phase: "transformed",
1613
+ structural: true
1614
+ } : {
1615
+ file,
1616
+ event: "update",
1617
+ environment,
1618
+ phase: "transformed"
1619
+ }
1620
+ });
1361
1621
  };
1362
- REQUIRED_PEERS = [
1363
- "react",
1364
- "react-dom",
1365
- "@vitejs/plugin-react",
1366
- "@vitejs/plugin-rsc"
1622
+ /**
1623
+ * Confirm the transform request finished (transformResult set again)
1624
+ * before emitting phase `transformed`. If confirmation never arrives
1625
+ * within the bounded schedule below, the pending key is RE-ARMED
1626
+ * rather than emitted — a `transformed` event over a still-stale
1627
+ * graph would be a false all-clear with no corrective event.
1628
+ */
1629
+ /**
1630
+ * Delays between confirmation re-checks: dense while a normal
1631
+ * transform request finishes, then exponential backoff for slow
1632
+ * import-analysis passes (large graphs, cold dep optimizer) — a
1633
+ * completed slow transform is CACHED, so no later transform hook may
1634
+ * ever fire for it and the tail checks are the only chance to emit.
1635
+ * Total window ≈ 16 s, then give up (bounded — the async-safety
1636
+ * rules ban open-ended polling) and re-arm the pending key.
1637
+ */
1638
+ const CONFIRM_DELAYS_MS = [
1639
+ ...Array.from({ length: 25 }, () => 20),
1640
+ 500,
1641
+ 1e3,
1642
+ 2e3,
1643
+ 4e3,
1644
+ 8e3
1367
1645
  ];
1368
- }));
1646
+ const confirmAndEmit = (file, environment, attempt = 0, structural = false) => {
1647
+ if (!isTransformed || isTransformed(file, environment)) {
1648
+ emitTransformed(file, environment, structural);
1649
+ return;
1650
+ }
1651
+ if (attempt >= CONFIRM_DELAYS_MS.length) {
1652
+ if (!structural) pending.add(key(file, environment));
1653
+ return;
1654
+ }
1655
+ setTimeout(() => confirmAndEmit(file, environment, attempt + 1, structural), CONFIRM_DELAYS_MS[attempt]);
1656
+ };
1657
+ return {
1658
+ onHotUpdate(update) {
1659
+ const file = normalizePath(canonicalize(update.file));
1660
+ if (!isScannableSourceFile(file, root, extensions)) return;
1661
+ if (update.type === "delete") pending.delete(key(file, update.environment));
1662
+ else pending.add(key(file, update.environment));
1663
+ send({
1664
+ type: "custom",
1665
+ event: GRAPH_UPDATE_EVENT,
1666
+ data: {
1667
+ file,
1668
+ event: update.type,
1669
+ environment: update.environment,
1670
+ phase: "invalidated"
1671
+ }
1672
+ });
1673
+ },
1674
+ onTransform(id, environment) {
1675
+ const file = normalizePath(id.split("?")[0]);
1676
+ if (file.includes("virtual:timber-route-manifest")) {
1677
+ confirmAndEmit(file, environment, 25, true);
1678
+ return;
1679
+ }
1680
+ const pendingKey = key(file, environment);
1681
+ if (!pending.has(pendingKey)) return;
1682
+ pending.delete(pendingKey);
1683
+ confirmAndEmit(file, environment);
1684
+ }
1685
+ };
1686
+ }
1369
1687
  //#endregion
1370
1688
  //#region src/server/compress.ts
1371
- init_config_validation();
1372
1689
  /**
1373
1690
  * MIME types that benefit from compression.
1374
1691
  * text/* is handled via prefix matching; these are the specific
@@ -1481,7 +1798,8 @@ function compressResponse(request, response) {
1481
1798
  */
1482
1799
  function compressWithGzip(body) {
1483
1800
  const gzip = createGzip({ flush: constants.Z_SYNC_FLUSH });
1484
- pipeline(Readable.fromWeb(body), gzip, () => {});
1801
+ const nodeInput = Readable.fromWeb(body);
1802
+ pipeline(nodeInput, gzip, () => {});
1485
1803
  return Readable.toWeb(gzip);
1486
1804
  }
1487
1805
  //#endregion
@@ -1516,10 +1834,35 @@ var ASSET_EXTENSIONS = /\.(?:js|ts|tsx|jsx|css|map|json|svg|png|jpg|jpeg|gif|web
1516
1834
  * Hook: configureServer (returns post-hook to register after Vite's middleware)
1517
1835
  */
1518
1836
  function timberDevServer(ctx) {
1837
+ let graphChannel = null;
1519
1838
  return {
1520
1839
  name: "timber-dev-server",
1521
1840
  apply: "serve",
1522
1841
  /**
1842
+ * Push channel for the graph endpoint, phase 1: `invalidated`, one
1843
+ * per (file, environment). Emitted from hotUpdate — which runs
1844
+ * AFTER Vite invalidates the environment module graphs — never
1845
+ * from a raw watcher listener, which would race consumers into
1846
+ * querying pre-invalidation memberships (design/47 §"Dev-server
1847
+ * endpoint").
1848
+ */
1849
+ hotUpdate({ file, type }) {
1850
+ graphChannel?.onHotUpdate({
1851
+ file,
1852
+ type,
1853
+ environment: this.environment.name
1854
+ });
1855
+ },
1856
+ /**
1857
+ * Push channel phase 2: `transformed`, when a pending-invalidated
1858
+ * module's import edges are actually rebuilt. A Set lookup for
1859
+ * everything without a pending invalidation — free on the hot
1860
+ * path. Returning nothing leaves the code untouched.
1861
+ */
1862
+ transform(_code, id) {
1863
+ graphChannel?.onTransform(id, this.environment.name);
1864
+ },
1865
+ /**
1523
1866
  * Register the dev server middleware and config file watcher.
1524
1867
  *
1525
1868
  * Registers as a pre-hook (no return value) so our middleware runs
@@ -1532,7 +1875,30 @@ function timberDevServer(ctx) {
1532
1875
  const configPaths = CONFIG_FILE_NAMES.map((name) => join(ctx.root, name));
1533
1876
  server.watcher.add(configPaths);
1534
1877
  listenForClientErrors(server, ctx.root);
1878
+ server.middlewares.use(createGraphEndpointMiddleware(server, ctx));
1879
+ graphChannel = makeGraphUpdateChannel(ctx, (payload) => server.hot.send(payload), (file, environment) => {
1880
+ const graph = server.environments[environment]?.moduleGraph;
1881
+ if (!graph) return false;
1882
+ const nodes = graph.getModulesByFile(file);
1883
+ if (nodes) {
1884
+ for (const node of nodes) if (node.transformResult != null) return true;
1885
+ return false;
1886
+ }
1887
+ return graph.getModuleById(file)?.transformResult != null;
1888
+ }, (file) => {
1889
+ if (server.config?.resolve?.preserveSymlinks || file.includes("virtual:")) return file;
1890
+ try {
1891
+ return realpathSync(file);
1892
+ } catch {
1893
+ try {
1894
+ return join(realpathSync(dirname(file)), basename(file));
1895
+ } catch {
1896
+ return file;
1897
+ }
1898
+ }
1899
+ });
1535
1900
  server.middlewares.use(createTimberMiddleware(server, ctx));
1901
+ registerDevDiscovery(server.httpServer, ctx.root, server.config);
1536
1902
  if (ctx.holdingServer) {
1537
1903
  const originalListen = server.listen.bind(server);
1538
1904
  const holdingRef = ctx.holdingServer;
@@ -2071,7 +2437,7 @@ function timberEntries(ctx) {
2071
2437
  }
2072
2438
  //#endregion
2073
2439
  //#region src/plugins/mdx.ts
2074
- var MDX_EXTENSIONS = ["mdx", "md"];
2440
+ var MDX_EXTENSIONS_UNDOTTED = [...MDX_EXTENSIONS].map((ext) => ext.slice(1));
2075
2441
  /**
2076
2442
  * Check if mdx-components.tsx (or .ts, .jsx, .js) exists at the project root
2077
2443
  * or in src/. Root takes precedence, matching Next.js behavior.
@@ -2096,7 +2462,7 @@ function findMdxComponents(root) {
2096
2462
  function shouldActivate(ctx) {
2097
2463
  if (ctx.config.mdx === false) return false;
2098
2464
  const exts = ctx.config.pageExtensions;
2099
- if (exts && exts.some((ext) => MDX_EXTENSIONS.includes(ext))) return true;
2465
+ if (exts && exts.some((ext) => MDX_EXTENSIONS_UNDOTTED.includes(ext))) return true;
2100
2466
  if (existsSync(join(ctx.root, "content"))) return true;
2101
2467
  return false;
2102
2468
  }
@@ -2121,7 +2487,8 @@ function shouldActivate(ctx) {
2121
2487
  */
2122
2488
  async function tryImport(name, projectRoot) {
2123
2489
  try {
2124
- const mod = await import(pathToFileURL(createRequire(join(projectRoot, "package.json")).resolve(name)).href);
2490
+ const resolved = createRequire(join(projectRoot, "package.json")).resolve(name);
2491
+ const mod = await import(pathToFileURL(resolved).href);
2125
2492
  return mod.default ?? mod;
2126
2493
  } catch {
2127
2494
  try {
@@ -2382,6 +2749,7 @@ var ROUTE_FILE_PATTERNS = /\/(page|layout|middleware|access|route|error|global-e
2382
2749
  */
2383
2750
  function writeCodegen(ctx) {
2384
2751
  if (!ctx.routeTree) return;
2752
+ if (process.env.TIMBER_ANALYZE === "1") return;
2385
2753
  writeRouteCodegen(ctx.routeTree, ctx.appDir, ctx.root).catch((err) => {
2386
2754
  console.warn("[timber] Failed to write codegen output:", err);
2387
2755
  });
@@ -2609,9 +2977,7 @@ function warnSchemaValidation(ctx) {
2609
2977
  case "bracket-mismatch":
2610
2978
  console.warn(`[timber] ${w.message}`);
2611
2979
  break;
2612
- case "missing-key":
2613
- console.warn(`[timber] ${w.message}`);
2614
- break;
2980
+ case "missing-key": console.warn(`[timber] ${w.message}`);
2615
2981
  }
2616
2982
  }
2617
2983
  }
@@ -2633,14 +2999,13 @@ var __dirname = dirname(fileURLToPath(import.meta.url));
2633
2999
  var PKG_ROOT = __dirname.endsWith("plugins") ? resolve(__dirname, "..", "..") : resolve(__dirname, "..");
2634
3000
  var SHIMS_DIR = resolve(PKG_ROOT, "src", "shims");
2635
3001
  /**
2636
- * Virtual module IDs for server-only and client-only poison pills.
2637
- *
2638
- * These packages cause build errors when imported in the wrong environment:
2639
- * - `server-only` errors when imported in a client component
2640
- * - `client-only` errors when imported in a server component
3002
+ * The server-only marker's virtual ID, needed directly by the
3003
+ * `#server-only-guard` resolution branch below. All poison-pill rules
3004
+ * (specifiers, virtual IDs, error messages, environment policy) live in
3005
+ * analyze/poison-rules.ts — the single source of truth shared with the
3006
+ * `timber graph` reporter (design/47 §3).
2641
3007
  */
2642
- var SERVER_ONLY_VIRTUAL = "\0timber:server-only";
2643
- var CLIENT_ONLY_VIRTUAL = "\0timber:client-only";
3008
+ var SERVER_ONLY_VIRTUAL = markerFor("server-only").virtualId;
2644
3009
  /**
2645
3010
  * Map from @timber-js/app/<subpath> to relative src/ file paths.
2646
3011
  *
@@ -2767,8 +3132,7 @@ function timberShims(_ctx) {
2767
3132
  * the browser.
2768
3133
  */
2769
3134
  resolveId(id) {
2770
- if (id === "server-only") return SERVER_ONLY_VIRTUAL;
2771
- if (id === "client-only") return CLIENT_ONLY_VIRTUAL;
3135
+ for (const marker of EXPLICIT_MARKERS) if (id === marker.specifier) return marker.virtualId;
2772
3136
  const cleanId = stripJsExtension(id);
2773
3137
  if (cleanId in SHIM_MAP) {
2774
3138
  if (envName(this) === "client" && cleanId === "next/navigation") return resolve(SHIMS_DIR, "navigation-client.ts");
@@ -2817,21 +3181,8 @@ function timberShims(_ctx) {
2817
3181
  * clearly identifies the boundary violation.
2818
3182
  */
2819
3183
  load(id) {
2820
- const isClient = envName(this) === "client";
2821
- if (id === SERVER_ONLY_VIRTUAL) {
2822
- if (isClient) return `throw new Error(
2823
- "This module cannot be imported from a Client Component module. " +
2824
- "It should only be used from a Server Component."
2825
- );`;
2826
- return "export {};";
2827
- }
2828
- if (id === CLIENT_ONLY_VIRTUAL) {
2829
- if (!isClient) return `throw new Error(
2830
- "This module cannot be imported from a Server Component module. " +
2831
- "It should only be used from a Client Component."
2832
- );`;
2833
- return "export {};";
2834
- }
3184
+ const env = envName(this);
3185
+ for (const marker of EXPLICIT_MARKERS) if (id === marker.virtualId) return poisonPillSource(marker, env);
2835
3186
  if (id === "\0timber:server-empty") return `
2836
3187
  const msg = "[timber] @timber-js/app/server was imported from client code. " +
2837
3188
  "Server modules (headers, cookies, redirect, deny, etc.) cannot be used in client components. " +
@@ -4448,7 +4799,7 @@ function encodeInteger(builder, num, relative) {
4448
4799
  } while (delta > 0);
4449
4800
  return num;
4450
4801
  }
4451
- var bufLength = 1024 * 16;
4802
+ var bufLength = 16384;
4452
4803
  var td = typeof TextDecoder !== "undefined" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== "undefined" ? { decode(buf) {
4453
4804
  return Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength).toString();
4454
4805
  } } : { decode(buf) {
@@ -4501,7 +4852,7 @@ function encode(decoded) {
4501
4852
  return writer.flush();
4502
4853
  }
4503
4854
  //#endregion
4504
- //#region ../../node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.mjs
4855
+ //#region ../../node_modules/.pnpm/magic-string@1.2.0/node_modules/magic-string/dist/index.mjs
4505
4856
  var BitSet = class BitSet {
4506
4857
  constructor(arg) {
4507
4858
  this.bits = arg instanceof BitSet ? arg.bits.slice() : [];
@@ -4545,14 +4896,16 @@ var Chunk = class Chunk {
4545
4896
  return this.start < index && index < this.end;
4546
4897
  }
4547
4898
  eachNext(fn) {
4548
- let chunk = this;
4899
+ fn(this);
4900
+ let chunk = this.next;
4549
4901
  while (chunk) {
4550
4902
  fn(chunk);
4551
4903
  chunk = chunk.next;
4552
4904
  }
4553
4905
  }
4554
4906
  eachPrevious(fn) {
4555
- let chunk = this;
4907
+ fn(this);
4908
+ let chunk = this.previous;
4556
4909
  while (chunk) {
4557
4910
  fn(chunk);
4558
4911
  chunk = chunk.previous;
@@ -4610,10 +4963,8 @@ var Chunk = class Chunk {
4610
4963
  if (this.outro.length) return true;
4611
4964
  const trimmed = this.content.replace(rx, "");
4612
4965
  if (trimmed.length) {
4613
- if (trimmed !== this.content) {
4614
- this.split(this.start + trimmed.length).edit("", void 0, true);
4615
- if (this.edited) this.edit(trimmed, this.storeName, true);
4616
- }
4966
+ if (trimmed !== this.content) if (this.edited) this.edit(trimmed, this.storeName, true);
4967
+ else this.split(this.start + trimmed.length).edit("", void 0, true);
4617
4968
  return true;
4618
4969
  } else {
4619
4970
  this.edit("", void 0, true);
@@ -4626,9 +4977,9 @@ var Chunk = class Chunk {
4626
4977
  if (this.intro.length) return true;
4627
4978
  const trimmed = this.content.replace(rx, "");
4628
4979
  if (trimmed.length) {
4629
- if (trimmed !== this.content) {
4630
- const newChunk = this.split(this.end - trimmed.length);
4631
- if (this.edited) newChunk.edit(trimmed, this.storeName, true);
4980
+ if (trimmed !== this.content) if (this.edited) this.edit(trimmed, this.storeName, true);
4981
+ else {
4982
+ this.split(this.end - trimmed.length);
4632
4983
  this.edit("", void 0, true);
4633
4984
  }
4634
4985
  return true;
@@ -4639,14 +4990,27 @@ var Chunk = class Chunk {
4639
4990
  }
4640
4991
  }
4641
4992
  };
4993
+ /**
4994
+ * The single error type thrown by MagicString.
4995
+ *
4996
+ * Every message is prefixed with `[MagicString]` so its source is obvious at a
4997
+ * glance, and is kept short and consistent in tone.
4998
+ */
4999
+ var MagicStringError = class extends Error {
5000
+ name = "MagicStringError";
5001
+ constructor(message, options) {
5002
+ super(`[MagicString] ${message}`, options);
5003
+ }
5004
+ };
4642
5005
  function getBtoa() {
4643
5006
  if (typeof globalThis !== "undefined" && typeof globalThis.btoa === "function") return (str) => globalThis.btoa(unescape(encodeURIComponent(str)));
4644
- else if (typeof Buffer === "function") return (str) => Buffer.from(str, "utf-8").toString("base64");
4645
- else return () => {
4646
- throw new Error("Unsupported environment: `window.btoa` or `Buffer` should be supported.");
5007
+ const buffer = globalThis["Buffer"];
5008
+ if (buffer) return (str) => buffer.from(str, "utf-8").toString("base64");
5009
+ return () => {
5010
+ throw new MagicStringError("unsupported environment: `btoa` or `Buffer` is required");
4647
5011
  };
4648
5012
  }
4649
- var btoa = /*#__PURE__*/ getBtoa();
5013
+ var btoa = /* #__PURE__ */ getBtoa();
4650
5014
  var SourceMap = class {
4651
5015
  constructor(properties) {
4652
5016
  this.version = 3;
@@ -4658,43 +5022,20 @@ var SourceMap = class {
4658
5022
  if (typeof properties.x_google_ignoreList !== "undefined") this.x_google_ignoreList = properties.x_google_ignoreList;
4659
5023
  if (typeof properties.debugId !== "undefined") this.debugId = properties.debugId;
4660
5024
  }
5025
+ /**
5026
+ * Returns the equivalent of `JSON.stringify(map)`
5027
+ */
4661
5028
  toString() {
4662
5029
  return JSON.stringify(this);
4663
5030
  }
5031
+ /**
5032
+ * Returns a DataURI containing the sourcemap. Useful for doing this sort of thing:
5033
+ * `generateMap(options?: SourceMapOptions): SourceMap;`
5034
+ */
4664
5035
  toUrl() {
4665
- return "data:application/json;charset=utf-8;base64," + btoa(this.toString());
5036
+ return `data:application/json;charset=utf-8;base64,${btoa(this.toString())}`;
4666
5037
  }
4667
5038
  };
4668
- function guessIndent(code) {
4669
- const lines = code.split("\n");
4670
- const tabbed = lines.filter((line) => /^\t+/.test(line));
4671
- const spaced = lines.filter((line) => /^ {2,}/.test(line));
4672
- if (tabbed.length === 0 && spaced.length === 0) return null;
4673
- if (tabbed.length >= spaced.length) return " ";
4674
- const min = spaced.reduce((previous, current) => {
4675
- const numSpaces = /^ +/.exec(current)[0].length;
4676
- return Math.min(numSpaces, previous);
4677
- }, Infinity);
4678
- return new Array(min + 1).join(" ");
4679
- }
4680
- function getRelativePath(from, to) {
4681
- const fromParts = from.split(/[/\\]/);
4682
- const toParts = to.split(/[/\\]/);
4683
- fromParts.pop();
4684
- while (fromParts[0] === toParts[0]) {
4685
- fromParts.shift();
4686
- toParts.shift();
4687
- }
4688
- if (fromParts.length) {
4689
- let i = fromParts.length;
4690
- while (i--) fromParts[i] = "..";
4691
- }
4692
- return fromParts.concat(toParts).join("/");
4693
- }
4694
- var toString = Object.prototype.toString;
4695
- function isObject(thing) {
4696
- return toString.call(thing) === "[object Object]";
4697
- }
4698
5039
  function getLocator(source) {
4699
5040
  const originalLines = source.split("\n");
4700
5041
  const lineOffsets = [];
@@ -4717,6 +5058,36 @@ function getLocator(source) {
4717
5058
  };
4718
5059
  };
4719
5060
  }
5061
+ function getRelativePath(from, to) {
5062
+ const fromParts = from.split(/[/\\]/);
5063
+ const toParts = to.split(/[/\\]/);
5064
+ fromParts.pop();
5065
+ while (fromParts[0] === toParts[0]) {
5066
+ fromParts.shift();
5067
+ toParts.shift();
5068
+ }
5069
+ if (fromParts.length) {
5070
+ let i = fromParts.length;
5071
+ while (i--) fromParts[i] = "..";
5072
+ }
5073
+ return fromParts.concat(toParts).join("/");
5074
+ }
5075
+ function guessIndent(code) {
5076
+ const lines = code.split("\n");
5077
+ const tabbed = lines.filter((line) => /^\t+/.test(line));
5078
+ const spaced = lines.filter((line) => /^ {2,}/.test(line));
5079
+ if (tabbed.length === 0 && spaced.length === 0) return null;
5080
+ if (tabbed.length >= spaced.length) return " ";
5081
+ const min = spaced.reduce((previous, current) => {
5082
+ const numSpaces = /^ +/.exec(current)[0].length;
5083
+ return Math.min(numSpaces, previous);
5084
+ }, Infinity);
5085
+ return " ".repeat(min);
5086
+ }
5087
+ var toString = Object.prototype.toString;
5088
+ function isObject(thing) {
5089
+ return toString.call(thing) === "[object Object]";
5090
+ }
4720
5091
  var wordRegex = /\w/;
4721
5092
  var Mappings = class {
4722
5093
  constructor(hires) {
@@ -4816,6 +5187,8 @@ var Mappings = class {
4816
5187
  }
4817
5188
  };
4818
5189
  var n = "\n";
5190
+ var NEWLINE_CHAR = "\n".charCodeAt(0);
5191
+ var CR_CHAR = "\r".charCodeAt(0);
4819
5192
  var warned = {
4820
5193
  insertLeft: false,
4821
5194
  insertRight: false,
@@ -4851,11 +5224,11 @@ var MagicString = class MagicString {
4851
5224
  },
4852
5225
  byStart: {
4853
5226
  writable: true,
4854
- value: {}
5227
+ value: /* @__PURE__ */ new Map([[0, chunk]])
4855
5228
  },
4856
5229
  byEnd: {
4857
5230
  writable: true,
4858
- value: {}
5231
+ value: /* @__PURE__ */ new Map([[string.length, chunk]])
4859
5232
  },
4860
5233
  filename: {
4861
5234
  writable: true,
@@ -4886,35 +5259,52 @@ var MagicString = class MagicString {
4886
5259
  value: options.offset || 0
4887
5260
  }
4888
5261
  });
4889
- this.byStart[0] = chunk;
4890
- this.byEnd[string.length] = chunk;
4891
5262
  }
5263
+ /**
5264
+ * Adds the specified character index (with respect to the original string) to sourcemap mappings, if `hires` is false.
5265
+ */
4892
5266
  addSourcemapLocation(char) {
4893
5267
  this.sourcemapLocations.add(char);
4894
5268
  }
5269
+ /**
5270
+ * Appends the specified content to the end of the string.
5271
+ */
4895
5272
  append(content) {
4896
- if (typeof content !== "string") throw new TypeError("outro content must be a string");
5273
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
4897
5274
  this.outro += content;
4898
5275
  return this;
4899
5276
  }
5277
+ /**
5278
+ * Appends the specified content at the index in the original string.
5279
+ * If a range *ending* with index is subsequently moved, the insert will be moved with it.
5280
+ * See also `s.prependLeft(...)`.
5281
+ */
4900
5282
  appendLeft(index, content) {
4901
5283
  index = index + this.offset;
4902
- if (typeof content !== "string") throw new TypeError("inserted content must be a string");
5284
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
4903
5285
  this._split(index);
4904
- const chunk = this.byEnd[index];
5286
+ const chunk = this.byEnd.get(index);
4905
5287
  if (chunk) chunk.appendLeft(content);
4906
5288
  else this.intro += content;
4907
5289
  return this;
4908
5290
  }
5291
+ /**
5292
+ * Appends the specified content at the index in the original string.
5293
+ * If a range *starting* with index is subsequently moved, the insert will be moved with it.
5294
+ * See also `s.prependRight(...)`.
5295
+ */
4909
5296
  appendRight(index, content) {
4910
5297
  index = index + this.offset;
4911
- if (typeof content !== "string") throw new TypeError("inserted content must be a string");
5298
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
4912
5299
  this._split(index);
4913
- const chunk = this.byStart[index];
5300
+ const chunk = this.byStart.get(index);
4914
5301
  if (chunk) chunk.appendRight(content);
4915
5302
  else this.outro += content;
4916
5303
  return this;
4917
5304
  }
5305
+ /**
5306
+ * Does what you'd expect.
5307
+ */
4918
5308
  clone() {
4919
5309
  const cloned = new MagicString(this.original, {
4920
5310
  filename: this.filename,
@@ -4923,8 +5313,8 @@ var MagicString = class MagicString {
4923
5313
  let originalChunk = this.firstChunk;
4924
5314
  let clonedChunk = cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone();
4925
5315
  while (originalChunk) {
4926
- cloned.byStart[clonedChunk.start] = clonedChunk;
4927
- cloned.byEnd[clonedChunk.end] = clonedChunk;
5316
+ cloned.byStart.set(clonedChunk.start, clonedChunk);
5317
+ cloned.byEnd.set(clonedChunk.end, clonedChunk);
4928
5318
  const nextOriginalChunk = originalChunk.next;
4929
5319
  const nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();
4930
5320
  if (nextClonedChunk) {
@@ -4941,6 +5331,10 @@ var MagicString = class MagicString {
4941
5331
  cloned.outro = this.outro;
4942
5332
  return cloned;
4943
5333
  }
5334
+ /**
5335
+ * Generates a sourcemap object with raw mappings in array form, rather than encoded as a string.
5336
+ * Useful if you need to manipulate the sourcemap further, but most of the time you will use `generateMap` instead.
5337
+ */
4944
5338
  generateDecodedMap(options) {
4945
5339
  options = options || {};
4946
5340
  const sourceIndex = 0;
@@ -4965,12 +5359,17 @@ var MagicString = class MagicString {
4965
5359
  x_google_ignoreList: this.ignoreList ? [sourceIndex] : void 0
4966
5360
  };
4967
5361
  }
5362
+ /**
5363
+ * Generates a version 3 sourcemap.
5364
+ */
4968
5365
  generateMap(options) {
4969
5366
  return new SourceMap(this.generateDecodedMap(options));
4970
5367
  }
5368
+ /** @internal */
4971
5369
  _ensureindentStr() {
4972
5370
  if (this.indentStr === void 0) this.indentStr = guessIndent(this.original);
4973
5371
  }
5372
+ /** @internal */
4974
5373
  _getRawIndentString() {
4975
5374
  this._ensureindentStr();
4976
5375
  return this.indentStr;
@@ -4990,6 +5389,7 @@ var MagicString = class MagicString {
4990
5389
  indentStr = this.indentStr || " ";
4991
5390
  }
4992
5391
  if (indentStr === "") return this;
5392
+ const resolvedIndentStr = indentStr;
4993
5393
  options = options || {};
4994
5394
  const isExcluded = {};
4995
5395
  if (options.exclude) (typeof options.exclude[0] === "number" ? [options.exclude] : options.exclude).forEach((exclusion) => {
@@ -4997,13 +5397,22 @@ var MagicString = class MagicString {
4997
5397
  });
4998
5398
  let shouldIndentNextCharacter = options.indentStart !== false;
4999
5399
  const replacer = (match) => {
5000
- if (shouldIndentNextCharacter) return `${indentStr}${match}`;
5400
+ if (shouldIndentNextCharacter) return `${resolvedIndentStr}${match}`;
5001
5401
  shouldIndentNextCharacter = true;
5002
5402
  return match;
5003
5403
  };
5004
5404
  this.intro = this.intro.replace(pattern, replacer);
5005
5405
  let charIndex = 0;
5006
5406
  let chunk = this.firstChunk;
5407
+ const indentAt = (index) => {
5408
+ shouldIndentNextCharacter = false;
5409
+ if (index === chunk.start) chunk.prependRight(resolvedIndentStr);
5410
+ else {
5411
+ this._splitChunk(chunk, index);
5412
+ chunk = chunk.next;
5413
+ chunk.prependRight(resolvedIndentStr);
5414
+ }
5415
+ };
5007
5416
  while (chunk) {
5008
5417
  const end = chunk.end;
5009
5418
  if (chunk.edited) {
@@ -5011,24 +5420,34 @@ var MagicString = class MagicString {
5011
5420
  chunk.content = chunk.content.replace(pattern, replacer);
5012
5421
  if (chunk.content.length) shouldIndentNextCharacter = chunk.content[chunk.content.length - 1] === "\n";
5013
5422
  }
5014
- } else {
5423
+ } else if (options.exclude) {
5015
5424
  charIndex = chunk.start;
5016
5425
  while (charIndex < end) {
5017
5426
  if (!isExcluded[charIndex]) {
5018
- const char = this.original[charIndex];
5019
- if (char === "\n") shouldIndentNextCharacter = true;
5020
- else if (char !== "\r" && shouldIndentNextCharacter) {
5021
- shouldIndentNextCharacter = false;
5022
- if (charIndex === chunk.start) chunk.prependRight(indentStr);
5023
- else {
5024
- this._splitChunk(chunk, charIndex);
5025
- chunk = chunk.next;
5026
- chunk.prependRight(indentStr);
5027
- }
5028
- }
5427
+ const char = this.original.charCodeAt(charIndex);
5428
+ if (char === NEWLINE_CHAR) shouldIndentNextCharacter = true;
5429
+ else if (char !== CR_CHAR && shouldIndentNextCharacter) indentAt(charIndex);
5029
5430
  }
5030
5431
  charIndex += 1;
5031
5432
  }
5433
+ } else {
5434
+ charIndex = chunk.start;
5435
+ while (charIndex < end) {
5436
+ if (!shouldIndentNextCharacter) {
5437
+ const nextLine = this.original.indexOf(n, charIndex);
5438
+ if (nextLine === -1 || nextLine >= end) break;
5439
+ shouldIndentNextCharacter = true;
5440
+ charIndex = nextLine + 1;
5441
+ continue;
5442
+ }
5443
+ const char = this.original.charCodeAt(charIndex);
5444
+ if (char === NEWLINE_CHAR || char === CR_CHAR) {
5445
+ charIndex += 1;
5446
+ continue;
5447
+ }
5448
+ indentAt(charIndex);
5449
+ charIndex += 1;
5450
+ }
5032
5451
  }
5033
5452
  charIndex = chunk.end;
5034
5453
  chunk = chunk.next;
@@ -5036,9 +5455,11 @@ var MagicString = class MagicString {
5036
5455
  this.outro = this.outro.replace(pattern, replacer);
5037
5456
  return this;
5038
5457
  }
5458
+ /** @internal */
5039
5459
  insert() {
5040
- throw new Error("magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)");
5460
+ throw new MagicStringError("insert() is deprecated, use appendLeft() or prependRight()");
5041
5461
  }
5462
+ /** @internal */
5042
5463
  insertLeft(index, content) {
5043
5464
  if (!warned.insertLeft) {
5044
5465
  console.warn("magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead");
@@ -5046,6 +5467,7 @@ var MagicString = class MagicString {
5046
5467
  }
5047
5468
  return this.appendLeft(index, content);
5048
5469
  }
5470
+ /** @internal */
5049
5471
  insertRight(index, content) {
5050
5472
  if (!warned.insertRight) {
5051
5473
  console.warn("magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead");
@@ -5053,19 +5475,23 @@ var MagicString = class MagicString {
5053
5475
  }
5054
5476
  return this.prependRight(index, content);
5055
5477
  }
5478
+ /**
5479
+ * Moves the characters from `start` and `end` to `index`.
5480
+ */
5056
5481
  move(start, end, index) {
5057
5482
  start = start + this.offset;
5058
5483
  end = end + this.offset;
5059
5484
  index = index + this.offset;
5060
- if (index >= start && index <= end) throw new Error("Cannot move a selection inside itself");
5485
+ if (start === end) return this;
5486
+ if (index >= start && index <= end) throw new MagicStringError("cannot move a selection inside itself");
5061
5487
  this._split(start);
5062
5488
  this._split(end);
5063
5489
  this._split(index);
5064
- const first = this.byStart[start];
5065
- const last = this.byEnd[end];
5490
+ const first = this.byStart.get(start);
5491
+ const last = this.byEnd.get(end);
5066
5492
  const oldLeft = first.previous;
5067
5493
  const oldRight = last.next;
5068
- const newRight = this.byStart[index];
5494
+ const newRight = this.byStart.get(index);
5069
5495
  if (!newRight && last === this.lastChunk) return this;
5070
5496
  const newLeft = newRight ? newRight.previous : this.lastChunk;
5071
5497
  if (oldLeft) oldLeft.next = oldRight;
@@ -5083,23 +5509,42 @@ var MagicString = class MagicString {
5083
5509
  if (!newRight) this.lastChunk = last;
5084
5510
  return this;
5085
5511
  }
5512
+ /**
5513
+ * Replaces the characters from `start` to `end` with `content`, along with the appended/prepended content in
5514
+ * that range. The same restrictions as `s.remove()` apply.
5515
+ *
5516
+ * The fourth argument is optional. It can have a storeName property - if true, the original name will be stored
5517
+ * for later inclusion in a sourcemap's names array - and a contentOnly property which determines whether only
5518
+ * the content is overwritten, or anything that was appended/prepended to the range as well.
5519
+ *
5520
+ * It may be preferred to use `s.update(...)` instead if you wish to avoid overwriting the appended/prepended content.
5521
+ */
5086
5522
  overwrite(start, end, content, options) {
5087
- options = options || {};
5523
+ const optionObject = typeof options === "object" && options ? options : {};
5088
5524
  return this.update(start, end, content, {
5089
- ...options,
5090
- overwrite: !options.contentOnly
5525
+ ...optionObject,
5526
+ overwrite: !optionObject.contentOnly
5091
5527
  });
5092
5528
  }
5529
+ /**
5530
+ * Replaces the characters from `start` to `end` with `content`. The same restrictions as `s.remove()` apply.
5531
+ *
5532
+ * The fourth argument is optional. It can have a storeName property - if true, the original name will be stored
5533
+ * for later inclusion in a sourcemap's names array - and an overwrite property which determines whether only
5534
+ * the content is overwritten, or anything that was appended/prepended to the range as well.
5535
+ */
5093
5536
  update(start, end, content, options) {
5094
5537
  start = start + this.offset;
5095
5538
  end = end + this.offset;
5096
- if (typeof content !== "string") throw new TypeError("replacement content must be a string");
5539
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
5097
5540
  if (this.original.length !== 0) {
5098
5541
  while (start < 0) start += this.original.length;
5099
5542
  while (end < 0) end += this.original.length;
5100
5543
  }
5101
- if (end > this.original.length) throw new Error("end is out of bounds");
5102
- if (start === end) throw new Error("Cannot overwrite a zero-length range – use appendLeft or prependRight instead");
5544
+ if (start < 0) throw new MagicStringError(`start ${start} is out of bounds`);
5545
+ if (end > this.original.length) throw new MagicStringError(`end ${end} is out of bounds`);
5546
+ if (start === end) throw new MagicStringError(`cannot overwrite a zero-length range at ${start}, use appendLeft() or prependRight()`);
5547
+ if (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);
5103
5548
  this._split(start);
5104
5549
  this._split(end);
5105
5550
  if (options === true) {
@@ -5109,8 +5554,9 @@ var MagicString = class MagicString {
5109
5554
  }
5110
5555
  options = { storeName: true };
5111
5556
  }
5112
- const storeName = options !== void 0 ? options.storeName : false;
5113
- const overwrite = options !== void 0 ? options.overwrite : false;
5557
+ const optionObject = typeof options === "object" && options ? options : {};
5558
+ const storeName = optionObject.storeName || false;
5559
+ const overwrite = optionObject.overwrite || false;
5114
5560
  if (storeName) {
5115
5561
  const original = this.original.slice(start, end);
5116
5562
  Object.defineProperty(this.storedNames, original, {
@@ -5119,12 +5565,12 @@ var MagicString = class MagicString {
5119
5565
  enumerable: true
5120
5566
  });
5121
5567
  }
5122
- const first = this.byStart[start];
5123
- const last = this.byEnd[end];
5568
+ const first = this.byStart.get(start);
5569
+ const last = this.byEnd.get(end);
5124
5570
  if (first) {
5125
5571
  let chunk = first;
5126
5572
  while (chunk !== last) {
5127
- if (chunk.next !== this.byStart[chunk.end]) throw new Error("Cannot overwrite across a split point");
5573
+ if (chunk.next !== this.byStart.get(chunk.end)) throw new MagicStringError("cannot overwrite across a split point");
5128
5574
  chunk = chunk.next;
5129
5575
  chunk.edit("", false);
5130
5576
  }
@@ -5136,29 +5582,42 @@ var MagicString = class MagicString {
5136
5582
  }
5137
5583
  return this;
5138
5584
  }
5585
+ /**
5586
+ * Prepends the string with the specified content.
5587
+ */
5139
5588
  prepend(content) {
5140
- if (typeof content !== "string") throw new TypeError("outro content must be a string");
5589
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
5141
5590
  this.intro = content + this.intro;
5142
5591
  return this;
5143
5592
  }
5593
+ /**
5594
+ * Same as `s.appendLeft(...)`, except that the inserted content will go *before* any previous appends or prepends at index
5595
+ */
5144
5596
  prependLeft(index, content) {
5145
5597
  index = index + this.offset;
5146
- if (typeof content !== "string") throw new TypeError("inserted content must be a string");
5598
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
5147
5599
  this._split(index);
5148
- const chunk = this.byEnd[index];
5600
+ const chunk = this.byEnd.get(index);
5149
5601
  if (chunk) chunk.prependLeft(content);
5150
5602
  else this.intro = content + this.intro;
5151
5603
  return this;
5152
5604
  }
5605
+ /**
5606
+ * Same as `s.appendRight(...)`, except that the inserted content will go *before* any previous appends or prepends at `index`
5607
+ */
5153
5608
  prependRight(index, content) {
5154
5609
  index = index + this.offset;
5155
- if (typeof content !== "string") throw new TypeError("inserted content must be a string");
5610
+ if (typeof content !== "string") throw new MagicStringError(`content must be a string, got ${typeof content}`);
5156
5611
  this._split(index);
5157
- const chunk = this.byStart[index];
5612
+ const chunk = this.byStart.get(index);
5158
5613
  if (chunk) chunk.prependRight(content);
5159
5614
  else this.outro = content + this.outro;
5160
5615
  return this;
5161
5616
  }
5617
+ /**
5618
+ * Removes the characters from `start` to `end` (of the original string, **not** the generated string).
5619
+ * Removing the same content twice, or making removals that partially overlap, will cause an error.
5620
+ */
5162
5621
  remove(start, end) {
5163
5622
  start = start + this.offset;
5164
5623
  end = end + this.offset;
@@ -5167,19 +5626,22 @@ var MagicString = class MagicString {
5167
5626
  while (end < 0) end += this.original.length;
5168
5627
  }
5169
5628
  if (start === end) return this;
5170
- if (start < 0 || end > this.original.length) throw new Error("Character is out of bounds");
5171
- if (start > end) throw new Error("end must be greater than start");
5629
+ if (start < 0 || end > this.original.length) throw new MagicStringError(`range ${start}–${end} is out of bounds`);
5630
+ if (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);
5172
5631
  this._split(start);
5173
5632
  this._split(end);
5174
- let chunk = this.byStart[start];
5633
+ let chunk = this.byStart.get(start);
5175
5634
  while (chunk) {
5176
5635
  chunk.intro = "";
5177
5636
  chunk.outro = "";
5178
5637
  chunk.edit("");
5179
- chunk = end > chunk.end ? this.byStart[chunk.end] : null;
5638
+ chunk = end > chunk.end ? this.byStart.get(chunk.end) : null;
5180
5639
  }
5181
5640
  return this;
5182
5641
  }
5642
+ /**
5643
+ * Reset the modified characters from `start` to `end` (of the original string, **not** the generated string).
5644
+ */
5183
5645
  reset(start, end) {
5184
5646
  start = start + this.offset;
5185
5647
  end = end + this.offset;
@@ -5188,25 +5650,26 @@ var MagicString = class MagicString {
5188
5650
  while (end < 0) end += this.original.length;
5189
5651
  }
5190
5652
  if (start === end) return this;
5191
- if (start < 0 || end > this.original.length) throw new Error("Character is out of bounds");
5192
- if (start > end) throw new Error("end must be greater than start");
5653
+ if (start < 0 || end > this.original.length) throw new MagicStringError(`range ${start}–${end} is out of bounds`);
5654
+ if (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);
5193
5655
  this._split(start);
5194
5656
  this._split(end);
5195
- let chunk = this.byStart[start];
5657
+ let chunk = this.byStart.get(start);
5196
5658
  while (chunk) {
5197
5659
  chunk.reset();
5198
- chunk = end > chunk.end ? this.byStart[chunk.end] : null;
5660
+ chunk = end > chunk.end ? this.byStart.get(chunk.end) : null;
5199
5661
  }
5200
5662
  return this;
5201
5663
  }
5202
5664
  lastChar() {
5203
5665
  if (this.outro.length) return this.outro[this.outro.length - 1];
5204
5666
  let chunk = this.lastChunk;
5205
- do {
5667
+ while (chunk) {
5206
5668
  if (chunk.outro.length) return chunk.outro[chunk.outro.length - 1];
5207
5669
  if (chunk.content.length) return chunk.content[chunk.content.length - 1];
5208
5670
  if (chunk.intro.length) return chunk.intro[chunk.intro.length - 1];
5209
- } while (chunk = chunk.previous);
5671
+ chunk = chunk.previous;
5672
+ }
5210
5673
  if (this.intro.length) return this.intro[this.intro.length - 1];
5211
5674
  return "";
5212
5675
  }
@@ -5215,7 +5678,7 @@ var MagicString = class MagicString {
5215
5678
  if (lineIndex !== -1) return this.outro.substr(lineIndex + 1);
5216
5679
  let lineStr = this.outro;
5217
5680
  let chunk = this.lastChunk;
5218
- do {
5681
+ while (chunk) {
5219
5682
  if (chunk.outro.length > 0) {
5220
5683
  lineIndex = chunk.outro.lastIndexOf(n);
5221
5684
  if (lineIndex !== -1) return chunk.outro.substr(lineIndex + 1) + lineStr;
@@ -5231,11 +5694,16 @@ var MagicString = class MagicString {
5231
5694
  if (lineIndex !== -1) return chunk.intro.substr(lineIndex + 1) + lineStr;
5232
5695
  lineStr = chunk.intro + lineStr;
5233
5696
  }
5234
- } while (chunk = chunk.previous);
5697
+ chunk = chunk.previous;
5698
+ }
5235
5699
  lineIndex = this.intro.lastIndexOf(n);
5236
5700
  if (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr;
5237
5701
  return this.intro + lineStr;
5238
5702
  }
5703
+ /**
5704
+ * Returns the content of the generated string that corresponds to the slice between `start` and `end` of the original string.
5705
+ * Throws error if the indices are for characters that were already removed.
5706
+ */
5239
5707
  slice(start = 0, end = this.original.length - this.offset) {
5240
5708
  start = start + this.offset;
5241
5709
  end = end + this.offset;
@@ -5249,12 +5717,12 @@ var MagicString = class MagicString {
5249
5717
  if (chunk.start < end && chunk.end >= end) return result;
5250
5718
  chunk = chunk.next;
5251
5719
  }
5252
- if (chunk && chunk.edited && chunk.start !== start) throw new Error(`Cannot use replaced character ${start} as slice start anchor.`);
5720
+ if (chunk && chunk.edited && chunk.start !== start) throw new MagicStringError(`cannot use edited character ${start} as slice start anchor`);
5253
5721
  const startChunk = chunk;
5254
5722
  while (chunk) {
5255
5723
  if (chunk.intro && (startChunk !== chunk || chunk.start === start)) result += chunk.intro;
5256
5724
  const containsEnd = chunk.start < end && chunk.end >= end;
5257
- if (containsEnd && chunk.edited && chunk.end !== end) throw new Error(`Cannot use replaced character ${end} as slice end anchor.`);
5725
+ if (containsEnd && chunk.edited && chunk.end !== end) throw new MagicStringError(`cannot use edited character ${end} as slice end anchor`);
5258
5726
  const sliceStart = startChunk === chunk ? start - chunk.start : 0;
5259
5727
  const sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;
5260
5728
  result += chunk.content.slice(sliceStart, sliceEnd);
@@ -5264,37 +5732,45 @@ var MagicString = class MagicString {
5264
5732
  }
5265
5733
  return result;
5266
5734
  }
5735
+ /**
5736
+ * Returns a clone of `s`, with all content before the `start` and `end` characters of the original string removed.
5737
+ */
5267
5738
  snip(start, end) {
5268
5739
  const clone = this.clone();
5269
5740
  clone.remove(0, start);
5270
5741
  clone.remove(end, clone.original.length);
5271
5742
  return clone;
5272
5743
  }
5744
+ /** @internal */
5273
5745
  _split(index) {
5274
- if (this.byStart[index] || this.byEnd[index]) return;
5746
+ if (this.byStart.get(index) || this.byEnd.get(index)) return;
5275
5747
  let chunk = this.lastSearchedChunk;
5276
5748
  let previousChunk = chunk;
5277
5749
  const searchForward = index > chunk.end;
5278
5750
  while (chunk) {
5279
5751
  if (chunk.contains(index)) return this._splitChunk(chunk, index);
5280
- chunk = searchForward ? this.byStart[chunk.end] : this.byEnd[chunk.start];
5752
+ chunk = searchForward ? this.byStart.get(chunk.end) : this.byEnd.get(chunk.start);
5281
5753
  if (chunk === previousChunk) return;
5282
5754
  previousChunk = chunk;
5283
5755
  }
5284
5756
  }
5757
+ /** @internal */
5285
5758
  _splitChunk(chunk, index) {
5286
5759
  if (chunk.edited && chunk.content.length) {
5287
5760
  const loc = getLocator(this.original)(index);
5288
- throw new Error(`Cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`);
5761
+ throw new MagicStringError(`cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`);
5289
5762
  }
5290
5763
  const newChunk = chunk.split(index);
5291
- this.byEnd[index] = chunk;
5292
- this.byStart[index] = newChunk;
5293
- this.byEnd[newChunk.end] = newChunk;
5764
+ this.byEnd.set(index, chunk);
5765
+ this.byStart.set(index, newChunk);
5766
+ this.byEnd.set(newChunk.end, newChunk);
5294
5767
  if (chunk === this.lastChunk) this.lastChunk = newChunk;
5295
5768
  this.lastSearchedChunk = chunk;
5296
5769
  return true;
5297
5770
  }
5771
+ /**
5772
+ * Returns the generated string.
5773
+ */
5298
5774
  toString() {
5299
5775
  let str = this.intro;
5300
5776
  let chunk = this.firstChunk;
@@ -5304,29 +5780,41 @@ var MagicString = class MagicString {
5304
5780
  }
5305
5781
  return str + this.outro;
5306
5782
  }
5783
+ /**
5784
+ * Returns true if the resulting source is empty (disregarding white space).
5785
+ */
5307
5786
  isEmpty() {
5308
5787
  let chunk = this.firstChunk;
5309
- do
5788
+ while (chunk) {
5310
5789
  if (chunk.intro.length && chunk.intro.trim() || chunk.content.length && chunk.content.trim() || chunk.outro.length && chunk.outro.trim()) return false;
5311
- while (chunk = chunk.next);
5790
+ chunk = chunk.next;
5791
+ }
5312
5792
  return true;
5313
5793
  }
5314
5794
  length() {
5315
5795
  let chunk = this.firstChunk;
5316
5796
  let length = 0;
5317
- do
5797
+ while (chunk) {
5318
5798
  length += chunk.intro.length + chunk.content.length + chunk.outro.length;
5319
- while (chunk = chunk.next);
5799
+ chunk = chunk.next;
5800
+ }
5320
5801
  return length;
5321
5802
  }
5803
+ /**
5804
+ * Removes empty lines from the start and end.
5805
+ */
5322
5806
  trimLines() {
5323
5807
  return this.trim("[\\r\\n]");
5324
5808
  }
5809
+ /**
5810
+ * Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the start and end.
5811
+ */
5325
5812
  trim(charType) {
5326
5813
  return this.trimStart(charType).trimEnd(charType);
5327
5814
  }
5815
+ /** @internal */
5328
5816
  trimEndAborted(charType) {
5329
- const rx = new RegExp((charType || "\\s") + "+$");
5817
+ const rx = new RegExp(`${charType || "\\s"}+$`);
5330
5818
  this.outro = this.outro.replace(rx, "");
5331
5819
  if (this.outro.length) return true;
5332
5820
  let chunk = this.lastChunk;
@@ -5335,21 +5823,25 @@ var MagicString = class MagicString {
5335
5823
  const aborted = chunk.trimEnd(rx);
5336
5824
  if (chunk.end !== end) {
5337
5825
  if (this.lastChunk === chunk) this.lastChunk = chunk.next;
5338
- this.byEnd[chunk.end] = chunk;
5339
- this.byStart[chunk.next.start] = chunk.next;
5340
- this.byEnd[chunk.next.end] = chunk.next;
5826
+ this.byEnd.set(chunk.end, chunk);
5827
+ this.byStart.set(chunk.next.start, chunk.next);
5828
+ this.byEnd.set(chunk.next.end, chunk.next);
5341
5829
  }
5342
5830
  if (aborted) return true;
5343
5831
  chunk = chunk.previous;
5344
5832
  } while (chunk);
5345
5833
  return false;
5346
5834
  }
5835
+ /**
5836
+ * Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the end.
5837
+ */
5347
5838
  trimEnd(charType) {
5348
5839
  this.trimEndAborted(charType);
5349
5840
  return this;
5350
5841
  }
5842
+ /** @internal */
5351
5843
  trimStartAborted(charType) {
5352
- const rx = new RegExp("^" + (charType || "\\s") + "+");
5844
+ const rx = new RegExp(`^${charType || "\\s"}+`);
5353
5845
  this.intro = this.intro.replace(rx, "");
5354
5846
  if (this.intro.length) return true;
5355
5847
  let chunk = this.firstChunk;
@@ -5358,22 +5850,29 @@ var MagicString = class MagicString {
5358
5850
  const aborted = chunk.trimStart(rx);
5359
5851
  if (chunk.end !== end) {
5360
5852
  if (chunk === this.lastChunk) this.lastChunk = chunk.next;
5361
- this.byEnd[chunk.end] = chunk;
5362
- this.byStart[chunk.next.start] = chunk.next;
5363
- this.byEnd[chunk.next.end] = chunk.next;
5853
+ this.byEnd.set(chunk.end, chunk);
5854
+ this.byStart.set(chunk.next.start, chunk.next);
5855
+ this.byEnd.set(chunk.next.end, chunk.next);
5364
5856
  }
5365
5857
  if (aborted) return true;
5366
5858
  chunk = chunk.next;
5367
5859
  } while (chunk);
5368
5860
  return false;
5369
5861
  }
5862
+ /**
5863
+ * Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the start.
5864
+ */
5370
5865
  trimStart(charType) {
5371
5866
  this.trimStartAborted(charType);
5372
5867
  return this;
5373
5868
  }
5869
+ /**
5870
+ * Indicates if the string has been changed.
5871
+ */
5374
5872
  hasChanged() {
5375
5873
  return this.original !== this.toString();
5376
5874
  }
5875
+ /** @internal */
5377
5876
  _replaceRegexp(searchValue, replacement) {
5378
5877
  function getReplacement(match, str) {
5379
5878
  if (typeof replacement === "string") return replacement.replace(/\$(\$|&|\d+)/g, (_, i) => {
@@ -5382,12 +5881,15 @@ var MagicString = class MagicString {
5382
5881
  if (+i < match.length) return match[+i];
5383
5882
  return `$${i}`;
5384
5883
  });
5385
- else return replacement(...match, match.index, str, match.groups);
5884
+ else return replacement(match[0], ...match.slice(1), match.index, str, match.groups);
5386
5885
  }
5387
5886
  function matchAll(re, str) {
5388
- let match;
5389
5887
  const matches = [];
5390
- while (match = re.exec(str)) matches.push(match);
5888
+ while (true) {
5889
+ const match = re.exec(str);
5890
+ if (!match) break;
5891
+ matches.push(match);
5892
+ }
5391
5893
  return matches;
5392
5894
  }
5393
5895
  if (searchValue.global) matchAll(searchValue, this.original).forEach((match) => {
@@ -5405,6 +5907,7 @@ var MagicString = class MagicString {
5405
5907
  }
5406
5908
  return this;
5407
5909
  }
5910
+ /** @internal */
5408
5911
  _replaceString(string, replacement) {
5409
5912
  const { original } = this;
5410
5913
  const index = original.indexOf(string);
@@ -5414,24 +5917,30 @@ var MagicString = class MagicString {
5414
5917
  }
5415
5918
  return this;
5416
5919
  }
5920
+ /**
5921
+ * String replacement with RegExp or string.
5922
+ */
5417
5923
  replace(searchValue, replacement) {
5418
5924
  if (typeof searchValue === "string") return this._replaceString(searchValue, replacement);
5419
5925
  return this._replaceRegexp(searchValue, replacement);
5420
5926
  }
5927
+ /** @internal */
5421
5928
  _replaceAllString(string, replacement) {
5422
5929
  const { original } = this;
5423
5930
  const stringLength = string.length;
5424
5931
  for (let index = original.indexOf(string); index !== -1; index = original.indexOf(string, index + stringLength)) {
5425
5932
  const previous = original.slice(index, index + stringLength);
5426
- let _replacement = replacement;
5427
- if (typeof replacement === "function") _replacement = replacement(previous, index, original);
5933
+ const _replacement = typeof replacement === "function" ? replacement(previous, index, original) : replacement;
5428
5934
  if (previous !== _replacement) this.overwrite(index, index + stringLength, _replacement);
5429
5935
  }
5430
5936
  return this;
5431
5937
  }
5938
+ /**
5939
+ * Same as `s.replace`, but replace all matched strings instead of just one.
5940
+ */
5432
5941
  replaceAll(searchValue, replacement) {
5433
5942
  if (typeof searchValue === "string") return this._replaceAllString(searchValue, replacement);
5434
- if (!searchValue.global) throw new TypeError("MagicString.prototype.replaceAll called with a non-global RegExp argument");
5943
+ if (!searchValue.global) throw new MagicStringError("replaceAll() requires a global RegExp");
5435
5944
  return this._replaceRegexp(searchValue, replacement);
5436
5945
  }
5437
5946
  };
@@ -5832,6 +6341,7 @@ function timberFonts(ctx) {
5832
6341
  if (pipeline.cssIdMap.matches(id)) {
5833
6342
  const importer = pipeline.cssIdMap.importerFor(id);
5834
6343
  if (!importer) return "";
6344
+ if (process.env.TIMBER_ANALYZE === "1") return "";
5835
6345
  const skipFonts = process.env.TIMBER_SKIP_FONTS === "1";
5836
6346
  for (const font of pipeline.googleFonts()) {
5837
6347
  if (font.importer !== importer) continue;
@@ -7339,8 +7849,10 @@ function lookupFacades(id, sharedModuleFacades) {
7339
7849
  if (!isBareSpecifier(id)) return void 0;
7340
7850
  const needle = `/node_modules/${id}/`;
7341
7851
  let merged;
7342
- for (const [key, facades] of sharedModuleFacades) if (key.includes(needle)) if (!merged) merged = [...facades];
7343
- else merged.push(...facades);
7852
+ for (const [key, facades] of sharedModuleFacades) if (key.includes(needle)) {
7853
+ if (!merged) merged = [...facades];
7854
+ else merged.push(...facades);
7855
+ }
7344
7856
  return merged;
7345
7857
  }
7346
7858
  /**
@@ -7415,6 +7927,7 @@ function clientChunkGroup(meta, appDir, root, sharedModuleFacades) {
7415
7927
  *
7416
7928
  * Design docs: design/11-platform.md, design/25-production-deployments.md
7417
7929
  */
7930
+ var POISON_MARKER_SPECIFIERS = EXPLICIT_MARKERS.map((m) => m.specifier);
7418
7931
  var NODE_BUILTINS = builtinModules.flatMap((m) => [m, `node:${m}`]);
7419
7932
  var CLOUDFLARE_BUILTINS = [
7420
7933
  "cloudflare:workers",
@@ -7439,12 +7952,8 @@ function timberServerBundle() {
7439
7952
  name: "timber-server-bundle",
7440
7953
  config(_cfg, { command }) {
7441
7954
  if (command === "serve") return { environments: {
7442
- rsc: { resolve: { noExternal: ["server-only", "client-only"] } },
7443
- ssr: { resolve: { noExternal: [
7444
- "server-only",
7445
- "client-only",
7446
- "nuqs"
7447
- ] } }
7955
+ rsc: { resolve: { noExternal: [...POISON_MARKER_SPECIFIERS] } },
7956
+ ssr: { resolve: { noExternal: [...POISON_MARKER_SPECIFIERS, "nuqs"] } }
7448
7957
  } };
7449
7958
  const serverDefine = { "process.env.NODE_ENV": JSON.stringify("production") };
7450
7959
  return {
@@ -7572,9 +8081,7 @@ function collectPatternNames(node, out) {
7572
8081
  for (const prop of node.properties ?? []) if (prop.type === "RestElement") collectPatternNames(prop, out);
7573
8082
  else collectPatternNames(prop.value, out);
7574
8083
  break;
7575
- case "TSParameterProperty":
7576
- if (node.parameter) collectPatternNames(node.parameter, out);
7577
- break;
8084
+ case "TSParameterProperty": if (node.parameter) collectPatternNames(node.parameter, out);
7578
8085
  }
7579
8086
  }
7580
8087
  /** Return the intersection of param names with `tracked`, or null if none. */
@@ -7946,7 +8453,8 @@ function timberCacheTransform(ctx) {
7946
8453
  }
7947
8454
  if (callSites.length === 0) return;
7948
8455
  callSites.sort((a, b) => a.call.start - b.call.start);
7949
- const relPath = relative(ctx.root || process.cwd(), id);
8456
+ const root = ctx.root || process.cwd();
8457
+ const relPath = relative(root, id);
7950
8458
  const s = new MagicString(code);
7951
8459
  const occurrences = /* @__PURE__ */ new Map();
7952
8460
  for (const { call, stmt } of callSites) {
@@ -8271,9 +8779,7 @@ function analyzeModule(program) {
8271
8779
  case "ExportAllDeclaration":
8272
8780
  collectExportAll(stmt, facts);
8273
8781
  break;
8274
- case "ExportDefaultDeclaration":
8275
- collectExportDefault(stmt, facts);
8276
- break;
8782
+ case "ExportDefaultDeclaration": collectExportDefault(stmt, facts);
8277
8783
  }
8278
8784
  walk(program, facts);
8279
8785
  return facts;
@@ -9354,7 +9860,8 @@ function timberPrebuilt(ctx) {
9354
9860
  if (bindings.named.size === 0 && bindings.namespaces.size === 0) return;
9355
9861
  const callSites = collectModuleScopeSites(program, bindings);
9356
9862
  if (callSites.length === 0) return;
9357
- const relPath = relative(ctx.root || process.cwd(), id);
9863
+ const root = ctx.root || process.cwd();
9864
+ const relPath = relative(root, id);
9358
9865
  const s = new MagicString(code);
9359
9866
  const occurrences = /* @__PURE__ */ new Map();
9360
9867
  const wrapperName = ctx.dev ? "__prebuiltDev" : "__prebuilt";
@@ -9514,27 +10021,24 @@ function timberPrebuilt(ctx) {
9514
10021
  * `export const prerender` to descendant pages via most-specific-wins:
9515
10022
  * walk the segment tree from leaf to root, first explicit value wins.
9516
10023
  *
9517
- * A layout that declares `export const prerender` is ALSO wrapped — the
9518
- * layout's flight payload is its own static shell (`children` is a
9519
- * separate component boundary), so caching it is natural (nav, sidebar,
9520
- * footer benefit from build-time rendering). See design/45 §Layout
9521
- * Propagation.
10024
+ * Layout declarations are propagation policy only. Layouts receive the real
10025
+ * descendant React element as `children` to preserve the server-layout
10026
+ * containment boundary, so their props are not cache-keyable and the layout
10027
+ * itself must not be registered for capture.
9522
10028
  *
9523
10029
  * This transform runs BEFORE timber-prebuilt so the generated
9524
10030
  * `cache.component(...)` call is picked up by the callsite rewrite.
9525
10031
  */
9526
10032
  /**
9527
10033
  * Walk the segment tree and resolve the effective prerender value for
9528
- * every page and layout. Returns a map from file path to resolved value.
10034
+ * every page. Returns a map from page file path to resolved value.
9529
10035
  *
9530
10036
  * **Pages:** walk from leaf toward root; first explicit `export const prerender`
9531
10037
  * wins (page > nearest layout > ... > root layout). If none, dynamic.
9532
10038
  *
9533
- * **Layouts:** a layout that declares `export const prerender` is wrapped
9534
- * directly (its own shell is a separate component boundary from `children`).
9535
- * Layouts without their own declaration are NOT wrapped — they don't
9536
- * inherit from ancestors, because wrapping a layout's shell without the
9537
- * author's explicit opt-in would cache content they may expect to be dynamic.
10039
+ * **Layouts:** declarations propagate to descendant pages but layouts are not
10040
+ * included in the result. Their real React-element `children` preserve secure
10041
+ * containment and deliberately make child-independent layout caching invalid.
9538
10042
  */
9539
10043
  function resolvePagePrerender(root) {
9540
10044
  const result = /* @__PURE__ */ new Map();
@@ -9542,7 +10046,6 @@ function resolvePagePrerender(root) {
9542
10046
  if (node.segmentType === "intercepting" || node.segmentType === "private") return;
9543
10047
  const layoutValue = node.layout ? getPrerenderExport(node.layout.filePath) : void 0;
9544
10048
  const stack = layoutValue !== void 0 ? [layoutValue, ...ancestorStack] : ancestorStack;
9545
- if (node.layout && layoutValue !== void 0 && layoutValue !== false) result.set(node.layout.filePath, layoutValue);
9546
10049
  if (node.page) {
9547
10050
  const pageValue = getPrerenderExport(node.page.filePath);
9548
10051
  const resolved = pageValue !== void 0 ? pageValue : stack[0];
@@ -10625,7 +11128,8 @@ function timber(config) {
10625
11128
  }
10626
11129
  let resolvedDevPort = null;
10627
11130
  let resolvedDevPortExplicit = false;
10628
- if (command === "serve" && !isPreview) {
11131
+ const isMiddlewareMode = Boolean(userConfig.server?.middlewareMode);
11132
+ if (command === "serve" && !isPreview && !isMiddlewareMode) {
10629
11133
  ctx.holdingServer = createHoldingServer();
10630
11134
  const holdingRef = ctx.holdingServer;
10631
11135
  const result = await startDevServerPort({
@@ -10706,7 +11210,6 @@ function timber(config) {
10706
11210
  ctx.buildDir = resolve(resolved.root, resolved.build.outDir);
10707
11211
  if (!ctx.dev) ctx.timer = createNoopTimer();
10708
11212
  else ctx.timer.start("dev-server-setup");
10709
- const { validateConfig, formatConfigErrors, checkPeerDependencies, formatMissingPeers } = (init_config_validation(), __toCommonJS(config_validation_exports));
10710
11213
  const configErrors = validateConfig(ctx.config);
10711
11214
  if (configErrors.length > 0) process.stderr.write(`${formatConfigErrors(configErrors)}\n\n`);
10712
11215
  const peerWarning = formatMissingPeers(checkPeerDependencies(ctx.root));