devflare 1.0.0-next.16 → 1.0.0-next.18

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 (982) hide show
  1. package/LLM.md +688 -229
  2. package/README.md +70 -8
  3. package/bin/devflare.js +1 -1
  4. package/dist/{account-fw8nafav.js → account-0evqkmnc.js} +8 -8
  5. package/dist/{account-0w8wdzjv.js → account-0v11zbzk.js} +9 -9
  6. package/dist/{account-eygq6qx7.js → account-2w85efas.js} +9 -9
  7. package/dist/{account-pzq69nys.js → account-61gw9s7t.js} +9 -9
  8. package/dist/account-65sk9q34.js +475 -0
  9. package/dist/account-77vx7q2f.js +475 -0
  10. package/dist/account-7z38mgqf.js +475 -0
  11. package/dist/account-8wgprpbt.js +475 -0
  12. package/dist/account-9gt3tej1.js +475 -0
  13. package/dist/account-dtndtbad.js +475 -0
  14. package/dist/account-e95v7f4s.js +475 -0
  15. package/dist/account-fbyyptg7.js +475 -0
  16. package/dist/account-gnzhz1c9.js +475 -0
  17. package/dist/account-m6jq6fnp.js +475 -0
  18. package/dist/account-mvnfagh9.js +475 -0
  19. package/dist/account-p0crq2gh.js +475 -0
  20. package/dist/account-qkcevx7a.js +475 -0
  21. package/dist/account-txwqg1rx.js +475 -0
  22. package/dist/account-w5n5bjh2.js +475 -0
  23. package/dist/account-zd61t0ey.js +475 -0
  24. package/dist/api-11gkk043.js +33 -0
  25. package/dist/api-2n6dd2ws.js +33 -0
  26. package/dist/api-dbxvch9h.js +33 -0
  27. package/dist/api-p9hf69kr.js +33 -0
  28. package/dist/api-r10j00ev.js +33 -0
  29. package/dist/api-senf2569.js +33 -0
  30. package/dist/api-swcgnp72.js +33 -0
  31. package/dist/{api-d6ekexs5.js → api-th82mps4.js} +3 -1
  32. package/dist/bridge/client.d.ts +29 -6
  33. package/dist/bridge/client.d.ts.map +1 -1
  34. package/dist/bridge/gateway-runtime.d.ts +8 -0
  35. package/dist/bridge/gateway-runtime.d.ts.map +1 -0
  36. package/dist/bridge/index.d.ts +2 -2
  37. package/dist/bridge/index.d.ts.map +1 -1
  38. package/dist/bridge/log.d.ts +5 -0
  39. package/dist/bridge/log.d.ts.map +1 -0
  40. package/dist/bridge/miniflare.d.ts.map +1 -1
  41. package/dist/bridge/proxy.d.ts +7 -5
  42. package/dist/bridge/proxy.d.ts.map +1 -1
  43. package/dist/bridge/serialization.d.ts +36 -16
  44. package/dist/bridge/serialization.d.ts.map +1 -1
  45. package/dist/bridge/server.d.ts +1 -0
  46. package/dist/bridge/server.d.ts.map +1 -1
  47. package/dist/bridge/v2/body-streams.d.ts +53 -0
  48. package/dist/bridge/v2/body-streams.d.ts.map +1 -0
  49. package/dist/bridge/v2/codec.d.ts +106 -0
  50. package/dist/bridge/v2/codec.d.ts.map +1 -0
  51. package/dist/bridge/v2/control-messages.d.ts +51 -0
  52. package/dist/bridge/v2/control-messages.d.ts.map +1 -0
  53. package/dist/bridge/v2/frames.d.ts +109 -0
  54. package/dist/bridge/v2/frames.d.ts.map +1 -0
  55. package/dist/bridge/v2/index.d.ts +11 -0
  56. package/dist/bridge/v2/index.d.ts.map +1 -0
  57. package/dist/bridge/v2/legacy-protocol.d.ts +146 -0
  58. package/dist/bridge/v2/legacy-protocol.d.ts.map +1 -0
  59. package/dist/bridge/v2/legacy-serialization.d.ts +103 -0
  60. package/dist/bridge/v2/legacy-serialization.d.ts.map +1 -0
  61. package/dist/bridge/v2/serialization.d.ts +48 -0
  62. package/dist/bridge/v2/serialization.d.ts.map +1 -0
  63. package/dist/bridge/v2/transport.d.ts +31 -0
  64. package/dist/bridge/v2/transport.d.ts.map +1 -0
  65. package/dist/bridge/v2/value-codec.d.ts +61 -0
  66. package/dist/bridge/v2/value-codec.d.ts.map +1 -0
  67. package/dist/bridge/v2/value-serialization.d.ts +103 -0
  68. package/dist/bridge/v2/value-serialization.d.ts.map +1 -0
  69. package/dist/bridge/v2/wire.d.ts +170 -0
  70. package/dist/bridge/v2/wire.d.ts.map +1 -0
  71. package/dist/bridge/v2/ws-relay.d.ts +53 -0
  72. package/dist/bridge/v2/ws-relay.d.ts.map +1 -0
  73. package/dist/browser-shim/server.d.ts +63 -0
  74. package/dist/browser-shim/server.d.ts.map +1 -1
  75. package/dist/browser.d.ts +396 -38
  76. package/dist/browser.d.ts.map +1 -1
  77. package/dist/{src/browser.js → browser.js} +19 -33
  78. package/dist/build-07mjrvsn.js +53 -0
  79. package/dist/build-0rfr8k1s.js +53 -0
  80. package/dist/build-1313sg73.js +52 -0
  81. package/dist/build-1hnntbks.js +53 -0
  82. package/dist/build-1r3myv0k.js +53 -0
  83. package/dist/build-28561w5v.js +54 -0
  84. package/dist/build-50yqpwb3.js +54 -0
  85. package/dist/build-55z8psd6.js +53 -0
  86. package/dist/build-5b9wj2p0.js +53 -0
  87. package/dist/build-5frhzh1m.js +53 -0
  88. package/dist/{build-p3r3117t.js → build-6ye9vnab.js} +8 -9
  89. package/dist/build-8gv18jrq.js +52 -0
  90. package/dist/build-9bgqypy6.js +53 -0
  91. package/dist/{build-506kjhcm.js → build-9em4ymqn.js} +12 -13
  92. package/dist/build-eh3x12qc.js +52 -0
  93. package/dist/build-emhyycp7.js +53 -0
  94. package/dist/build-f1m9jn7b.js +53 -0
  95. package/dist/build-ffe72jjv.js +54 -0
  96. package/dist/build-fx90y6za.js +53 -0
  97. package/dist/build-h31egsze.js +53 -0
  98. package/dist/build-hpczwagb.js +53 -0
  99. package/dist/{build-1kmkwqgh.js → build-hpkbanpw.js} +16 -15
  100. package/dist/build-j2re91xe.js +54 -0
  101. package/dist/{build-66866ahs.js → build-j78389rg.js} +12 -13
  102. package/dist/build-m3kckn5g.js +53 -0
  103. package/dist/build-mf3thcjm.js +53 -0
  104. package/dist/build-n3n5bv37.js +52 -0
  105. package/dist/build-ngfy4v5x.js +53 -0
  106. package/dist/build-pr843h0d.js +52 -0
  107. package/dist/build-qyg2b45p.js +52 -0
  108. package/dist/build-r6884kyt.js +53 -0
  109. package/dist/build-re370wkf.js +53 -0
  110. package/dist/build-vvndgwg0.js +52 -0
  111. package/dist/build-wp559jkf.js +54 -0
  112. package/dist/{build-g1adm3ww.js → build-x4r67275.js} +12 -13
  113. package/dist/build-xp4pfhvv.js +52 -0
  114. package/dist/build-y489r2h9.js +54 -0
  115. package/dist/build-y6g4bvx5.js +52 -0
  116. package/dist/build-yvn0yhwx.js +52 -0
  117. package/dist/build-z4vmhs5c.js +53 -0
  118. package/dist/bundler/defaults.d.ts +23 -0
  119. package/dist/bundler/defaults.d.ts.map +1 -0
  120. package/dist/bundler/do-bundler.d.ts.map +1 -1
  121. package/dist/bundler/index.d.ts +1 -0
  122. package/dist/bundler/index.d.ts.map +1 -1
  123. package/dist/bundler/rolldown-shared.d.ts +29 -0
  124. package/dist/bundler/rolldown-shared.d.ts.map +1 -1
  125. package/dist/bundler/worker-bundler.d.ts.map +1 -1
  126. package/dist/bundler/worker-compat.d.ts.map +1 -1
  127. package/dist/cli/build-manifest.d.ts +54 -0
  128. package/dist/cli/build-manifest.d.ts.map +1 -0
  129. package/dist/cli/commands/build-artifacts.d.ts +13 -0
  130. package/dist/cli/commands/build-artifacts.d.ts.map +1 -1
  131. package/dist/cli/commands/deploy.d.ts.map +1 -1
  132. package/dist/cli/dependencies.d.ts +1 -0
  133. package/dist/cli/dependencies.d.ts.map +1 -1
  134. package/dist/cli/deploy-strategy.d.ts +3 -3
  135. package/dist/cli/deploy-strategy.d.ts.map +1 -1
  136. package/dist/cli/help-pages/pages/core.d.ts.map +1 -1
  137. package/dist/cli/index.js +12 -0
  138. package/dist/cli/preview-bindings.d.ts +8 -1
  139. package/dist/cli/preview-bindings.d.ts.map +1 -1
  140. package/dist/cli/preview.d.ts +1 -2
  141. package/dist/cli/preview.d.ts.map +1 -1
  142. package/dist/cloudflare/account-resources.d.ts.map +1 -1
  143. package/dist/cloudflare/api.d.ts +67 -3
  144. package/dist/cloudflare/api.d.ts.map +1 -1
  145. package/dist/cloudflare/auth.d.ts.map +1 -1
  146. package/dist/{src/cloudflare → cloudflare}/index.js +7 -7
  147. package/dist/cloudflare/known-permission-group-ids.generated.d.ts +10 -0
  148. package/dist/cloudflare/known-permission-group-ids.generated.d.ts.map +1 -0
  149. package/dist/cloudflare/kv-namespace.d.ts +2 -1
  150. package/dist/cloudflare/kv-namespace.d.ts.map +1 -1
  151. package/dist/cloudflare/preferences.d.ts +7 -0
  152. package/dist/cloudflare/preferences.d.ts.map +1 -1
  153. package/dist/cloudflare/preview-registry-inference.d.ts +14 -0
  154. package/dist/cloudflare/preview-registry-inference.d.ts.map +1 -0
  155. package/dist/cloudflare/preview-registry-records.d.ts +3 -60
  156. package/dist/cloudflare/preview-registry-records.d.ts.map +1 -1
  157. package/dist/cloudflare/preview-registry-shape.d.ts +47 -0
  158. package/dist/cloudflare/preview-registry-shape.d.ts.map +1 -0
  159. package/dist/cloudflare/preview-registry-transport.d.ts +4 -0
  160. package/dist/cloudflare/preview-registry-transport.d.ts.map +1 -0
  161. package/dist/cloudflare/preview-urls.d.ts +3 -0
  162. package/dist/cloudflare/preview-urls.d.ts.map +1 -0
  163. package/dist/cloudflare/tokens.d.ts +23 -0
  164. package/dist/cloudflare/tokens.d.ts.map +1 -1
  165. package/dist/cloudflare/types.d.ts +1 -1
  166. package/dist/cloudflare/types.d.ts.map +1 -1
  167. package/dist/cloudflare/usage.d.ts +30 -2
  168. package/dist/cloudflare/usage.d.ts.map +1 -1
  169. package/dist/config/binding-resolution-helpers.d.ts +36 -0
  170. package/dist/config/binding-resolution-helpers.d.ts.map +1 -0
  171. package/dist/config/compatibility.d.ts +3 -0
  172. package/dist/config/compatibility.d.ts.map +1 -0
  173. package/dist/config/compiler.d.ts +61 -20
  174. package/dist/config/compiler.d.ts.map +1 -1
  175. package/dist/config/deploy-resources.d.ts +58 -0
  176. package/dist/config/deploy-resources.d.ts.map +1 -0
  177. package/dist/config/index.d.ts +5 -2
  178. package/dist/config/index.d.ts.map +1 -1
  179. package/dist/config/preview-resources.d.ts +6 -0
  180. package/dist/config/preview-resources.d.ts.map +1 -1
  181. package/dist/config/preview.d.ts.map +1 -1
  182. package/dist/config/ref.d.ts +14 -1
  183. package/dist/config/ref.d.ts.map +1 -1
  184. package/dist/config/resolve-phased.d.ts +72 -0
  185. package/dist/config/resolve-phased.d.ts.map +1 -0
  186. package/dist/config/resolve.d.ts +7 -0
  187. package/dist/config/resolve.d.ts.map +1 -1
  188. package/dist/config/resource-resolution.d.ts +26 -6
  189. package/dist/config/resource-resolution.d.ts.map +1 -1
  190. package/dist/config/schema-bindings.d.ts +262 -0
  191. package/dist/config/schema-bindings.d.ts.map +1 -1
  192. package/dist/config/schema-env.d.ts +375 -39
  193. package/dist/config/schema-env.d.ts.map +1 -1
  194. package/dist/config/schema-normalization.d.ts +26 -2
  195. package/dist/config/schema-normalization.d.ts.map +1 -1
  196. package/dist/config/schema.d.ts +994 -63
  197. package/dist/config/schema.d.ts.map +1 -1
  198. package/dist/config/service-bindings-validation.d.ts +36 -0
  199. package/dist/config/service-bindings-validation.d.ts.map +1 -0
  200. package/dist/{config-hwdqjse7.js → config-1japnjmx.js} +5 -5
  201. package/dist/{config-q0g5qdga.js → config-287wjn1m.js} +6 -6
  202. package/dist/{config-fjwke42y.js → config-4x6vq82e.js} +6 -6
  203. package/dist/{config-pxvewrhv.js → config-5n0avhcx.js} +6 -6
  204. package/dist/config-70s2ap5j.js +59 -0
  205. package/dist/config-7hge8ze6.js +59 -0
  206. package/dist/config-7rbp7aek.js +59 -0
  207. package/dist/config-b8xbbmta.js +59 -0
  208. package/dist/config-baee5690.js +59 -0
  209. package/dist/config-bczpc1ey.js +59 -0
  210. package/dist/{src/config-entry.js → config-entry.js} +3 -3
  211. package/dist/config-fhmwzaw6.js +59 -0
  212. package/dist/config-g9vkfa4x.js +59 -0
  213. package/dist/config-gpexkzth.js +59 -0
  214. package/dist/config-nspw7sgv.js +59 -0
  215. package/dist/config-ntm4x9wt.js +59 -0
  216. package/dist/config-nv6hfpg6.js +59 -0
  217. package/dist/config-pjc33wew.js +59 -0
  218. package/dist/config-pnz2e8s3.js +59 -0
  219. package/dist/config-qts6nh6g.js +59 -0
  220. package/dist/config-sg2xrdt4.js +59 -0
  221. package/dist/config-vzwckat3.js +59 -0
  222. package/dist/config-x90dkmm7.js +59 -0
  223. package/dist/{src/decorators → decorators}/index.js +2 -2
  224. package/dist/deploy-1s6nv5rp.js +921 -0
  225. package/dist/{deploy-ykpcjkc2.js → deploy-30ph1rrd.js} +263 -32
  226. package/dist/{deploy-ex4g5avz.js → deploy-39dmfn9d.js} +338 -38
  227. package/dist/deploy-44n2pshy.js +1016 -0
  228. package/dist/deploy-45qxpsfe.js +921 -0
  229. package/dist/deploy-64e57w1g.js +1040 -0
  230. package/dist/deploy-82j43vta.js +1040 -0
  231. package/dist/deploy-99m8qhpa.js +1041 -0
  232. package/dist/deploy-9twkd32f.js +1040 -0
  233. package/dist/deploy-a2eq2c1n.js +1040 -0
  234. package/dist/{deploy-csfhdr64.js → deploy-a3pb1qs5.js} +259 -29
  235. package/dist/deploy-agbtfm04.js +921 -0
  236. package/dist/{deploy-jnb0bhka.js → deploy-aswbtbf3.js} +361 -49
  237. package/dist/deploy-bqf3kxy5.js +972 -0
  238. package/dist/deploy-fv4z648h.js +921 -0
  239. package/dist/deploy-gsybda2f.js +1038 -0
  240. package/dist/deploy-h17nzysm.js +921 -0
  241. package/dist/deploy-hc89h4wg.js +1045 -0
  242. package/dist/deploy-jey5pnqn.js +1040 -0
  243. package/dist/deploy-jv0yfqvk.js +1040 -0
  244. package/dist/deploy-kn3z6spd.js +941 -0
  245. package/dist/deploy-m22xmz9w.js +921 -0
  246. package/dist/deploy-nefp2njy.js +1038 -0
  247. package/dist/deploy-ppp8pg6w.js +1038 -0
  248. package/dist/deploy-qah2eag6.js +1041 -0
  249. package/dist/deploy-qdq2gpad.js +1045 -0
  250. package/dist/deploy-r1yf8913.js +1038 -0
  251. package/dist/deploy-r8nam9rr.js +1038 -0
  252. package/dist/deploy-rrm4a0xw.js +921 -0
  253. package/dist/deploy-s0tfnc12.js +1040 -0
  254. package/dist/deploy-s636ks9k.js +1041 -0
  255. package/dist/deploy-sany8t54.js +1045 -0
  256. package/dist/deploy-skqn61j3.js +1038 -0
  257. package/dist/deploy-smv2870h.js +921 -0
  258. package/dist/deploy-sp16nxs5.js +972 -0
  259. package/dist/deploy-sr805bvq.js +921 -0
  260. package/dist/deploy-t9dehmn0.js +1041 -0
  261. package/dist/deploy-taxt7njz.js +1041 -0
  262. package/dist/deploy-tnfvfh9m.js +1040 -0
  263. package/dist/deploy-w5f8db4s.js +1040 -0
  264. package/dist/deploy-wsxcectr.js +921 -0
  265. package/dist/deploy-xyfbhj3v.js +1038 -0
  266. package/dist/deploy-yv1y5xaa.js +921 -0
  267. package/dist/deploy-z3ejw37k.js +1040 -0
  268. package/dist/{dev-8nssqatr.js → dev-02tgdc4f.js} +199 -448
  269. package/dist/dev-0tqhveye.js +2314 -0
  270. package/dist/dev-3dj2gkfq.js +2314 -0
  271. package/dist/dev-3e0etsww.js +2314 -0
  272. package/dist/dev-47dk7c13.js +2314 -0
  273. package/dist/dev-4a2a31cm.js +2314 -0
  274. package/dist/dev-4w1stcn8.js +2427 -0
  275. package/dist/dev-5wkh1z4a.js +2188 -0
  276. package/dist/dev-6t22zmey.js +2350 -0
  277. package/dist/dev-89p1sdv7.js +2395 -0
  278. package/dist/dev-8d1gxjky.js +2427 -0
  279. package/dist/dev-8yawx3cv.js +2314 -0
  280. package/dist/dev-9h4p8a0c.js +2393 -0
  281. package/dist/dev-9xmttj4c.js +2314 -0
  282. package/dist/dev-at6gy2td.js +2427 -0
  283. package/dist/dev-bkbz97z0.js +2314 -0
  284. package/dist/{dev-grznx8fn.js → dev-ct3344kv.js} +199 -448
  285. package/dist/{dev-7ef5e2j1.js → dev-dg8dh5c1.js} +123 -298
  286. package/dist/dev-dr5jb965.js +2427 -0
  287. package/dist/dev-e4sjqtbq.js +2314 -0
  288. package/dist/dev-ecq26mg4.js +2350 -0
  289. package/dist/dev-ef237vgp.js +2324 -0
  290. package/dist/dev-enbdg4st.js +2314 -0
  291. package/dist/dev-jcrxg8hq.js +2160 -0
  292. package/dist/dev-jk0gqges.js +2432 -0
  293. package/dist/dev-k62936am.js +2314 -0
  294. package/dist/dev-k8ptbvrs.js +2160 -0
  295. package/dist/dev-kqm107h4.js +2422 -0
  296. package/dist/dev-n0gx7eya.js +2350 -0
  297. package/dist/dev-n23m6rtb.js +2314 -0
  298. package/dist/dev-ny8fmkzg.js +2432 -0
  299. package/dist/dev-p1c65cga.js +2386 -0
  300. package/dist/dev-p4fjbb4h.js +2395 -0
  301. package/dist/dev-pnfcv79z.js +2160 -0
  302. package/dist/dev-qnrrv5ey.js +2393 -0
  303. package/dist/dev-qqysg50t.js +2427 -0
  304. package/dist/dev-r9f3n11q.js +2410 -0
  305. package/dist/dev-s0815dw4.js +2427 -0
  306. package/dist/dev-s4tpkg60.js +2314 -0
  307. package/dist/dev-s82fcesg.js +2314 -0
  308. package/dist/dev-s9sz53me.js +2401 -0
  309. package/dist/dev-sdka7z0d.js +2427 -0
  310. package/dist/dev-server/d1-migrations.d.ts +22 -0
  311. package/dist/dev-server/d1-migrations.d.ts.map +1 -1
  312. package/dist/dev-server/dev-server-state.d.ts +56 -0
  313. package/dist/dev-server/dev-server-state.d.ts.map +1 -0
  314. package/dist/dev-server/gateway-script.d.ts +14 -1
  315. package/dist/dev-server/gateway-script.d.ts.map +1 -1
  316. package/dist/dev-server/miniflare-bindings.d.ts +16 -0
  317. package/dist/dev-server/miniflare-bindings.d.ts.map +1 -0
  318. package/dist/dev-server/miniflare-dev-config.d.ts +30 -0
  319. package/dist/dev-server/miniflare-dev-config.d.ts.map +1 -0
  320. package/dist/dev-server/miniflare-worker-config.d.ts +44 -0
  321. package/dist/dev-server/miniflare-worker-config.d.ts.map +1 -0
  322. package/dist/dev-server/reload-queue.d.ts +13 -0
  323. package/dist/dev-server/reload-queue.d.ts.map +1 -0
  324. package/dist/dev-server/server-startup-helpers.d.ts +84 -0
  325. package/dist/dev-server/server-startup-helpers.d.ts.map +1 -0
  326. package/dist/dev-server/server.d.ts.map +1 -1
  327. package/dist/dev-server/vite-utils.d.ts +18 -0
  328. package/dist/dev-server/vite-utils.d.ts.map +1 -1
  329. package/dist/dev-server/worker-source-watcher.d.ts +6 -0
  330. package/dist/dev-server/worker-source-watcher.d.ts.map +1 -1
  331. package/dist/dev-t3tjscah.js +2350 -0
  332. package/dist/dev-t50kdb1j.js +2338 -0
  333. package/dist/dev-t5xf55pt.js +2314 -0
  334. package/dist/dev-t63c44bb.js +2314 -0
  335. package/dist/dev-wg3d38sy.js +2433 -0
  336. package/dist/dev-wh4rfgsh.js +2427 -0
  337. package/dist/{dev-2pd33m28.js → dev-wjh8gdd1.js} +200 -325
  338. package/dist/dev-xzxy9qvq.js +2314 -0
  339. package/dist/dev-yymaq4ph.js +2392 -0
  340. package/dist/dev-zg2w2ve3.js +2422 -0
  341. package/dist/dev-zsb2xk1x.js +2427 -0
  342. package/dist/dev-zty3yhzg.js +2324 -0
  343. package/dist/{doctor-04ammrrh.js → doctor-3mqavqg3.js} +10 -10
  344. package/dist/{doctor-fzkznce1.js → doctor-5nek32fz.js} +10 -10
  345. package/dist/{doctor-sa5xv1bz.js → doctor-7ra1w0sk.js} +10 -10
  346. package/dist/doctor-ak830a0k.js +245 -0
  347. package/dist/doctor-bye3cs8a.js +245 -0
  348. package/dist/{doctor-fmjj65mc.js → doctor-c5m9pmwq.js} +8 -8
  349. package/dist/doctor-cqfkgxvw.js +245 -0
  350. package/dist/doctor-e1h9mhzp.js +245 -0
  351. package/dist/doctor-fmqsrafk.js +245 -0
  352. package/dist/doctor-hgs7wr5g.js +245 -0
  353. package/dist/doctor-j8ytsy94.js +245 -0
  354. package/dist/doctor-mcmkgp6e.js +245 -0
  355. package/dist/doctor-qb6m2exc.js +245 -0
  356. package/dist/doctor-qq4tsh8q.js +245 -0
  357. package/dist/doctor-tecv869a.js +245 -0
  358. package/dist/doctor-wg0245pe.js +245 -0
  359. package/dist/doctor-z3jfqxtz.js +245 -0
  360. package/dist/durable-object-4hey8fgy.js +13 -0
  361. package/dist/durable-object-v3gsnybk.js +13 -0
  362. package/dist/env.d.ts.map +1 -1
  363. package/dist/index-0krb65s3.js +215 -0
  364. package/dist/index-0mantew0.js +513 -0
  365. package/dist/{index-p03n4qet.js → index-0mezg6ar.js} +26 -21
  366. package/dist/{index-mqekt778.js → index-0tk2rs0q.js} +1 -1
  367. package/dist/{index-h18pxvzs.js → index-124e9t4t.js} +1 -1
  368. package/dist/{index-na3mnm1k.js → index-1546yrn0.js} +2 -2
  369. package/dist/index-15fpa5tx.js +232 -0
  370. package/dist/{index-jb75kwa4.js → index-18mp5v50.js} +33 -14
  371. package/dist/{index-4v9bc2pc.js → index-195tc6qh.js} +26 -21
  372. package/dist/{index-0kfzdywd.js → index-1bg8w2gf.js} +1 -1
  373. package/dist/index-1d4jg11n.js +542 -0
  374. package/dist/index-1e2qtrmj.js +188 -0
  375. package/dist/{index-v5nmqthy.js → index-1ghhgb9d.js} +2 -2
  376. package/dist/index-1nhd9nkd.js +232 -0
  377. package/dist/{index-6psz1h4c.js → index-1wn8mjep.js} +116 -96
  378. package/dist/index-1xhd5czz.js +185 -0
  379. package/dist/index-2a2g4fwp.js +993 -0
  380. package/dist/{index-fvsadj32.js → index-2bmtj21z.js} +2 -2
  381. package/dist/{index-816krz9p.js → index-2dpmd14d.js} +1 -1
  382. package/dist/{index-3ke5d2vn.js → index-2fa0afdp.js} +173 -30
  383. package/dist/{index-d8etnfef.js → index-2rcrefqd.js} +173 -30
  384. package/dist/index-2t2m5148.js +1372 -0
  385. package/dist/index-2vbzamev.js +437 -0
  386. package/dist/index-2vdep9h0.js +993 -0
  387. package/dist/{index-zfhq6s96.js → index-2y90j9cz.js} +2 -2
  388. package/dist/index-33ep0z9x.js +385 -0
  389. package/dist/index-37jgbaw6.js +1372 -0
  390. package/dist/index-380ncsqc.js +977 -0
  391. package/dist/{index-thna1tkd.js → index-3e1x39fc.js} +111 -26
  392. package/dist/index-3e7by9sy.js +223 -0
  393. package/dist/{index-xk9djfjp.js → index-3egad6wm.js} +34 -15
  394. package/dist/index-3f8rzmjw.js +232 -0
  395. package/dist/index-3vd4r37r.js +1372 -0
  396. package/dist/index-3vgn5e89.js +1682 -0
  397. package/dist/index-3x7k3t0f.js +513 -0
  398. package/dist/index-3xfe2dst.js +399 -0
  399. package/dist/index-464j1zb4.js +513 -0
  400. package/dist/{index-pnbs1b8k.js → index-48rxsj95.js} +110 -25
  401. package/dist/index-4bezcdd1.js +385 -0
  402. package/dist/index-4fp11z9e.js +973 -0
  403. package/dist/{index-m3fmw6mx.js → index-4knecthc.js} +2 -2
  404. package/dist/index-502y7w13.js +538 -0
  405. package/dist/index-50mxxb4q.js +185 -0
  406. package/dist/index-5achzspr.js +185 -0
  407. package/dist/index-5ef3jmv7.js +1372 -0
  408. package/dist/index-5eswe8yv.js +844 -0
  409. package/dist/index-5gevxfgs.js +513 -0
  410. package/dist/index-5gmf048z.js +817 -0
  411. package/dist/index-5jtkxpjf.js +971 -0
  412. package/dist/{index-72mve6vh.js → index-5m85bd9x.js} +1 -1
  413. package/dist/{index-4rrttqj5.js → index-5n5nn0a8.js} +62 -176
  414. package/dist/index-5p3bgjwr.js +808 -0
  415. package/dist/index-5vzcszr2.js +1230 -0
  416. package/dist/index-5w77r4w9.js +513 -0
  417. package/dist/index-62srkqcm.js +168 -0
  418. package/dist/index-63cgqe43.js +1372 -0
  419. package/dist/index-65e7xx1a.js +19 -0
  420. package/dist/index-65qrje14.js +185 -0
  421. package/dist/index-66sx3b3v.js +385 -0
  422. package/dist/{index-b8m6883k.js → index-678j0n13.js} +2 -2
  423. package/dist/{index-epw1jxz5.js → index-6ftrth7n.js} +194 -180
  424. package/dist/index-6g90pvxa.js +215 -0
  425. package/dist/index-6j4m5x2d.js +1372 -0
  426. package/dist/{index-7v583xan.js → index-6jwpke14.js} +13 -46
  427. package/dist/index-6knsjvxh.js +1372 -0
  428. package/dist/index-6kwq6yf8.js +979 -0
  429. package/dist/index-6mg4yvc6.js +74 -0
  430. package/dist/{index-e9yw4d6y.js → index-6phry941.js} +5 -5
  431. package/dist/index-6r59wbek.js +232 -0
  432. package/dist/index-6sf815ps.js +74 -0
  433. package/dist/index-6zd89k6y.js +1230 -0
  434. package/dist/{index-ry131z23.js → index-71rwg0cn.js} +62 -176
  435. package/dist/index-75ex2m0x.js +695 -0
  436. package/dist/{index-htzf0py1.js → index-79exzs3q.js} +194 -180
  437. package/dist/{index-1sp39f2f.js → index-7bxj118m.js} +62 -176
  438. package/dist/index-7c6np4mq.js +397 -0
  439. package/dist/{index-7x0ybbtx.js → index-7cm339qz.js} +5 -5
  440. package/dist/index-7e359eb5.js +895 -0
  441. package/dist/index-7eqyr4j8.js +70 -0
  442. package/dist/index-7k278fgz.js +273 -0
  443. package/dist/index-7kazxkjt.js +1372 -0
  444. package/dist/index-7m0x8m9r.js +844 -0
  445. package/dist/index-7p74smg8.js +1372 -0
  446. package/dist/index-7q8fke3k.js +188 -0
  447. package/dist/index-7qk6eafn.js +1682 -0
  448. package/dist/{index-yzddwp02.js → index-7vbjt6ba.js} +110 -93
  449. package/dist/{index-7kcxjhta.js → index-7z4b0vgd.js} +19 -5
  450. package/dist/index-82xn4azv.js +74 -0
  451. package/dist/index-83wns7cz.js +70 -0
  452. package/dist/index-852945d4.js +413 -0
  453. package/dist/{index-8t5nb4qx.js → index-86rvj79f.js} +5 -5
  454. package/dist/index-88tcq0t4.js +542 -0
  455. package/dist/{index-q4kaz181.js → index-8evn52g1.js} +279 -268
  456. package/dist/index-8jkf4nsd.js +695 -0
  457. package/dist/{index-sqrksgb2.js → index-8nx4ce3e.js} +7 -7
  458. package/dist/index-8q1bcnrh.js +1372 -0
  459. package/dist/index-8t5gynct.js +971 -0
  460. package/dist/index-905svbb6.js +470 -0
  461. package/dist/index-94cb0sac.js +1372 -0
  462. package/dist/index-95mmvbw7.js +538 -0
  463. package/dist/index-97x94h0m.js +438 -0
  464. package/dist/index-9an9qqr1.js +728 -0
  465. package/dist/index-9d125myk.js +1372 -0
  466. package/dist/index-9gg0kqw0.js +470 -0
  467. package/dist/index-9ryw7mcw.js +971 -0
  468. package/dist/index-a3e13a7m.js +478 -0
  469. package/dist/index-a6j44jmr.js +1372 -0
  470. package/dist/index-a75ejnvt.js +1711 -0
  471. package/dist/index-ab2nck1h.js +1372 -0
  472. package/dist/index-abrqnq3e.js +488 -0
  473. package/dist/index-afjbpgb1.js +1218 -0
  474. package/dist/index-at89fpde.js +470 -0
  475. package/dist/{index-cgbvmse6.js → index-awr0tp6p.js} +1 -1
  476. package/dist/index-b1be9bdh.js +1372 -0
  477. package/dist/index-b1xs3wc4.js +513 -0
  478. package/dist/index-b50x7seh.js +513 -0
  479. package/dist/{index-9az6s7ad.js → index-b5ra8w3q.js} +1 -1
  480. package/dist/index-b64sbzgv.js +884 -0
  481. package/dist/index-b7r8ntpm.js +1372 -0
  482. package/dist/index-ba9gyy13.js +513 -0
  483. package/dist/{index-k29yjhv0.js → index-bb66mn7p.js} +1 -1
  484. package/dist/index-bc5pvbbd.js +1193 -0
  485. package/dist/index-bj0mk3dw.js +74 -0
  486. package/dist/index-bj3a8dr0.js +1372 -0
  487. package/dist/index-bk3eez1g.js +513 -0
  488. package/dist/index-btjx137w.js +774 -0
  489. package/dist/index-btrfqp9h.js +133 -0
  490. package/dist/index-bx6gangy.js +402 -0
  491. package/dist/index-c0tc0yts.js +471 -0
  492. package/dist/{index-6jef5emv.js → index-c0whkev9.js} +27 -3
  493. package/dist/index-ca96qkva.js +1372 -0
  494. package/dist/index-cdtzkedk.js +993 -0
  495. package/dist/index-cejgenma.js +1372 -0
  496. package/dist/index-cp8jt5pr.js +52 -0
  497. package/dist/index-cpz69pek.js +1372 -0
  498. package/dist/{index-gs4y9gdf.js → index-crrdegk5.js} +2 -2
  499. package/dist/index-cskszwkx.js +1372 -0
  500. package/dist/index-cxf22a0s.js +74 -0
  501. package/dist/index-cy3c3w81.js +270 -0
  502. package/dist/index-d5dgb1j6.js +74 -0
  503. package/dist/index-da397xcx.js +1372 -0
  504. package/dist/index-damyy8bw.js +1372 -0
  505. package/dist/{index-x9cwdxw5.js → index-dd6fwwmq.js} +3 -3
  506. package/dist/index-dh1954bp.js +52 -0
  507. package/dist/index-djp2wd1f.js +1372 -0
  508. package/dist/{index-0apbm26n.js → index-dmbdj6va.js} +111 -94
  509. package/dist/index-dmf76tac.js +1372 -0
  510. package/dist/index-dphr32gc.js +420 -0
  511. package/dist/index-dxh2qyyw.js +52 -0
  512. package/dist/index-dzayfxjy.js +492 -0
  513. package/dist/index-e05q77kt.js +397 -0
  514. package/dist/index-e11b1fb2.js +495 -0
  515. package/dist/index-e3zvspqj.js +968 -0
  516. package/dist/index-e4tzzbn9.js +1372 -0
  517. package/dist/index-e5ct1gwb.js +1372 -0
  518. package/dist/index-e7ptcz1a.js +1372 -0
  519. package/dist/index-e7wt0203.js +513 -0
  520. package/dist/{index-61jsjnsv.js → index-ebwsvf9t.js} +110 -25
  521. package/dist/index-ed73jn3d.js +185 -0
  522. package/dist/index-ed7n5d07.js +185 -0
  523. package/dist/index-ejs2a4kd.js +513 -0
  524. package/dist/index-esjrgt3y.js +467 -0
  525. package/dist/index-ev03khsd.js +513 -0
  526. package/dist/index-f1gsqm54.js +168 -0
  527. package/dist/index-f90314kt.js +52 -0
  528. package/dist/index-f9mhsept.js +185 -0
  529. package/dist/index-fa6zwffw.js +70 -0
  530. package/dist/index-fama7kpt.js +52 -0
  531. package/dist/index-fgk87mk2.js +1067 -0
  532. package/dist/index-fkyvxe4b.js +968 -0
  533. package/dist/index-g0h40xke.js +513 -0
  534. package/dist/index-g0rqh52c.js +385 -0
  535. package/dist/{index-0eqksag4.js → index-g170d619.js} +13 -46
  536. package/dist/index-g3qtxkms.js +881 -0
  537. package/dist/index-gactvqcs.js +467 -0
  538. package/dist/index-gaew61v4.js +470 -0
  539. package/dist/index-gba371j7.js +542 -0
  540. package/dist/index-gegyyfnw.js +1372 -0
  541. package/dist/index-get7he2s.js +133 -0
  542. package/dist/index-gn5wy09x.js +205 -0
  543. package/dist/{index-2pb7b9mw.js → index-gtbgzwfs.js} +62 -176
  544. package/dist/index-gtpz0gkz.js +185 -0
  545. package/dist/index-h1s66pmp.js +52 -0
  546. package/dist/{index-11m5a8wd.js → index-h8r2d8y5.js} +112 -26
  547. package/dist/index-heeqwrfd.js +385 -0
  548. package/dist/{index-7g8zyws4.js → index-hheb5dyt.js} +2 -2
  549. package/dist/index-hjz2x9nq.js +441 -0
  550. package/dist/index-hkex7ns5.js +513 -0
  551. package/dist/index-hmbctwv6.js +517 -0
  552. package/dist/index-hpzasdhw.js +513 -0
  553. package/dist/index-hqdr9wdm.js +74 -0
  554. package/dist/index-hrvz8d26.js +1372 -0
  555. package/dist/index-hyvhnf6r.js +971 -0
  556. package/dist/index-j2kc5rbv.js +895 -0
  557. package/dist/index-j2xdxwsz.js +133 -0
  558. package/dist/index-j47hhb3r.js +694 -0
  559. package/dist/index-j5aphr5x.js +185 -0
  560. package/dist/index-j68v36q1.js +188 -0
  561. package/dist/index-j7cf22x7.js +968 -0
  562. package/dist/index-j7xxrbnr.js +694 -0
  563. package/dist/index-jptqxkew.js +470 -0
  564. package/dist/index-jsymy3mb.js +781 -0
  565. package/dist/index-jwvy32xk.js +188 -0
  566. package/dist/index-jxe1b19v.js +133 -0
  567. package/dist/index-jz96ry5g.js +513 -0
  568. package/dist/index-k6wtsgs1.js +971 -0
  569. package/dist/index-kawa49m8.js +371 -0
  570. package/dist/index-key4e5c9.js +168 -0
  571. package/dist/index-khbmdrn2.js +884 -0
  572. package/dist/index-kpzfwex6.js +264 -0
  573. package/dist/index-kse4gn99.js +74 -0
  574. package/dist/index-ktscz0r2.js +264 -0
  575. package/dist/index-kybmjvad.js +1212 -0
  576. package/dist/index-kzm9cea8.js +185 -0
  577. package/dist/index-m2d74gqg.js +808 -0
  578. package/dist/index-m56w7mjt.js +513 -0
  579. package/dist/index-m95ha3n4.js +264 -0
  580. package/dist/index-ma151p8g.js +264 -0
  581. package/dist/index-mg8vwqxf.js +514 -0
  582. package/dist/index-mhdsywhs.js +264 -0
  583. package/dist/index-mjgx910r.js +895 -0
  584. package/dist/index-mkrmaea3.js +185 -0
  585. package/dist/index-mkxnyyjn.js +264 -0
  586. package/dist/index-mp5mrst6.js +1372 -0
  587. package/dist/index-ms15cr86.js +513 -0
  588. package/dist/index-mt99xkc6.js +133 -0
  589. package/dist/index-mttv6k25.js +881 -0
  590. package/dist/index-myxfx52v.js +385 -0
  591. package/dist/index-mzw7732t.js +74 -0
  592. package/dist/index-n3mjwz22.js +188 -0
  593. package/dist/index-n3yksgz0.js +1372 -0
  594. package/dist/{index-9n6djthj.js → index-n4jr3dmk.js} +32 -38
  595. package/dist/index-n5drt64b.js +74 -0
  596. package/dist/index-n8frmffg.js +264 -0
  597. package/dist/index-n8k8chde.js +694 -0
  598. package/dist/index-na796ka6.js +994 -0
  599. package/dist/index-nbs4q0qg.js +1218 -0
  600. package/dist/index-newpq2zf.js +968 -0
  601. package/dist/index-nexg9p7j.js +1271 -0
  602. package/dist/index-nfm8tb5n.js +74 -0
  603. package/dist/index-nga2tg9z.js +1372 -0
  604. package/dist/{index-43dq8yx8.js → index-ngbzr9gz.js} +111 -94
  605. package/dist/index-nh90nk7j.js +380 -0
  606. package/dist/index-njnmfxm5.js +1372 -0
  607. package/dist/index-nqma24j3.js +385 -0
  608. package/dist/index-ntddf5d9.js +993 -0
  609. package/dist/index-nte9n8w9.js +538 -0
  610. package/dist/index-ntxp7ke1.js +264 -0
  611. package/dist/index-nwxnmw41.js +264 -0
  612. package/dist/index-p1xe5eem.js +513 -0
  613. package/dist/{index-wztc9stx.js → index-p477xm52.js} +13 -46
  614. package/dist/index-p8nmkrgw.js +470 -0
  615. package/dist/{index-yqbxjysa.js → index-p97s12vf.js} +50 -43
  616. package/dist/index-p9hvv0yd.js +401 -0
  617. package/dist/index-pac7wv88.js +307 -0
  618. package/dist/index-ptp2pfq1.js +52 -0
  619. package/dist/index-pyeycp3f.js +74 -0
  620. package/dist/index-q23xf3vr.js +479 -0
  621. package/dist/index-q34rvh5a.js +247 -0
  622. package/dist/{index-j185x270.js → index-q5errwrj.js} +53 -46
  623. package/dist/{index-2jnrqbny.js → index-q5nhzc9m.js} +4 -88
  624. package/dist/index-q8f4kawk.js +204 -0
  625. package/dist/index-qer8zv2r.js +997 -0
  626. package/dist/index-qhyy018y.js +467 -0
  627. package/dist/index-qmhdydwy.js +70 -0
  628. package/dist/index-qpmvca5j.js +470 -0
  629. package/dist/index-qr96vaj1.js +52 -0
  630. package/dist/{index-74198nxd.js → index-qtyhg3dn.js} +53 -46
  631. package/dist/index-qye17gq5.js +264 -0
  632. package/dist/index-r0839f5k.js +133 -0
  633. package/dist/index-r1rqg72v.js +1372 -0
  634. package/dist/index-rbckga8p.js +971 -0
  635. package/dist/index-rbxb5x2w.js +1372 -0
  636. package/dist/index-rck779bj.js +739 -0
  637. package/dist/index-rfn2gt5f.js +1658 -0
  638. package/dist/index-rg21w26a.js +470 -0
  639. package/dist/index-rgcz45t0.js +1372 -0
  640. package/dist/index-rhnd376q.js +133 -0
  641. package/dist/index-rjc5z3w6.js +971 -0
  642. package/dist/index-rkhtayd6.js +385 -0
  643. package/dist/index-rm8srzmv.js +371 -0
  644. package/dist/index-rmhk5j03.js +968 -0
  645. package/dist/index-rp4t86bt.js +993 -0
  646. package/dist/index-rpq5ktdy.js +264 -0
  647. package/dist/index-rpsmhdd4.js +1218 -0
  648. package/dist/index-rqpakjyr.js +470 -0
  649. package/dist/index-rttk33x6.js +232 -0
  650. package/dist/index-rwa82e89.js +385 -0
  651. package/dist/index-rz185crv.js +695 -0
  652. package/dist/index-s22verzj.js +1218 -0
  653. package/dist/index-s2s3g1nt.js +133 -0
  654. package/dist/index-s7ytytth.js +781 -0
  655. package/dist/index-sefnpzwa.js +185 -0
  656. package/dist/index-sgxw0xzd.js +513 -0
  657. package/dist/index-stc0caq6.js +1009 -0
  658. package/dist/index-svz82w9h.js +513 -0
  659. package/dist/index-sx49e8x9.js +884 -0
  660. package/dist/index-sxadwvw9.js +185 -0
  661. package/dist/index-sxn223fz.js +1372 -0
  662. package/dist/index-sy0c2mh0.js +1372 -0
  663. package/dist/index-syeh1hca.js +264 -0
  664. package/dist/index-t18wyhgf.js +418 -0
  665. package/dist/index-t4fhcx1n.js +71 -0
  666. package/dist/index-td4hbgj5.js +1372 -0
  667. package/dist/{index-hjy8ctpc.js → index-tkvt9mmq.js} +47 -14
  668. package/dist/index-tmmcf4m6.js +808 -0
  669. package/dist/index-tpgs5v64.js +366 -0
  670. package/dist/index-tt4fsv91.js +412 -0
  671. package/dist/{index-t08te69w.js → index-tte89s31.js} +28 -11
  672. package/dist/index-tvjg7swe.js +1372 -0
  673. package/dist/index-txndxr4w.js +513 -0
  674. package/dist/index-tyh5jc55.js +990 -0
  675. package/dist/index-tyt0wa52.js +470 -0
  676. package/dist/index-tyt3wcfr.js +1372 -0
  677. package/dist/index-v3znz08m.js +968 -0
  678. package/dist/index-v78xbj6n.js +808 -0
  679. package/dist/index-v915brjk.js +1372 -0
  680. package/dist/index-v922fmsx.js +52 -0
  681. package/dist/index-v9w1bbfe.js +842 -0
  682. package/dist/index-vbbgtm8p.js +513 -0
  683. package/dist/{index-k6vq6kkt.js → index-vcjgrmzj.js} +3 -3
  684. package/dist/{index-9ba1etyz.js → index-vdewcg1r.js} +204 -54
  685. package/dist/index-vhqww6tt.js +307 -0
  686. package/dist/index-vse8620z.js +1372 -0
  687. package/dist/index-vtjp46c3.js +52 -0
  688. package/dist/{index-jwd8pcb2.js → index-vxhxk8mf.js} +53 -46
  689. package/dist/index-w3azfsa0.js +695 -0
  690. package/dist/index-w4tq35dn.js +52 -0
  691. package/dist/index-w5qxvxzq.js +991 -0
  692. package/dist/index-w5sedpqn.js +986 -0
  693. package/dist/index-waha3chv.js +1230 -0
  694. package/dist/index-wdxww0kj.js +1006 -0
  695. package/dist/index-wdy5y07x.js +1372 -0
  696. package/dist/index-wf9pnh6j.js +385 -0
  697. package/dist/index-wnnbbbkt.js +1192 -0
  698. package/dist/index-wvcmvtjf.js +1372 -0
  699. package/dist/index-x0jbntp0.js +470 -0
  700. package/dist/index-x6scc3nx.js +70 -0
  701. package/dist/index-x8e2wsbv.js +971 -0
  702. package/dist/index-xec4p3v5.js +560 -0
  703. package/dist/index-xgfyxpfs.js +1218 -0
  704. package/dist/index-xm9hp9xc.js +1372 -0
  705. package/dist/index-xp7zkxcx.js +1372 -0
  706. package/dist/index-xrbj0ebk.js +185 -0
  707. package/dist/index-xskax7r3.js +50 -0
  708. package/dist/index-xvk5n96q.js +694 -0
  709. package/dist/index-xy1jvt4w.js +1229 -0
  710. package/dist/index-xzg9hhf3.js +470 -0
  711. package/dist/index-xzpg0kaz.js +70 -0
  712. package/dist/index-y3q6qvv3.js +316 -0
  713. package/dist/index-y44ts1dk.js +52 -0
  714. package/dist/index-y5nt1wjb.js +971 -0
  715. package/dist/index-y82b8w14.js +1372 -0
  716. package/dist/index-yb07t3c5.js +1372 -0
  717. package/dist/index-yc3xz3vm.js +431 -0
  718. package/dist/index-yeaqrevg.js +1372 -0
  719. package/dist/index-ygwsd1nn.js +438 -0
  720. package/dist/index-yhdavjk7.js +371 -0
  721. package/dist/index-yjhns95b.js +188 -0
  722. package/dist/index-yk23p7he.js +1372 -0
  723. package/dist/index-ykfgpsmm.js +190 -0
  724. package/dist/index-ymz3cfab.js +968 -0
  725. package/dist/index-yq9g1sq7.js +264 -0
  726. package/dist/index-ys5q9ch9.js +366 -0
  727. package/dist/index-yt0n4p46.js +973 -0
  728. package/dist/index-ytq1t9jx.js +232 -0
  729. package/dist/index-ywmtmf3b.js +513 -0
  730. package/dist/index-yzb44q6d.js +1372 -0
  731. package/dist/index-z043xk61.js +133 -0
  732. package/dist/index-z0gsf674.js +431 -0
  733. package/dist/index-z32n0ndp.js +1372 -0
  734. package/dist/index-z4qgk76w.js +1372 -0
  735. package/dist/{index-yc0gcchc.js → index-z8njfj2g.js} +11 -44
  736. package/dist/{index-0w826dsr.js → index-z9fjnwa8.js} +21 -3
  737. package/dist/{index-1xpj0m4r.js → index-z9gy8w6b.js} +1 -1
  738. package/dist/index-zapkc14c.js +264 -0
  739. package/dist/index-zes6w8yr.js +185 -0
  740. package/dist/index-zgrqest7.js +695 -0
  741. package/dist/index-zsngz131.js +1372 -0
  742. package/dist/index-zxhc6sb0.js +192 -0
  743. package/dist/index.d.ts +1 -5
  744. package/dist/index.d.ts.map +1 -1
  745. package/dist/index.js +61 -0
  746. package/dist/{init-r4hnxan3.js → init-wfh63bfz.js} +1 -1
  747. package/dist/{login-5bsxxpvc.js → login-1amyp1jy.js} +10 -10
  748. package/dist/{login-bhaw72zc.js → login-1cdwn1dj.js} +11 -11
  749. package/dist/{login-2hnz4m4n.js → login-456h8jk3.js} +11 -11
  750. package/dist/{login-6tzvczw2.js → login-4n470c4j.js} +11 -11
  751. package/dist/login-4sh7s849.js +77 -0
  752. package/dist/login-5dmkf0pz.js +77 -0
  753. package/dist/login-88tp4gbb.js +77 -0
  754. package/dist/login-b51faqpc.js +77 -0
  755. package/dist/login-bxyjqmbj.js +77 -0
  756. package/dist/login-c4649qss.js +77 -0
  757. package/dist/login-d80a2qxd.js +77 -0
  758. package/dist/login-dp0napaz.js +77 -0
  759. package/dist/login-j3r6z2t4.js +77 -0
  760. package/dist/login-jkfkdjg4.js +77 -0
  761. package/dist/login-kch6f2yj.js +77 -0
  762. package/dist/login-pmqh94ws.js +77 -0
  763. package/dist/login-rc82x5j8.js +77 -0
  764. package/dist/login-tvppwyx2.js +77 -0
  765. package/dist/login-w76jx22q.js +77 -0
  766. package/dist/login-ze7y36rc.js +77 -0
  767. package/dist/{previews-gm3z0syj.js → previews-02jmcwft.js} +140 -94
  768. package/dist/previews-31bq82km.js +1225 -0
  769. package/dist/{previews-j9ymq4ys.js → previews-62pcvvpe.js} +140 -95
  770. package/dist/{previews-3rn8mz2c.js → previews-76fxkp59.js} +140 -94
  771. package/dist/previews-844bp6kf.js +1214 -0
  772. package/dist/previews-8amn46qv.js +1214 -0
  773. package/dist/previews-a5xbkksy.js +1214 -0
  774. package/dist/previews-bgnryzav.js +1214 -0
  775. package/dist/previews-bkhv9dnr.js +1214 -0
  776. package/dist/previews-c2c64z5m.js +1214 -0
  777. package/dist/previews-e4wgscsb.js +1214 -0
  778. package/dist/previews-ew4reetn.js +1214 -0
  779. package/dist/previews-hzqke1fg.js +1214 -0
  780. package/dist/previews-j8wa3sge.js +1214 -0
  781. package/dist/previews-k5n6vhpm.js +1214 -0
  782. package/dist/previews-n4sdyxa5.js +1214 -0
  783. package/dist/previews-npwrwb0b.js +1214 -0
  784. package/dist/previews-q8ph9wbe.js +1214 -0
  785. package/dist/previews-rfswrh7q.js +1214 -0
  786. package/dist/previews-s0y5yp8s.js +1214 -0
  787. package/dist/previews-s5b6mnz5.js +1214 -0
  788. package/dist/{previews-d487qde5.js → previews-sdte4984.js} +23 -23
  789. package/dist/previews-t5tdm6t0.js +1225 -0
  790. package/dist/previews-tk7vpzj9.js +1214 -0
  791. package/dist/previews-tqt4pk27.js +1214 -0
  792. package/dist/previews-vqg4psk2.js +1225 -0
  793. package/dist/{productions-x9p0pym1.js → productions-4abj58kx.js} +12 -12
  794. package/dist/{productions-5ev5qweg.js → productions-4dpec71r.js} +13 -13
  795. package/dist/{productions-120xg0aq.js → productions-4nedsanh.js} +13 -13
  796. package/dist/{productions-p5rbgp2f.js → productions-5c58yafp.js} +13 -13
  797. package/dist/{productions-me3tdvr9.js → productions-5xq5cjhx.js} +13 -13
  798. package/dist/productions-6dr0bmd7.js +505 -0
  799. package/dist/productions-8f6s8dqr.js +505 -0
  800. package/dist/productions-a2hcwwzf.js +505 -0
  801. package/dist/productions-b7svyjp7.js +505 -0
  802. package/dist/productions-bf2cnr05.js +505 -0
  803. package/dist/productions-dkgry3gv.js +505 -0
  804. package/dist/productions-eqh105tk.js +505 -0
  805. package/dist/productions-etvcm7yf.js +505 -0
  806. package/dist/productions-f1zpbmjz.js +505 -0
  807. package/dist/productions-j14pvx93.js +505 -0
  808. package/dist/productions-j7s1ywvg.js +505 -0
  809. package/dist/productions-jp3v3q3p.js +505 -0
  810. package/dist/productions-m9p42amj.js +505 -0
  811. package/dist/productions-mxbneawa.js +505 -0
  812. package/dist/productions-np4exh9p.js +505 -0
  813. package/dist/productions-rr1hqgda.js +505 -0
  814. package/dist/productions-rtf9ksgg.js +505 -0
  815. package/dist/productions-w2nzftcz.js +505 -0
  816. package/dist/productions-wbks5h7e.js +505 -0
  817. package/dist/productions-y99ayk6h.js +505 -0
  818. package/dist/productions-zpqyw5gm.js +505 -0
  819. package/dist/runtime/context-events.d.ts.map +1 -1
  820. package/dist/runtime/context.d.ts +8 -1
  821. package/dist/runtime/context.d.ts.map +1 -1
  822. package/dist/runtime/exports.d.ts +1 -4
  823. package/dist/runtime/exports.d.ts.map +1 -1
  824. package/dist/runtime/index.d.ts +3 -3
  825. package/dist/runtime/index.d.ts.map +1 -1
  826. package/dist/{src/runtime → runtime}/index.js +22 -7
  827. package/dist/runtime/middleware.d.ts +55 -0
  828. package/dist/runtime/middleware.d.ts.map +1 -1
  829. package/dist/runtime/router/index.d.ts +7 -0
  830. package/dist/runtime/router/index.d.ts.map +1 -0
  831. package/dist/runtime/router/types.d.ts +24 -0
  832. package/dist/runtime/router/types.d.ts.map +1 -0
  833. package/dist/runtime/validation.d.ts +9 -1
  834. package/dist/runtime/validation.d.ts.map +1 -1
  835. package/dist/{src/sveltekit → sveltekit}/index.js +36 -71
  836. package/dist/sveltekit/platform.d.ts +10 -0
  837. package/dist/sveltekit/platform.d.ts.map +1 -1
  838. package/dist/test/binding-hints.d.ts +11 -0
  839. package/dist/test/binding-hints.d.ts.map +1 -0
  840. package/dist/test/bridge-context.d.ts +7 -0
  841. package/dist/test/bridge-context.d.ts.map +1 -1
  842. package/dist/test/index.d.ts +0 -1
  843. package/dist/test/index.d.ts.map +1 -1
  844. package/dist/{index-2x53aqjm.js → test/index.js} +836 -774
  845. package/dist/test/simple-context-bindings.d.ts +13 -0
  846. package/dist/test/simple-context-bindings.d.ts.map +1 -0
  847. package/dist/test/simple-context-env.d.ts +35 -0
  848. package/dist/test/simple-context-env.d.ts.map +1 -0
  849. package/dist/test/simple-context-gateway-script.d.ts.map +1 -1
  850. package/dist/test/simple-context-handlers.d.ts +12 -0
  851. package/dist/test/simple-context-handlers.d.ts.map +1 -0
  852. package/dist/test/simple-context-lifecycle.d.ts +32 -0
  853. package/dist/test/simple-context-lifecycle.d.ts.map +1 -0
  854. package/dist/test/simple-context-mfconfig.d.ts +7 -0
  855. package/dist/test/simple-context-mfconfig.d.ts.map +1 -0
  856. package/dist/test/simple-context-multi-worker.d.ts +16 -0
  857. package/dist/test/simple-context-multi-worker.d.ts.map +1 -0
  858. package/dist/test/simple-context-runtime.d.ts +19 -0
  859. package/dist/test/simple-context-runtime.d.ts.map +1 -0
  860. package/dist/test/simple-context-startup.d.ts +11 -0
  861. package/dist/test/simple-context-startup.d.ts.map +1 -0
  862. package/dist/test/simple-context-transport.d.ts +14 -0
  863. package/dist/test/simple-context-transport.d.ts.map +1 -0
  864. package/dist/test/simple-context.d.ts +6 -3
  865. package/dist/test/simple-context.d.ts.map +1 -1
  866. package/dist/test/utilities.d.ts +13 -5
  867. package/dist/test/utilities.d.ts.map +1 -1
  868. package/dist/test/worker.d.ts +1 -1
  869. package/dist/test/worker.d.ts.map +1 -1
  870. package/dist/{token-kedhcret.js → token-3b9wws58.js} +3 -3
  871. package/dist/{token-m8jmnjwk.js → token-47kcz18j.js} +3 -3
  872. package/dist/token-exz78pth.js +419 -0
  873. package/dist/token-fcthx92c.js +419 -0
  874. package/dist/token-grwp8z4q.js +419 -0
  875. package/dist/token-jkmm44z2.js +419 -0
  876. package/dist/token-qxtvzm3b.js +419 -0
  877. package/dist/token-rq8mvtz9.js +419 -0
  878. package/dist/token-sct51r47.js +419 -0
  879. package/dist/token-sfgxcgen.js +419 -0
  880. package/dist/transform/durable-object.d.ts.map +1 -1
  881. package/dist/transform/worker-entrypoint.d.ts +5 -0
  882. package/dist/transform/worker-entrypoint.d.ts.map +1 -1
  883. package/dist/types-0qv4xces.js +572 -0
  884. package/dist/types-2nvrs9jg.js +572 -0
  885. package/dist/types-2pbe8kzw.js +572 -0
  886. package/dist/types-2zyt0m43.js +572 -0
  887. package/dist/types-4xxer9ep.js +572 -0
  888. package/dist/{types-6e5yx6km.js → types-5t5y7a5n.js} +9 -9
  889. package/dist/{types-1gwr2ex6.js → types-5wd2rygw.js} +9 -9
  890. package/dist/types-7j3ykgx7.js +572 -0
  891. package/dist/types-8g78x34n.js +572 -0
  892. package/dist/types-e6d336q3.js +572 -0
  893. package/dist/types-hqh2fx0x.js +572 -0
  894. package/dist/types-j12xmdnd.js +572 -0
  895. package/dist/types-jqn26et3.js +572 -0
  896. package/dist/types-n0mxbq26.js +572 -0
  897. package/dist/types-naz9hvw5.js +572 -0
  898. package/dist/{types-p0gckpn6.js → types-qjcd1jks.js} +7 -7
  899. package/dist/types-r9zb8sw1.js +572 -0
  900. package/dist/types-rv5xwgsn.js +572 -0
  901. package/dist/types-t39njdqx.js +572 -0
  902. package/dist/types-tkgch3xv.js +572 -0
  903. package/dist/{types-0sqwkp7x.js → types-vvtb7rrh.js} +9 -9
  904. package/dist/types-w1grncdj.js +572 -0
  905. package/dist/types-wmw49exb.js +572 -0
  906. package/dist/types-ymxz9jga.js +572 -0
  907. package/dist/utils/resolve-package.d.ts.map +1 -1
  908. package/dist/utils/send-email.js +19 -0
  909. package/dist/vite/config-file.d.ts.map +1 -1
  910. package/dist/{src/vite → vite}/index.js +12 -11
  911. package/dist/vite/plugin-config-hook.d.ts +28 -0
  912. package/dist/vite/plugin-config-hook.d.ts.map +1 -0
  913. package/dist/vite/plugin-context.d.ts +25 -0
  914. package/dist/vite/plugin-context.d.ts.map +1 -0
  915. package/dist/vite/plugin-durable-objects.d.ts +18 -0
  916. package/dist/vite/plugin-durable-objects.d.ts.map +1 -0
  917. package/dist/vite/plugin-programmatic.d.ts +44 -0
  918. package/dist/vite/plugin-programmatic.d.ts.map +1 -0
  919. package/dist/vite/plugin-transform.d.ts +41 -0
  920. package/dist/vite/plugin-transform.d.ts.map +1 -0
  921. package/dist/vite/plugin.d.ts +6 -39
  922. package/dist/vite/plugin.d.ts.map +1 -1
  923. package/dist/{worker-y9ha6g44.js → worker-18ceqscc.js} +11 -11
  924. package/dist/{worker-0srh2jfr.js → worker-1yqpwte2.js} +12 -12
  925. package/dist/{worker-qtam8grz.js → worker-2aw27zxy.js} +12 -12
  926. package/dist/{worker-4xrfd10a.js → worker-45tp4a8f.js} +12 -12
  927. package/dist/worker-68zttchg.js +513 -0
  928. package/dist/worker-729cf3fh.js +513 -0
  929. package/dist/worker-aydzxt4f.js +513 -0
  930. package/dist/worker-ejdxma7k.js +513 -0
  931. package/dist/worker-entry/composed-worker.d.ts +1 -0
  932. package/dist/worker-entry/composed-worker.d.ts.map +1 -1
  933. package/dist/worker-entry/durable-object-discovery.d.ts +20 -0
  934. package/dist/worker-entry/durable-object-discovery.d.ts.map +1 -0
  935. package/dist/worker-entry/extensions.d.ts +5 -0
  936. package/dist/worker-entry/extensions.d.ts.map +1 -0
  937. package/dist/worker-entry/routes.d.ts +1 -1
  938. package/dist/worker-entry/routes.d.ts.map +1 -1
  939. package/dist/worker-entry/surface-paths.d.ts +13 -4
  940. package/dist/worker-entry/surface-paths.d.ts.map +1 -1
  941. package/dist/worker-entrypoint-4xp7msd7.js +16 -0
  942. package/dist/worker-entrypoint-f1v9y4s8.js +15 -0
  943. package/dist/{worker-qzm0b7br.js → worker-f6xqjg65.js} +12 -12
  944. package/dist/worker-fdnn62de.js +513 -0
  945. package/dist/worker-frnh95rg.js +513 -0
  946. package/dist/worker-k55nfrmp.js +513 -0
  947. package/dist/worker-kqc6w7ry.js +513 -0
  948. package/dist/worker-ksvcq8be.js +513 -0
  949. package/dist/worker-mjzfstv5.js +513 -0
  950. package/dist/worker-p4rtsndj.js +513 -0
  951. package/dist/worker-p6d53qan.js +513 -0
  952. package/dist/worker-qh2qbv97.js +513 -0
  953. package/dist/worker-r234vnv9.js +513 -0
  954. package/dist/worker-r47bv7gt.js +513 -0
  955. package/dist/worker-s4nvbqsm.js +513 -0
  956. package/dist/worker-ttj7vwce.js +513 -0
  957. package/dist/worker-wv4jdneg.js +513 -0
  958. package/dist/worker-xcbscr75.js +513 -0
  959. package/dist/worker-ywwkf3cp.js +513 -0
  960. package/dist/worker-z8wtk0sh.js +513 -0
  961. package/package.json +138 -123
  962. package/dist/account-s66jb15j.js +0 -475
  963. package/dist/browser-shim/worker.d.ts +0 -14
  964. package/dist/browser-shim/worker.d.ts.map +0 -1
  965. package/dist/deploy-7nmzc9r8.js +0 -609
  966. package/dist/deploy-tp0g6qdp.js +0 -609
  967. package/dist/index-091sh1ma.js +0 -1229
  968. package/dist/index-f85s8gj3.js +0 -2649
  969. package/dist/index-fe2ngvh7.js +0 -1229
  970. package/dist/index-hfj1a2c4.js +0 -2649
  971. package/dist/index-maxpsfk8.js +0 -402
  972. package/dist/index-mbdmrner.js +0 -402
  973. package/dist/index-mea5bc45.js +0 -418
  974. package/dist/index-sgb7c8nm.js +0 -402
  975. package/dist/index-vt4yxkmf.js +0 -470
  976. package/dist/index-wyq6c6yj.js +0 -402
  977. package/dist/index-zyt5byt6.js +0 -2649
  978. package/dist/login-x8tgckqm.js +0 -77
  979. package/dist/previews-q031mx34.js +0 -1168
  980. package/dist/src/cli/index.js +0 -12
  981. package/dist/src/index.js +0 -144
  982. package/dist/src/test/index.js +0 -77
package/LLM.md CHANGED
@@ -11,7 +11,7 @@ It is meant to read like a proper markdown handbook rather than a second source
11
11
  - Links use the same `/docs/...` routes as the documentation site.
12
12
 
13
13
  ## Documentation map
14
- This export covers 83 pages across 5 top-level groups.
14
+ This export covers 87 pages across 5 top-level groups.
15
15
 
16
16
  ### Quickstart
17
17
  See why Devflare exists, build the smallest safe first worker, and keep the documentation contract nearby before you branch into the deeper toolkit.
@@ -56,7 +56,7 @@ Keep the day-to-day Devflare surfaces easy to scan: runtime model, HTTP split, a
56
56
  - **Frameworks** — Choose the right host lane for worker-rendered Svelte, standalone Vite apps, and full SvelteKit shells without losing the worker-first mental model.
57
57
  - [Svelte in workers](/docs/svelte-with-rolldown) — When a worker-only fetch surface or Durable Object imports `.svelte`, add the Svelte compiler to `rolldown.options.plugins`. That compilation belongs to Devflare’s worker bundler, not the main Vite plugin chain.
58
58
  - [Vite standalone](/docs/vite-standalone) — An effective Vite config is what opts the package into Vite-backed flows: a local `vite.config.*`, a non-empty `config.vite`, or both together. Use `devflare/vite` when the package really is a Vite app and you want Devflare to keep Worker config, Durable Objects, and generated Wrangler output aligned underneath it.
59
- - [SvelteKit](/docs/sveltekit-with-devflare) — Point Devflare at SvelteKits Cloudflare worker output—often via `files.fetch`, but sometimes by handing `wrangler.passthrough.main` the adapter worker directly—keep `sveltekit()` in `vite.config.ts`, and compose `devflare/sveltekit` into `src/hooks.server.ts` so local platform bindings line up with the Worker runtime Devflare manages.
59
+ - [SvelteKit](/docs/sveltekit-with-devflare) — Hand SvelteKit's Cloudflare adapter output to Devflare via `wrangler.passthrough.main` (the adapter worker is a build artifact and does not exist until `vite build` runs), keep `sveltekit()` in `vite.config.ts`, and compose `devflare/sveltekit` into `src/hooks.server.ts` so local platform bindings line up with the Worker runtime Devflare manages.
60
60
 
61
61
  ### Ship & operate
62
62
  Deploy explicitly, choose the right preview model, manage preview lifecycle cleanly, and keep CI/CD plus verification honest.
@@ -92,70 +92,76 @@ Use cross-cutting guides to choose the right storage, state, async, file-deliver
92
92
  Use the per-binding guides for the exact authoring, runtime, testing, preview, and example details once the guide pages have already helped you choose the right pattern.
93
93
 
94
94
  - **KV** — Fast lookup state, cache-like reads, and lightweight shared data with strong local support.
95
- - [KV](/docs/kv-binding) — KV bindings are first-class in Devflare: author stable names in config, keep env typed, and run real get or put flows locally.
96
- - [KV internals](/docs/kv-internals) — KV goes through the full Devflare pipeline: normalize authoring, resolve names when needed, then compile to Wrangler output.
97
- - [Testing KV](/docs/kv-testing) — Use the default test harness first. KV is one of the bindings Devflare supports best in local tests.
98
- - [KV example](/docs/kv-example) — This example keeps KV simple: one binding, one fetch handler, one assertion.
95
+ - [KV](/docs/bindings/kv) — KV bindings are first-class in Devflare: author stable names in config, keep env typed, and run real get or put flows locally.
96
+ - [KV internals](/docs/bindings/kv/internals) — KV goes through the full Devflare pipeline: normalize authoring, resolve names when needed, then compile to Wrangler output.
97
+ - [Testing KV](/docs/bindings/kv/testing) — Use the default test harness first. KV is one of the bindings Devflare supports best in local tests.
98
+ - [KV example](/docs/bindings/kv/example) — This example keeps KV simple: one binding, one fetch handler, one assertion.
99
99
 
100
100
  - **D1** — SQLite-style relational queries with a strong local harness and id or name-based authoring.
101
- - [D1](/docs/d1-binding) — D1 gets the same stable-name authoring story as KV, but the runtime shape is relational: `prepare`, `batch`, `exec`, and prepared statements.
102
- - [D1 internals](/docs/d1-internals) — D1 uses the same normalize-then-resolve pattern as KV, but compiles to Wrangler `d1_databases` and exposes a relational local runtime surface.
103
- - [Testing D1](/docs/d1-testing) — D1 is one of the easiest bindings to test meaningfully with Devflare because the local runtime already speaks the same database API your worker uses.
104
- - [D1 example](/docs/d1-example) — This starter example keeps D1 focused on one job: answer a single query and prove the binding works locally.
101
+ - [D1](/docs/bindings/d1) — D1 gets the same stable-name authoring story as KV, but the runtime shape is relational: `prepare`, `batch`, `exec`, and prepared statements.
102
+ - [D1 internals](/docs/bindings/d1/internals) — D1 uses the same normalize-then-resolve pattern as KV, but compiles to Wrangler `d1_databases` and exposes a relational local runtime surface.
103
+ - [Testing D1](/docs/bindings/d1/testing) — D1 is one of the easiest bindings to test meaningfully with Devflare because the local runtime already speaks the same database API your worker uses.
104
+ - [D1 example](/docs/bindings/d1/example) — This starter example keeps D1 focused on one job: answer a single query and prove the binding works locally.
105
105
 
106
106
  - **R2** — Object storage bindings with strong local support and one important rule: do not assume a browser URL contract.
107
- - [R2](/docs/r2-binding) — R2 is straightforward in config and well-supported locally, but browser-facing delivery should usually go through a Worker route instead of assuming bucket URLs.
108
- - [R2 internals](/docs/r2-internals) — R2 is simpler than KV or D1 because the authored value is already the bucket name, so there is no name-versus-id resolution dance.
109
- - [Testing R2](/docs/r2-testing) — R2 is local-friendly, which means you can test real object operations without inventing a storage adapter just to get off the ground.
110
- - [R2 example](/docs/r2-example) — This example uses one private bucket and one route, which is still the cleanest default shape for many real apps.
107
+ - [R2](/docs/bindings/r2) — R2 is straightforward in config and well-supported locally, but browser-facing delivery should usually go through a Worker route instead of assuming bucket URLs.
108
+ - [R2 internals](/docs/bindings/r2/internals) — R2 is simpler than KV or D1 because the authored value is already the bucket name, so there is no name-versus-id resolution dance.
109
+ - [Testing R2](/docs/bindings/r2/testing) — R2 is local-friendly, which means you can test real object operations without inventing a storage adapter just to get off the ground.
110
+ - [R2 example](/docs/bindings/r2/example) — This example uses one private bucket and one route, which is still the cleanest default shape for many real apps.
111
111
 
112
112
  - **Durable Objects** — Stateful coordination primitives with strong local support, cross-worker wiring, and important preview caveats.
113
- - [Durable Objects](/docs/durable-object-binding) — Devflare treats Durable Objects as a real first-class surface in config, local runtime, and tests, not as an awkward plugin hanging off the side of the worker.
114
- - [Durable Objects internals](/docs/durable-object-internals) — Durable Object bindings normalize into a stable binding shape, compile into Wrangler `durable_objects.bindings`, and participate in Devflare’s own DO bundling path.
115
- - [Testing Durable Objects](/docs/durable-object-testing) — Durable Objects are well-supported in the default Devflare harness, which means you can test real object behavior without hand-building a fake namespace first.
116
- - [Durable Objects example](/docs/durable-object-example) — This example uses a tiny counter object because the shape is easy to understand and still proves the important DO wiring.
113
+ - [Durable Objects](/docs/bindings/durable-objects) — The fast Devflare payoff is simple: put one counter object in a `do.*` file, call it from the worker, and call the same object directly in tests.
114
+ - [Durable Objects internals](/docs/bindings/durable-objects/internals) — Durable Object bindings normalize into a stable binding shape, compile into Wrangler `durable_objects.bindings`, and participate in Devflare’s own DO bundling path.
115
+ - [Testing Durable Objects](/docs/bindings/durable-objects/testing) — Durable Objects are well-supported in the default Devflare harness, which means you can test real object behavior without hand-building a fake namespace first.
116
+ - [Durable Objects example](/docs/bindings/durable-objects/example) — This example shows the whole Durable Object story in the smallest useful shape: one auto-discovered object, one worker route, and one direct test.
117
117
 
118
118
  - **Queues** — Producer and consumer bindings for background work with a strong local trigger story.
119
- - [Queues](/docs/queue-binding) — Devflare models Queue producers and consumers explicitly, which makes local tests and preview naming much easier to reason about.
120
- - [Queues internals](/docs/queue-internals) — Queue config is compiled into explicit producer and consumer blocks, with preview resource materialization available for both queue names and DLQs.
121
- - [Testing Queues](/docs/queue-testing) — Queue testing is one of the places where Devflare’s helper surface feels especially good because the queue trigger already knows how to drive the real handler shape.
122
- - [Queues example](/docs/queue-example) — This starter example wires one producer, one consumer, and one stored result so you can see the whole queue loop without ceremony.
119
+ - [Queues](/docs/bindings/queues) — Devflare models Queue producers and consumers explicitly, which makes local tests and preview naming much easier to reason about.
120
+ - [Queues internals](/docs/bindings/queues/internals) — Queue config is compiled into explicit producer and consumer blocks, with preview resource materialization available for both queue names and DLQs.
121
+ - [Testing Queues](/docs/bindings/queues/testing) — Queue testing is one of the places where Devflare’s helper surface feels especially good because the queue trigger already knows how to drive the real handler shape.
122
+ - [Queues example](/docs/bindings/queues/example) — This starter example wires one producer, one consumer, and one stored result so you can see the whole queue loop without ceremony.
123
+
124
+ - **Services** — Worker-to-worker bindings with `ref()` support, typed env generation, and good local multi-worker tests.
125
+ - [Services](/docs/bindings/services) — The fast Devflare payoff is simple: wire one worker to another with `ref()`, call it through `env.MATH_SERVICE`, and prove the same relationship locally in one test.
126
+ - [Services internals](/docs/bindings/services/internals) — Devflare resolves referenced worker configs, bundles the linked worker surfaces, and then exposes those services as local multi-worker bindings.
127
+ - [Testing Services](/docs/bindings/services/testing) — Service bindings are one of the clearest Devflare wins in multi-worker apps: you can keep the real worker boundary and still prove it through the default local harness.
128
+ - [Services example](/docs/bindings/services/example) — This example shows the smallest useful service-binding loop: one `ref()`, one gateway route, and one local multi-worker test.
123
129
 
124
130
  - **AI** — Workers AI bindings for remote inference, with a deliberately remote-oriented testing story.
125
- - [AI](/docs/ai-binding) — AI is a supported binding in Devflare, but it is intentionally treated as remote-oriented because real model inference lives on Cloudflare infrastructure.
126
- - [AI internals](/docs/ai-internals) — AI has a smaller compiler story than storage bindings, but a more explicit auth and remote-runtime story.
127
- - [Testing AI](/docs/ai-testing) — The right AI test strategy is selective: use remote mode when you mean to test inference, and skip cleanly when the environment is not allowed to do that.
128
- - [AI example](/docs/ai-example) — This example keeps the AI path tiny: one binding, one inference call, one JSON response.
131
+ - [AI](/docs/bindings/ai) — Devflare makes Workers AI usable by keeping the binding tiny in config, the worker call obvious, and the remote smoke test explicit instead of fake.
132
+ - [AI internals](/docs/bindings/ai/internals) — AI has a smaller compiler story than storage bindings, but a more explicit auth and remote-runtime story.
133
+ - [Testing AI](/docs/bindings/ai/testing) — The right AI test strategy is selective: use remote mode when you mean to test inference, and skip cleanly when the environment is not allowed to do that.
134
+ - [AI example](/docs/bindings/ai/example) — This example keeps the AI story honest and useful: one binding, one tiny inference route, and one skip-aware remote smoke test.
129
135
 
130
136
  - **Vectorize** — Vector similarity indexes with explicit remote testing and preview-aware index naming.
131
- - [Vectorize](/docs/vectorize-binding) — Vectorize is fully modeled in Devflare config and preview naming, but meaningful tests are still remote-oriented because the index lives on Cloudflare infrastructure.
132
- - [Vectorize internals](/docs/vectorize-internals) — Vectorize compiles cleanly into Wrangler output and participates in preview resource lifecycle, but the runtime value of the binding mostly lives in remote infrastructure.
133
- - [Testing Vectorize](/docs/vectorize-testing) — The right Vectorize tests are targeted remote checks: a small insert or query, a clear skip condition, and a real index behind the binding.
134
- - [Vectorize example](/docs/vectorize-example) — This example keeps Vectorize honest: one index binding, one upsert, and one query against the same worker path.
137
+ - [Vectorize](/docs/bindings/vectorize) — Devflare makes Vectorize usable by keeping the index name explicit in config, preview naming honest, and the real smoke test explicit instead of buried under mocks.
138
+ - [Vectorize internals](/docs/bindings/vectorize/internals) — Vectorize compiles cleanly into Wrangler output and participates in preview resource lifecycle, but the runtime value of the binding mostly lives in remote infrastructure.
139
+ - [Testing Vectorize](/docs/bindings/vectorize/testing) — The right Vectorize tests are targeted remote checks: a small insert or query, a clear skip condition, and a real index behind the binding.
140
+ - [Vectorize example](/docs/bindings/vectorize/example) — This example keeps Vectorize honest and usable: one index binding, one upsert-and-query route, and one skip-aware remote smoke test.
135
141
 
136
142
  - **Hyperdrive** — PostgreSQL-oriented bindings with schema support, name resolution, and a narrower proven local story than D1 or KV.
137
- - [Hyperdrive](/docs/hyperdrive-binding) — Hyperdrive is modeled in Devflare config and compile flows like other name-based resources, but its tested local ergonomics are thinner than D1 or KV.
138
- - [Hyperdrive internals](/docs/hyperdrive-internals) — Hyperdrive uses the same normalize-and-resolve pattern as KV and D1, but preview lifecycle includes a fallback path instead of guaranteed preview cloning.
139
- - [Testing Hyperdrive](/docs/hyperdrive-testing) — Hyperdrive testing should start smaller and more cautiously than D1 testing: prove the binding exists, then add targeted integration where the real database path matters.
140
- - [Hyperdrive example](/docs/hyperdrive-example) — This example keeps Hyperdrive focused on one thing: prove the binding exists and expose the connection information your app will need next.
143
+ - [Hyperdrive](/docs/bindings/hyperdrive) — Hyperdrive is modeled in Devflare config and compile flows like other name-based resources, but its tested local ergonomics are thinner than D1 or KV.
144
+ - [Hyperdrive internals](/docs/bindings/hyperdrive/internals) — Hyperdrive uses the same normalize-and-resolve pattern as KV and D1, but preview lifecycle includes a fallback path instead of guaranteed preview cloning.
145
+ - [Testing Hyperdrive](/docs/bindings/hyperdrive/testing) — Hyperdrive testing should start smaller and more cautiously than D1 testing: prove the binding exists, then add targeted integration where the real database path matters.
146
+ - [Hyperdrive example](/docs/bindings/hyperdrive/example) — This example keeps Hyperdrive focused on one thing: prove the binding exists and expose the connection information your app will need next.
141
147
 
142
148
  - **Browser Rendering** — Headless browser support with an explicit single-binding limit and a stronger dev-server story than test-helper story.
143
- - [Browser Rendering](/docs/browser-binding) — Devflare supports Browser Rendering, but there is exactly one browser binding today, and the best-supported local story lives in dev-server and integration flows.
144
- - [Browser Rendering internals](/docs/browser-internals) — Browser Rendering support in Devflare is more than a config pass-through: the dev server starts a browser shim and a binding worker that line up with Cloudflare and puppeteer expectations.
145
- - [Testing Browser Rendering](/docs/browser-testing) — Browser tests should usually be integration-flavored: either drive the worker in dev or exercise a thin smoke path that proves the binding can launch and fetch.
146
- - [Browser Rendering example](/docs/browser-example) — This example shows the real browser shape most people care about: launch a browser, read one page title, close the browser cleanly.
149
+ - [Browser Rendering](/docs/bindings/browser-rendering) — Browser Rendering shines in Devflare’s bridge-backed dev story: keep one browser binding, one narrow worker route, and one smoke path that proves launch works.
150
+ - [Browser Rendering internals](/docs/bindings/browser-rendering/internals) — Browser Rendering support in Devflare is more than a config pass-through: the dev server starts a browser shim and a binding worker that line up with Cloudflare and puppeteer expectations.
151
+ - [Testing Browser Rendering](/docs/bindings/browser-rendering/testing) — Browser tests should usually be integration-flavored: either drive the worker in dev or exercise a thin smoke path that proves the binding can launch and fetch.
152
+ - [Browser Rendering example](/docs/bindings/browser-rendering/example) — This example shows the real browser path people actually need: one binding, one title-read route, and one smoke check through the dev server.
147
153
 
148
154
  - **Analytics Engine** — Dataset bindings for writeDataPoint-style event recording with schema support and lighter local testing guidance.
149
- - [Analytics Engine](/docs/analytics-engine-binding) — Analytics Engine is modeled cleanly in Devflare config and generated types, but the repo evidence points to a lighter local story than the first-class storage bindings.
150
- - [Analytics Engine internals](/docs/analytics-engine-internals) — Analytics Engine has a straightforward compiler story, plus a preview note that matters because datasets are auto-created on first write instead of provisioned like buckets or databases.
151
- - [Testing Analytics Engine](/docs/analytics-engine-testing) — Analytics Engine tests should stay thin: verify that the worker writes a data point, not that you can recreate Cloudflare analytics locally.
152
- - [Analytics Engine example](/docs/analytics-engine-example) — This example writes one analytics event from one route, which is usually all you need to teach the binding shape clearly.
155
+ - [Analytics Engine](/docs/bindings/analytics-engine) — Analytics Engine is modeled cleanly in Devflare config and generated types, but the repo evidence points to a lighter local story than the first-class storage bindings.
156
+ - [Analytics Engine internals](/docs/bindings/analytics-engine/internals) — Analytics Engine has a straightforward compiler story, plus a preview note that matters because datasets are auto-created on first write instead of provisioned like buckets or databases.
157
+ - [Testing Analytics Engine](/docs/bindings/analytics-engine/testing) — Analytics Engine tests should stay thin: verify that the worker writes a data point, not that you can recreate Cloudflare analytics locally.
158
+ - [Analytics Engine example](/docs/bindings/analytics-engine/example) — This example writes one analytics event from one route, which is usually all you need to teach the binding shape clearly.
153
159
 
154
160
  - **Send Email** — Outbound email bindings with real local support, plus an important distinction from inbound email event handlers.
155
- - [Send Email](/docs/send-email-binding) — Send Email is a real binding surface in Devflare, and it is worth documenting separately from inbound `src/email.ts` handlers so the two flows do not get blurred together.
156
- - [Send Email internals](/docs/send-email-internals) — Send Email compiles into Wrangler output, normalizes message input at runtime, and supports local address restrictions instead of treating email as an unbounded free-for-all.
157
- - [Testing Send Email](/docs/send-email-testing) — Send Email is stronger locally than many platform-service bindings because outbound email can be exercised in the default harness, while inbound email has its own related helper surface.
158
- - [Send Email example](/docs/send-email-example) — This example keeps outbound email explicit: one binding, one recipient rule, one worker path that sends one message.
161
+ - [Send Email](/docs/bindings/send-email) — Send Email is a real binding surface in Devflare, and it is worth documenting separately from inbound `src/email.ts` handlers so the two flows do not get blurred together.
162
+ - [Send Email internals](/docs/bindings/send-email/internals) — Send Email compiles into Wrangler output, normalizes message input at runtime, and supports local address restrictions instead of treating email as an unbounded free-for-all.
163
+ - [Testing Send Email](/docs/bindings/send-email/testing) — Send Email is stronger locally than many platform-service bindings because outbound email can be exercised in the default harness, while inbound email has its own related helper surface.
164
+ - [Send Email example](/docs/bindings/send-email/example) — This example keeps outbound email explicit: one binding, one recipient rule, one worker path that sends one message.
159
165
 
160
166
  ## Full documentation
161
167
 
@@ -303,10 +309,10 @@ Hover a label to see what it means for config, local runtime, tests, previews, a
303
309
  - **KV, D1, and R2** — Devflare gives the main storage bindings a strong local-first story: readable config, generated env typing, local runtime behavior, and realistic tests without losing the Cloudflare shape. ([link](/docs/storage-bindings))
304
310
  - **Durable Objects and queues** — Stateful objects and deferred work are treated as real worker surfaces, with config discovery, local runtime wrappers, and test helpers that match the application boundary. ([link](/docs/durable-objects-and-queues))
305
311
  - **Service bindings and worker composition** — Service bindings and `ref()` let worker-to-worker dependencies stay explicit enough for local multi-worker runtime, generated types, and real tests through the same env surface the app uses. ([link](/docs/multi-workers))
306
- - **Hyperdrive** — Hyperdrive is modeled cleanly in config and generated output, but the local and preview ergonomics are more constrained than KV, D1, or R2 because the real database and credentials stay remote. ([link](/docs/hyperdrive-binding))
307
- - **Workers AI** — The AI binding is supported in config, types, and deployment flows, but meaningful tests are remote-oriented because real inference still lives on Cloudflare infrastructure. ([link](/docs/ai-binding))
308
- - **Vectorize** — Vectorize is fully modeled in config and preview-aware naming, but real inserts and similarity queries still need remote infrastructure and honest remote-mode tests. ([link](/docs/vectorize-binding))
309
- - **Browser Rendering** — Browser Rendering is fully supported through Devflare's bridge-backed local dev story, config model, generated typing, and runtime integration. The main platform caveat is still the Cloudflare one: exactly one browser binding. ([link](/docs/browser-binding))
312
+ - **Hyperdrive** — Hyperdrive is modeled cleanly in config and generated output, but the local and preview ergonomics are more constrained than KV, D1, or R2 because the real database and credentials stay remote. ([link](/docs/bindings/hyperdrive))
313
+ - **Workers AI** — The AI binding is supported in config, types, and deployment flows, but meaningful tests are remote-oriented because real inference still lives on Cloudflare infrastructure. ([link](/docs/bindings/ai))
314
+ - **Vectorize** — Vectorize is fully modeled in config and preview-aware naming, but real inserts and similarity queries still need remote infrastructure and honest remote-mode tests. ([link](/docs/bindings/vectorize))
315
+ - **Browser Rendering** — Browser Rendering is fully supported through Devflare's bridge-backed local dev story, config model, generated typing, and runtime integration. The main platform caveat is still the Cloudflare one: exactly one browser binding. ([link](/docs/bindings/browser-rendering))
310
316
 
311
317
  #### What Devflare adds on top of raw Cloudflare workflows
312
318
 
@@ -943,9 +949,9 @@ Once one tiny example works locally, jump to the dedicated binding guides for th
943
949
 
944
950
  ##### Highlights
945
951
 
946
- - **Durable Objects guide** — Read the fuller guidance on stateful objects, migrations, previews, and local testing. ([link](/docs/durable-object-binding))
947
- - **R2 guide** — Open the deeper R2 page for delivery boundaries, testing patterns, and storage architecture choices. ([link](/docs/r2-binding))
948
- - **Browser Rendering guide** — Open the browser guide when you need the single-binding caveat, dev-server details, or heavier browser workflows. ([link](/docs/browser-binding))
952
+ - **Durable Objects guide** — Read the fuller guidance on stateful objects, migrations, previews, and local testing. ([link](/docs/bindings/durable-objects))
953
+ - **R2 guide** — Open the deeper R2 page for delivery boundaries, testing patterns, and storage architecture choices. ([link](/docs/bindings/r2))
954
+ - **Browser Rendering guide** — Open the browser guide when you need the single-binding caveat, dev-server details, or heavier browser workflows. ([link](/docs/bindings/browser-rendering))
949
955
 
950
956
  ---
951
957
 
@@ -2577,6 +2583,26 @@ This is why `config.env` is more than a raw Wrangler mirror. It can change the D
2577
2583
  | `routes`, `assets`, `limits`, `observability` | Deployment routing, static assets, CPU limits, or observability should differ by lane. |
2578
2584
  | `rolldown`, `vite`, `wrangler` | The build host or the passthrough escape hatch needs environment-specific behavior. |
2579
2585
 
2586
+ #### Environment overrides: arrays replace, objects deep-merge, primitives replace
2587
+
2588
+ Overlays compose onto the base config with three rules: object-shaped values are deep-merged key by key, primitive values (strings, numbers, booleans) are replaced wholesale, and array-shaped values are replaced wholesale (they do not append). Reading an environment block as an override of the base — not as an addition to it — keeps these rules predictable.
2589
+
2590
+ The replace-arrays rule is the one most likely to surprise someone arriving from a config system that appended arrays. If a base config sets `routes: […]` and the overlay sets `routes: […]`, the overlay’s array becomes the resolved value; the base array is not concatenated. The same applies to `migrations` and to nested arrays like `triggers.crons`.
2591
+
2592
+ ##### Reference table
2593
+
2594
+ | Field shape | Merge rule | Example |
2595
+ | --- | --- | --- |
2596
+ | `routes` (array) | Replace | Base `routes: [{ pattern: "app.example.com/*", zone_name: "example.com" }]` + overlay `routes: [{ pattern: "preview.example.com/*", zone_name: "example.com" }]` resolves to **only** the preview entry. |
2597
+ | `migrations` (array) | Replace | Base `migrations: [{ tag: "v1", new_classes: ["Room"] }]` + overlay `migrations: [{ tag: "v2", new_classes: ["Room", "User"] }]` resolves to **only** the v2 entry. To preserve history, restate the prior migrations in the overlay. |
2598
+ | `triggers.crons` (array under nested object) | Replace at the array level (the parent `triggers` object is still deep-merged) | Base `triggers: { crons: ["*/5 * * * *"] }` + overlay `triggers: { crons: ["0 * * * *"] }` resolves to `triggers.crons = ["0 * * * *"]`. Other keys on `triggers` deep-merge as usual. |
2599
+ | `bindings` (object) | Deep-merge | Adding `bindings.kv.NEW_NS` in an overlay extends the base `bindings.kv` map; existing namespaces survive unless the overlay names the same key. |
2600
+ | `name`, `compatibility_date` (primitive) | Replace | The overlay value wins when present; otherwise the base value stays. |
2601
+
2602
+ > **Warning — Arrays replace, they do not append**
2603
+ >
2604
+ > If you only want to add one extra route, one extra cron, or one extra migration to the base, the overlay must restate the base entries alongside the new one. An overlay that lists only the new entry will silently drop the base entries from the resolved config.
2605
+
2580
2606
  #### Choose the environment where it matters, and let explicit deploy targets do the rest
2581
2607
 
2582
2608
  ##### Steps
@@ -3903,17 +3929,18 @@ That is great once you already opened the right binding page. This index is for
3903
3929
 
3904
3930
  ##### Highlights
3905
3931
 
3906
- - **Testing KV** — Use the default test harness first. KV is one of the bindings Devflare supports best in local tests. Open the KV overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/kv-testing))
3907
- - **Testing D1** — D1 is one of the easiest bindings to test meaningfully with Devflare because the local runtime already speaks the same database API your worker uses. Open the D1 overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/d1-testing))
3908
- - **Testing R2** — R2 is local-friendly, which means you can test real object operations without inventing a storage adapter just to get off the ground. Open the R2 overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/r2-testing))
3909
- - **Testing Durable Objects** — Durable Objects are well-supported in the default Devflare harness, which means you can test real object behavior without hand-building a fake namespace first. Open the Durable Objects overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/durable-object-testing))
3910
- - **Testing Queues** — Queue testing is one of the places where Devflare’s helper surface feels especially good because the queue trigger already knows how to drive the real handler shape. Open the Queues overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/queue-testing))
3911
- - **Testing AI** — The right AI test strategy is selective: use remote mode when you mean to test inference, and skip cleanly when the environment is not allowed to do that. Open the AI overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/ai-testing))
3912
- - **Testing Vectorize** — The right Vectorize tests are targeted remote checks: a small insert or query, a clear skip condition, and a real index behind the binding. Open the Vectorize overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/vectorize-testing))
3913
- - **Testing Hyperdrive** — Hyperdrive testing should start smaller and more cautiously than D1 testing: prove the binding exists, then add targeted integration where the real database path matters. Open the Hyperdrive overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/hyperdrive-testing))
3914
- - **Testing Browser Rendering** — Browser tests should usually be integration-flavored: either drive the worker in dev or exercise a thin smoke path that proves the binding can launch and fetch. Open the Browser Rendering overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/browser-testing))
3915
- - **Testing Analytics Engine** — Analytics Engine tests should stay thin: verify that the worker writes a data point, not that you can recreate Cloudflare analytics locally. Open the Analytics Engine overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/analytics-engine-testing))
3916
- - **Testing Send Email** — Send Email is stronger locally than many platform-service bindings because outbound email can be exercised in the default harness, while inbound email has its own related helper surface. Open the Send Email overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/send-email-testing))
3932
+ - **Testing KV** — Use the default test harness first. KV is one of the bindings Devflare supports best in local tests. Open the KV overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/bindings/kv/testing))
3933
+ - **Testing D1** — D1 is one of the easiest bindings to test meaningfully with Devflare because the local runtime already speaks the same database API your worker uses. Open the D1 overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/bindings/d1/testing))
3934
+ - **Testing R2** — R2 is local-friendly, which means you can test real object operations without inventing a storage adapter just to get off the ground. Open the R2 overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/bindings/r2/testing))
3935
+ - **Testing Durable Objects** — Durable Objects are well-supported in the default Devflare harness, which means you can test real object behavior without hand-building a fake namespace first. Open the Durable Objects overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/bindings/durable-objects/testing))
3936
+ - **Testing Queues** — Queue testing is one of the places where Devflare’s helper surface feels especially good because the queue trigger already knows how to drive the real handler shape. Open the Queues overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/bindings/queues/testing))
3937
+ - **Testing Services** — Service bindings are one of the clearest Devflare wins in multi-worker apps: you can keep the real worker boundary and still prove it through the default local harness. Open the Services overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/bindings/services/testing))
3938
+ - **Testing AI** — The right AI test strategy is selective: use remote mode when you mean to test inference, and skip cleanly when the environment is not allowed to do that. Open the AI overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/bindings/ai/testing))
3939
+ - **Testing Vectorize** — The right Vectorize tests are targeted remote checks: a small insert or query, a clear skip condition, and a real index behind the binding. Open the Vectorize overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/bindings/vectorize/testing))
3940
+ - **Testing Hyperdrive** — Hyperdrive testing should start smaller and more cautiously than D1 testing: prove the binding exists, then add targeted integration where the real database path matters. Open the Hyperdrive overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/bindings/hyperdrive/testing))
3941
+ - **Testing Browser Rendering** — Browser tests should usually be integration-flavored: either drive the worker in dev or exercise a thin smoke path that proves the binding can launch and fetch. Open the Browser Rendering overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/bindings/browser-rendering/testing))
3942
+ - **Testing Analytics Engine** — Analytics Engine tests should stay thin: verify that the worker writes a data point, not that you can recreate Cloudflare analytics locally. Open the Analytics Engine overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/bindings/analytics-engine/testing))
3943
+ - **Testing Send Email** — Send Email is stronger locally than many platform-service bindings because outbound email can be exercised in the default harness, while inbound email has its own related helper surface. Open the Send Email overview first when you need the full binding story, or jump straight here when the only open question is how to test it. ([link](/docs/bindings/send-email/testing))
3917
3944
 
3918
3945
  #### The testing posture is not identical for every binding
3919
3946
 
@@ -3926,6 +3953,7 @@ That is great once you already opened the right binding page. This index is for
3926
3953
  | R2 | First-class local runtime and tests | `createTestContext()` with `env.ASSETS` or `cf.worker.fetch()` |
3927
3954
  | Durable Objects | First-class local runtime and tests, including cross-worker references | `createTestContext()` with the real DO namespace in `env` |
3928
3955
  | Queues | First-class local runtime and queue-trigger tests | `createTestContext()` plus `cf.queue.trigger()` |
3956
+ | Services | First-class local runtime and multi-worker tests | `createTestContext()` plus `env.MY_SERVICE` |
3929
3957
  | AI | Remote-oriented; local tests require remote mode | `createTestContext()` after remote mode is enabled, plus `shouldSkip.ai` |
3930
3958
  | Vectorize | Remote-oriented; local tests require remote mode or explicit mocks | `createTestContext()` in remote mode plus `shouldSkip.vectorize` |
3931
3959
  | Hyperdrive | Supported, but with a narrower proven local test story | `createTestContext()` plus small binding or smoke checks |
@@ -4168,7 +4196,7 @@ That means you should think in terms of host ownership, not a separate CLI mode.
4168
4196
 
4169
4197
  ### Compose Devflare with SvelteKit by letting SvelteKit host the app and Devflare supply the Worker platform
4170
4198
 
4171
- > Point Devflare at SvelteKits Cloudflare worker output—often via `files.fetch`, but sometimes by handing `wrangler.passthrough.main` the adapter worker directly—keep `sveltekit()` in `vite.config.ts`, and compose `devflare/sveltekit` into `src/hooks.server.ts` so local platform bindings line up with the Worker runtime Devflare manages.
4199
+ > Hand SvelteKit's Cloudflare adapter output to Devflare via `wrangler.passthrough.main` (the adapter worker is a build artifact and does not exist until `vite build` runs), keep `sveltekit()` in `vite.config.ts`, and compose `devflare/sveltekit` into `src/hooks.server.ts` so local platform bindings line up with the Worker runtime Devflare manages.
4172
4200
 
4173
4201
  | Field | Value |
4174
4202
  | --- | --- |
@@ -4184,14 +4212,16 @@ This is the path for full SvelteKit apps where the framework owns the outer shel
4184
4212
  | Fact | Value |
4185
4213
  | --- | --- |
4186
4214
  | Best for | Full SvelteKit apps that deploy through Devflare |
4187
- | Worker entry | The adapter worker output your package actually emits, commonly `.svelte-kit/cloudflare/_worker.js` or a repo-specific path such as `.adapter-cloudflare/_worker.js` |
4215
+ | Worker entry | The adapter worker output your package actually emits, commonly `.svelte-kit/cloudflare/_worker.js` or a repo-specific path such as `.adapter-cloudflare/_worker.js`, wired via `wrangler.passthrough.main` |
4188
4216
  | Hook helper | `devflare/sveltekit` |
4189
4217
 
4190
4218
  #### Wire the SvelteKit package like a SvelteKit app first
4191
4219
 
4192
4220
  SvelteKit still owns the app shell, routing, and framework build. Devflare plugs Worker-aware config, generated Wrangler output, and any Durable Object discovery into that Vite-driven flow.
4193
4221
 
4194
- Keep Devflare aligned with the adapter output your package actually emits. Many packages do that with `files.fetch` and an adapter default such as `.svelte-kit/cloudflare/_worker.js`. The documentation app in this repository instead points `wrangler.passthrough.main` at its configured `.adapter-cloudflare/_worker.js` output, which is equally valid when the package already owns the adapter worker directly.
4222
+ The adapter worker is a **build artifact** — `@sveltejs/adapter-cloudflare` only writes `.svelte-kit/cloudflare/_worker.js` (or your repo's equivalent, like `.adapter-cloudflare/_worker.js`) during `vite build`. Devflare resolves handler paths *before* the framework build runs, so pointing `files.fetch` at that path fails on a clean checkout with `Configured fetch handler "…" was not found`. Use `wrangler.passthrough.main` instead: devflare skips composition entirely for the worker entry, and wrangler picks up the adapter output post-build.
4223
+
4224
+ If you also have queue handlers, scheduled handlers, durable objects, or routes, keep those in `files.queue` / `files.scheduled` / `files.durableObjects` / `files.routes` as normal source files — composition still applies to those surfaces.
4195
4225
 
4196
4226
  ##### Example — `devflare.config.ts`
4197
4227
 
@@ -4201,8 +4231,16 @@ import { defineConfig } from 'devflare/config'
4201
4231
  export default defineConfig({
4202
4232
  name: 'notes-app',
4203
4233
  files: {
4204
- fetch: '.svelte-kit/cloudflare/_worker.js',
4234
+ // fetch is supplied by SvelteKit's adapter output below;
4235
+ // keep this false so devflare does not try to compose around an unbuilt artifact.
4236
+ fetch: false,
4205
4237
  durableObjects: 'src/do/**/*.ts'
4238
+ },
4239
+ wrangler: {
4240
+ passthrough: {
4241
+ // SvelteKit's @sveltejs/adapter-cloudflare writes this file during vite build.
4242
+ main: '.svelte-kit/cloudflare/_worker.js'
4243
+ }
4206
4244
  }
4207
4245
  })
4208
4246
  ```
@@ -5446,10 +5484,10 @@ export async function GET({ env, params }: FetchEvent<DevflareEnv>): Promise<Res
5446
5484
 
5447
5485
  ##### Highlights
5448
5486
 
5449
- - **KV** — Open the KV guide when the storage shape is keyed lookup, cache-like state, or namespace lifecycle. ([link](/docs/kv-binding))
5450
- - **D1** — Open the D1 guide when the storage shape is query-driven and you need the actual SQL-shaped runtime contract. ([link](/docs/d1-binding))
5451
- - **R2** — Open the R2 guide when the real question is bucket usage, testing, preview naming, or file delivery details. ([link](/docs/r2-binding))
5452
- - **Hyperdrive** — Open the Hyperdrive guide when the worker is reaching an existing PostgreSQL system and the operational caveats matter more than the storage taxonomy. ([link](/docs/hyperdrive-binding))
5487
+ - **KV** — Open the KV guide when the storage shape is keyed lookup, cache-like state, or namespace lifecycle. ([link](/docs/bindings/kv))
5488
+ - **D1** — Open the D1 guide when the storage shape is query-driven and you need the actual SQL-shaped runtime contract. ([link](/docs/bindings/d1))
5489
+ - **R2** — Open the R2 guide when the real question is bucket usage, testing, preview naming, or file delivery details. ([link](/docs/bindings/r2))
5490
+ - **Hyperdrive** — Open the Hyperdrive guide when the worker is reaching an existing PostgreSQL system and the operational caveats matter more than the storage taxonomy. ([link](/docs/bindings/hyperdrive))
5453
5491
 
5454
5492
  ---
5455
5493
 
@@ -5585,7 +5623,7 @@ export async function GET({ env, params }: FetchEvent<DevflareEnv>): Promise<Res
5585
5623
 
5586
5624
  ##### Highlights
5587
5625
 
5588
- - **R2 binding guide** — Open this once the architecture choice is done and the next question is the exact binding shape, local runtime behavior, or testing posture. ([link](/docs/r2-binding))
5626
+ - **R2 binding guide** — Open this once the architecture choice is done and the next question is the exact binding shape, local runtime behavior, or testing posture. ([link](/docs/bindings/r2))
5589
5627
  - **Preview-scoped bindings** — Open this when preview deployments should own separate buckets or other disposable infrastructure that can be cleaned up by scope later. ([link](/docs/config-previews))
5590
5628
  - **createTestContext()** — Open this when the next question is how the local worker-shaped test harness exposes real R2 bindings and helper surfaces. ([link](/docs/create-test-context))
5591
5629
 
@@ -5709,8 +5747,8 @@ export default defineConfig({
5709
5747
 
5710
5748
  ##### Highlights
5711
5749
 
5712
- - **Durable Objects** — Open the Durable Objects guide for the real binding shape, local tests, migrations, and preview caveats. ([link](/docs/durable-object-binding))
5713
- - **Queues** — Open the Queues guide for producer and consumer authoring, queue tests, and preview resource lifecycle details. ([link](/docs/queue-binding))
5750
+ - **Durable Objects** — Open the Durable Objects guide for the real binding shape, local tests, migrations, and preview caveats. ([link](/docs/bindings/durable-objects))
5751
+ - **Queues** — Open the Queues guide for producer and consumer authoring, queue tests, and preview resource lifecycle details. ([link](/docs/bindings/queues))
5714
5752
 
5715
5753
  ---
5716
5754
 
@@ -5725,7 +5763,7 @@ export default defineConfig({
5725
5763
  | Navigation title | Worker composition |
5726
5764
  | Eyebrow | Composition |
5727
5765
 
5728
- The service-binding reference pages can explain the mechanics. This page exists for the composition question: when should another worker exist at all, how do you keep the boundary explicit, and which docs own the deeper service details once you commit to it?
5766
+ The Services guide can explain the mechanics. This page exists for the composition question: when should another worker exist at all, how do you keep the boundary explicit, and which docs own the deeper service details once you commit to it?
5729
5767
 
5730
5768
  #### At a glance
5731
5769
 
@@ -5740,7 +5778,7 @@ The service-binding reference pages can explain the mechanics. This page exists
5740
5778
 
5741
5779
  The goal is not to split one worker just because the file count went up. The goal is to give a real runtime boundary a real worker boundary, then let service bindings make that relationship explicit enough for tooling and review.
5742
5780
 
5743
- That means this page should answer the architecture choice first. The service-binding guide can take over once the answer is already “yes, another worker should exist.”
5781
+ That means this page should answer the architecture choice first. The Services guide can take over once the answer is already “yes, another worker should exist.”
5744
5782
 
5745
5783
  ##### Reference table
5746
5784
 
@@ -5758,20 +5796,20 @@ That means this page should answer the architecture choice first. The service-bi
5758
5796
 
5759
5797
  If another worker is real, the relationship belongs in config instead of in copied worker names or half-remembered script references. `ref()` gives Devflare enough structure to follow the dependency into local runtime, generated env types, and compiled output.
5760
5798
 
5761
- Keep the architecture example simple: one referenced worker and one explicit service binding are enough to show the boundary. Named entrypoints are real too, but the service-binding and generated-types pages own that deeper contract once the worker boundary itself is already justified.
5799
+ Keep the architecture example simple: one referenced worker and one explicit service binding are enough to show the boundary. Named entrypoints are real too, but the Services and generated-types pages own that deeper contract once the worker boundary itself is already justified.
5762
5800
 
5763
5801
  ##### Example — Model the worker family with `ref()` and one explicit service binding
5764
5802
 
5765
5803
  ```ts
5766
5804
  import { defineConfig, ref } from 'devflare/config'
5767
5805
 
5768
- const mathWorker = ref(() => import('../math-service/devflare.config'))
5806
+ const mathWorker = ref(() => import('../math-service/devflare.config'))
5769
5807
 
5770
5808
  export default defineConfig({
5771
5809
  name: 'gateway',
5772
5810
  bindings: {
5773
5811
  services: {
5774
- MATH_SERVICE: mathWorker.worker
5812
+ MATH_SERVICE: mathWorker.worker
5775
5813
  }
5776
5814
  }
5777
5815
  })
@@ -5809,8 +5847,8 @@ test('service binding calls the default worker export', async () => {
5809
5847
 
5810
5848
  ##### Highlights
5811
5849
 
5812
- - **Service binding guide** — Open the service guide for the exact binding shape, env typing, and compiler behavior once another worker is definitely the right boundary. ([link](/docs/service-binding))
5813
- - **Testing Services** — Open the service testing guide when the next question is the right default harness or how to test named entrypoints accurately. ([link](/docs/service-testing))
5850
+ - **Services guide** — Open the service guide for the exact binding shape, env typing, and compiler behavior once another worker is definitely the right boundary. ([link](/docs/bindings/services))
5851
+ - **Testing Services** — Open the service testing guide when the next question is the right default harness or how to test named entrypoints accurately. ([link](/docs/bindings/services/testing))
5814
5852
  - **Generated types** — Open this page when `ref()` relationships, named entrypoints, or `defineConfig<Entrypoints>()` typing becomes the real question. ([link](/docs/generated-types))
5815
5853
  - **Preview strategies** — Open the preview page when the worker family needs real isolation and the naming model is the release question now. ([link](/docs/preview-strategies))
5816
5854
  - **Testing overview** — Use the testing map when the next question is broader than service bindings alone. ([link](/docs/testing-overview))
@@ -5823,7 +5861,7 @@ test('service binding calls the default worker export', async () => {
5823
5861
 
5824
5862
  | Field | Value |
5825
5863
  | --- | --- |
5826
- | Route | [`/docs/kv-binding`](/docs/kv-binding) |
5864
+ | Route | [`/docs/bindings/kv`](/docs/bindings/kv) |
5827
5865
  | Group | Bindings |
5828
5866
  | Navigation title | KV |
5829
5867
  | Eyebrow | Binding reference |
@@ -5901,9 +5939,9 @@ Cloudflare Workers KV docs is the platform reference. This page is the Devflare
5901
5939
 
5902
5940
  ##### Highlights
5903
5941
 
5904
- - **KV internals** — See normalization, Wrangler `kv_namespaces`, and the preview or runtime details behind the authored shape. ([link](/docs/kv-internals))
5905
- - **Testing KV** — Start from `createTestContext()` plus `env.CACHE` or `cf.worker.fetch()` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/kv-testing))
5906
- - **KV example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/kv-example))
5942
+ - **KV internals** — See normalization, Wrangler `kv_namespaces`, and the preview or runtime details behind the authored shape. ([link](/docs/bindings/kv/internals))
5943
+ - **Testing KV** — Start from `createTestContext()` plus `env.CACHE` or `cf.worker.fetch()` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/bindings/kv/testing))
5944
+ - **KV example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/bindings/kv/example))
5907
5945
 
5908
5946
  ---
5909
5947
 
@@ -5913,7 +5951,7 @@ Cloudflare Workers KV docs is the platform reference. This page is the Devflare
5913
5951
 
5914
5952
  | Field | Value |
5915
5953
  | --- | --- |
5916
- | Route | [`/docs/kv-internals`](/docs/kv-internals) |
5954
+ | Route | [`/docs/bindings/kv/internals`](/docs/bindings/kv/internals) |
5917
5955
  | Group | Bindings |
5918
5956
  | Navigation title | KV internals |
5919
5957
  | Eyebrow | Under the hood |
@@ -5993,7 +6031,7 @@ export default defineConfig({
5993
6031
 
5994
6032
  | Field | Value |
5995
6033
  | --- | --- |
5996
- | Route | [`/docs/kv-testing`](/docs/kv-testing) |
6034
+ | Route | [`/docs/bindings/kv/testing`](/docs/bindings/kv/testing) |
5997
6035
  | Group | Bindings |
5998
6036
  | Navigation title | Testing KV |
5999
6037
  | Eyebrow | Testing |
@@ -6058,7 +6096,7 @@ test('stores and reads a cache value', async () => {
6058
6096
 
6059
6097
  | Field | Value |
6060
6098
  | --- | --- |
6061
- | Route | [`/docs/kv-example`](/docs/kv-example) |
6099
+ | Route | [`/docs/bindings/kv/example`](/docs/bindings/kv/example) |
6062
6100
  | Group | Bindings |
6063
6101
  | Navigation title | KV example |
6064
6102
  | Eyebrow | Starter example |
@@ -6148,7 +6186,7 @@ test('writes and reads through the worker', async () => {
6148
6186
 
6149
6187
  | Field | Value |
6150
6188
  | --- | --- |
6151
- | Route | [`/docs/d1-binding`](/docs/d1-binding) |
6189
+ | Route | [`/docs/bindings/d1`](/docs/bindings/d1) |
6152
6190
  | Group | Bindings |
6153
6191
  | Navigation title | D1 |
6154
6192
  | Eyebrow | Binding reference |
@@ -6226,9 +6264,9 @@ Cloudflare D1 docs is the platform reference. This page is the Devflare translat
6226
6264
 
6227
6265
  ##### Highlights
6228
6266
 
6229
- - **D1 internals** — See normalization, Wrangler `d1_databases`, and the preview or runtime details behind the authored shape. ([link](/docs/d1-internals))
6230
- - **Testing D1** — Start from `createTestContext()` with `env.DB` or `cf.worker.fetch()` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/d1-testing))
6231
- - **D1 example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/d1-example))
6267
+ - **D1 internals** — See normalization, Wrangler `d1_databases`, and the preview or runtime details behind the authored shape. ([link](/docs/bindings/d1/internals))
6268
+ - **Testing D1** — Start from `createTestContext()` with `env.DB` or `cf.worker.fetch()` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/bindings/d1/testing))
6269
+ - **D1 example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/bindings/d1/example))
6232
6270
 
6233
6271
  ---
6234
6272
 
@@ -6238,7 +6276,7 @@ Cloudflare D1 docs is the platform reference. This page is the Devflare translat
6238
6276
 
6239
6277
  | Field | Value |
6240
6278
  | --- | --- |
6241
- | Route | [`/docs/d1-internals`](/docs/d1-internals) |
6279
+ | Route | [`/docs/bindings/d1/internals`](/docs/bindings/d1/internals) |
6242
6280
  | Group | Bindings |
6243
6281
  | Navigation title | D1 internals |
6244
6282
  | Eyebrow | Under the hood |
@@ -6318,7 +6356,7 @@ export default defineConfig({
6318
6356
 
6319
6357
  | Field | Value |
6320
6358
  | --- | --- |
6321
- | Route | [`/docs/d1-testing`](/docs/d1-testing) |
6359
+ | Route | [`/docs/bindings/d1/testing`](/docs/bindings/d1/testing) |
6322
6360
  | Group | Bindings |
6323
6361
  | Navigation title | Testing D1 |
6324
6362
  | Eyebrow | Testing |
@@ -6383,7 +6421,7 @@ test('D1 answers a simple health query', async () => {
6383
6421
 
6384
6422
  | Field | Value |
6385
6423
  | --- | --- |
6386
- | Route | [`/docs/d1-example`](/docs/d1-example) |
6424
+ | Route | [`/docs/bindings/d1/example`](/docs/bindings/d1/example) |
6387
6425
  | Group | Bindings |
6388
6426
  | Navigation title | D1 example |
6389
6427
  | Eyebrow | Starter example |
@@ -6466,7 +6504,7 @@ test('GET / returns a D1-backed health response', async () => {
6466
6504
 
6467
6505
  | Field | Value |
6468
6506
  | --- | --- |
6469
- | Route | [`/docs/r2-binding`](/docs/r2-binding) |
6507
+ | Route | [`/docs/bindings/r2`](/docs/bindings/r2) |
6470
6508
  | Group | Bindings |
6471
6509
  | Navigation title | R2 |
6472
6510
  | Eyebrow | Binding reference |
@@ -6543,9 +6581,9 @@ Cloudflare R2 docs is the platform reference. This page is the Devflare translat
6543
6581
 
6544
6582
  ##### Highlights
6545
6583
 
6546
- - **R2 internals** — See normalization, Wrangler `r2_buckets`, and the preview or runtime details behind the authored shape. ([link](/docs/r2-internals))
6547
- - **Testing R2** — Start from `createTestContext()` with `env.ASSETS` or `cf.worker.fetch()` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/r2-testing))
6548
- - **R2 example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/r2-example))
6584
+ - **R2 internals** — See normalization, Wrangler `r2_buckets`, and the preview or runtime details behind the authored shape. ([link](/docs/bindings/r2/internals))
6585
+ - **Testing R2** — Start from `createTestContext()` with `env.ASSETS` or `cf.worker.fetch()` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/bindings/r2/testing))
6586
+ - **R2 example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/bindings/r2/example))
6549
6587
 
6550
6588
  ---
6551
6589
 
@@ -6555,7 +6593,7 @@ Cloudflare R2 docs is the platform reference. This page is the Devflare translat
6555
6593
 
6556
6594
  | Field | Value |
6557
6595
  | --- | --- |
6558
- | Route | [`/docs/r2-internals`](/docs/r2-internals) |
6596
+ | Route | [`/docs/bindings/r2/internals`](/docs/bindings/r2/internals) |
6559
6597
  | Group | Bindings |
6560
6598
  | Navigation title | R2 internals |
6561
6599
  | Eyebrow | Under the hood |
@@ -6634,7 +6672,7 @@ export default defineConfig({
6634
6672
 
6635
6673
  | Field | Value |
6636
6674
  | --- | --- |
6637
- | Route | [`/docs/r2-testing`](/docs/r2-testing) |
6675
+ | Route | [`/docs/bindings/r2/testing`](/docs/bindings/r2/testing) |
6638
6676
  | Group | Bindings |
6639
6677
  | Navigation title | Testing R2 |
6640
6678
  | Eyebrow | Testing |
@@ -6700,7 +6738,7 @@ test('stores and reads an object', async () => {
6700
6738
 
6701
6739
  | Field | Value |
6702
6740
  | --- | --- |
6703
- | Route | [`/docs/r2-example`](/docs/r2-example) |
6741
+ | Route | [`/docs/bindings/r2/example`](/docs/bindings/r2/example) |
6704
6742
  | Group | Bindings |
6705
6743
  | Navigation title | R2 example |
6706
6744
  | Eyebrow | Starter example |
@@ -6791,16 +6829,16 @@ test('GET /files/hello.txt serves the stored object', async () => {
6791
6829
 
6792
6830
  ### Use Durable Objects when coordination or state really belongs with a single object identity
6793
6831
 
6794
- > Devflare treats Durable Objects as a real first-class surface in config, local runtime, and tests, not as an awkward plugin hanging off the side of the worker.
6832
+ > The fast Devflare payoff is simple: put one counter object in a `do.*` file, call it from the worker, and call the same object directly in tests.
6795
6833
 
6796
6834
  | Field | Value |
6797
6835
  | --- | --- |
6798
- | Route | [`/docs/durable-object-binding`](/docs/durable-object-binding) |
6836
+ | Route | [`/docs/bindings/durable-objects`](/docs/bindings/durable-objects) |
6799
6837
  | Group | Bindings |
6800
6838
  | Navigation title | Durable Objects |
6801
6839
  | Eyebrow | Binding reference |
6802
6840
 
6803
- That makes DO-heavy apps easier to reason about locally, but it also means you should be honest about the preview and migration caveats that come with them.
6841
+ Devflare auto-discovers `**/do.*.{ts,js}` by default, wires the Durable Object binding into the worker env, and lets tests use the same namespace without making you invent a fake DO harness first.
6804
6842
 
6805
6843
  #### At a glance
6806
6844
 
@@ -6812,26 +6850,31 @@ That makes DO-heavy apps easier to reason about locally, but it also means you s
6812
6850
 
6813
6851
  #### Author it in the simplest shape that still says what you mean
6814
6852
 
6815
- A DO binding can be as simple as a class name string when the object lives in the same worker package.
6853
+ The easiest honest starting point is one local Durable Object class and one binding that points at it by class name.
6816
6854
 
6817
- When the object lives in another worker, `ref()` keeps that relationship explicit instead of scattering script names and class names across the repo.
6855
+ If the class lives in a `do.*` file, Devflare discovers it with the default `**/do.*.{ts,js}` pattern, so the first example does not need extra DO file config.
6818
6856
 
6819
- ##### Example — Durable Object authoring in one worker
6857
+ ##### Example — Start with one discovered Durable Object and one binding
6820
6858
 
6821
6859
  ```ts
6822
6860
  import { defineConfig } from 'devflare/config'
6823
6861
 
6824
6862
  export default defineConfig({
6825
- name: 'chat-worker',
6863
+ name: 'counter-worker',
6826
6864
  files: {
6827
- durableObjects: 'src/do/**/*.ts'
6865
+ fetch: 'src/fetch.ts'
6828
6866
  },
6829
6867
  bindings: {
6830
6868
  durableObjects: {
6831
- ROOM: 'ChatRoom',
6832
- LOCK: { className: 'WriteLock' }
6869
+ COUNTER: 'Counter'
6833
6870
  }
6834
- }
6871
+ },
6872
+ migrations: [
6873
+ {
6874
+ tag: 'v1',
6875
+ new_classes: ['Counter']
6876
+ }
6877
+ ]
6835
6878
  })
6836
6879
  ```
6837
6880
 
@@ -6840,7 +6883,7 @@ export default defineConfig({
6840
6883
  ##### Key points
6841
6884
 
6842
6885
  - Use Durable Objects when state or coordination should live behind one object identity, not when you merely want a fancy singleton.
6843
- - They are a good fit for rooms, counters, distributed locks, and request serialization.
6886
+ - They are a good fit for counters, rooms, distributed locks, and request serialization.
6844
6887
  - If the state is really just data you query, D1 or KV may stay simpler and easier to preview.
6845
6888
 
6846
6889
  #### Notes worth keeping visible
@@ -6875,9 +6918,9 @@ Cloudflare Durable Objects docs is the platform reference. This page is the Devf
6875
6918
 
6876
6919
  ##### Highlights
6877
6920
 
6878
- - **Durable Objects internals** — See normalization, Wrangler `durable_objects.bindings`, and the preview or runtime details behind the authored shape. ([link](/docs/durable-object-internals))
6879
- - **Testing Durable Objects** — Start from `createTestContext()` with the real DO namespace in `env` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/durable-object-testing))
6880
- - **Durable Objects example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/durable-object-example))
6921
+ - **Durable Objects internals** — See normalization, Wrangler `durable_objects.bindings`, and the preview or runtime details behind the authored shape. ([link](/docs/bindings/durable-objects/internals))
6922
+ - **Testing Durable Objects** — Start from `createTestContext()` with the real DO namespace in `env` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/bindings/durable-objects/testing))
6923
+ - **Durable Objects example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/bindings/durable-objects/example))
6881
6924
 
6882
6925
  ---
6883
6926
 
@@ -6887,7 +6930,7 @@ Cloudflare Durable Objects docs is the platform reference. This page is the Devf
6887
6930
 
6888
6931
  | Field | Value |
6889
6932
  | --- | --- |
6890
- | Route | [`/docs/durable-object-internals`](/docs/durable-object-internals) |
6933
+ | Route | [`/docs/bindings/durable-objects/internals`](/docs/bindings/durable-objects/internals) |
6891
6934
  | Group | Bindings |
6892
6935
  | Navigation title | Durable Objects internals |
6893
6936
  | Eyebrow | Under the hood |
@@ -6918,16 +6961,21 @@ Keep the binding readable in source, then inspect only the Wrangler-facing slice
6918
6961
  import { defineConfig } from 'devflare/config'
6919
6962
 
6920
6963
  export default defineConfig({
6921
- name: 'chat-worker',
6964
+ name: 'counter-worker',
6922
6965
  files: {
6923
- durableObjects: 'src/do/**/*.ts'
6966
+ fetch: 'src/fetch.ts'
6924
6967
  },
6925
6968
  bindings: {
6926
6969
  durableObjects: {
6927
- ROOM: 'ChatRoom',
6928
- LOCK: { className: 'WriteLock' }
6970
+ COUNTER: 'Counter'
6929
6971
  }
6930
- }
6972
+ },
6973
+ migrations: [
6974
+ {
6975
+ tag: 'v1',
6976
+ new_classes: ['Counter']
6977
+ }
6978
+ ]
6931
6979
  })
6932
6980
  ```
6933
6981
 
@@ -6971,7 +7019,7 @@ export default defineConfig({
6971
7019
 
6972
7020
  | Field | Value |
6973
7021
  | --- | --- |
6974
- | Route | [`/docs/durable-object-testing`](/docs/durable-object-testing) |
7022
+ | Route | [`/docs/bindings/durable-objects/testing`](/docs/bindings/durable-objects/testing) |
6975
7023
  | Group | Bindings |
6976
7024
  | Navigation title | Testing Durable Objects |
6977
7025
  | Eyebrow | Testing |
@@ -7003,10 +7051,10 @@ beforeAll(() => createTestContext())
7003
7051
  afterAll(() => env.dispose())
7004
7052
 
7005
7053
  test('the counter object increments', async () => {
7006
- const id = env.COUNTER.idFromName('global')
7007
- const stub = env.COUNTER.get(id)
7008
- const response = await stub.fetch('https://counter/increment')
7009
- expect(await response.text()).toBe('1')
7054
+ const counter = env.COUNTER.getByName('main')
7055
+ expect(await counter.increment()).toBe(1)
7056
+ expect(await counter.increment()).toBe(2)
7057
+ expect(await counter.getValue()).toBe(2)
7010
7058
  })
7011
7059
  ```
7012
7060
 
@@ -7034,28 +7082,28 @@ test('the counter object increments', async () => {
7034
7082
 
7035
7083
  ### A small Durable Objects example you can adapt quickly
7036
7084
 
7037
- > This example uses a tiny counter object because the shape is easy to understand and still proves the important DO wiring.
7085
+ > This example shows the whole Durable Object story in the smallest useful shape: one auto-discovered object, one worker route, and one direct test.
7038
7086
 
7039
7087
  | Field | Value |
7040
7088
  | --- | --- |
7041
- | Route | [`/docs/durable-object-example`](/docs/durable-object-example) |
7089
+ | Route | [`/docs/bindings/durable-objects/example`](/docs/bindings/durable-objects/example) |
7042
7090
  | Group | Bindings |
7043
7091
  | Navigation title | Durable Objects example |
7044
7092
  | Eyebrow | Starter example |
7045
7093
 
7046
- A counter is not glamorous, but it teaches the real ingredients: one binding, one class, one namespace lookup, and one request path that exercises state.
7094
+ A counter is enough to show why Devflare is valuable here: you do not need custom DO glue just to get a real local loop. The same `env.COUNTER` namespace works in the worker and in tests.
7047
7095
 
7048
7096
  #### At a glance
7049
7097
 
7050
7098
  | Fact | Value |
7051
7099
  | --- | --- |
7052
- | Config focus | Explicit class discovery and DO binding |
7053
- | Runtime shape | Namespace lookup plus `stub.fetch()` |
7100
+ | Config focus | Auto-discovered `do.*` file plus one DO binding |
7101
+ | Runtime shape | Direct namespace method calls from the worker and the test harness |
7054
7102
  | Best use | Counters, room state, and small single-identity coordination examples |
7055
7103
 
7056
7104
  #### Start by wiring the binding clearly in config
7057
7105
 
7058
- ##### Example — Minimal Durable Object config
7106
+ ##### Example — Minimal Durable Object config using the default discovery pattern
7059
7107
 
7060
7108
  ```ts
7061
7109
  import { defineConfig } from 'devflare/config'
@@ -7063,8 +7111,7 @@ import { defineConfig } from 'devflare/config'
7063
7111
  export default defineConfig({
7064
7112
  name: 'do-example',
7065
7113
  files: {
7066
- fetch: 'src/fetch.ts',
7067
- durableObjects: 'src/do/**/*.ts'
7114
+ fetch: 'src/fetch.ts'
7068
7115
  },
7069
7116
  bindings: {
7070
7117
  durableObjects: {
@@ -7078,36 +7125,63 @@ export default defineConfig({
7078
7125
  }
7079
7126
  ]
7080
7127
  })
7128
+
7129
+ // Devflare auto-discovers src/do.counter.ts via the default:
7130
+ // durableObjects: '**/do.*.{ts,js}'
7081
7131
  ```
7082
7132
 
7083
7133
  #### Then use it in one honest runtime path
7084
7134
 
7085
7135
  ##### Key points
7086
7136
 
7087
- - This tiny shape already proves that the object class, namespace, and fetch path are wired correctly.
7088
- - Once this works, richer room or lock logic becomes a normal extension instead of a blind leap.
7137
+ - This tiny shape already proves that the object class, namespace, storage, and worker path are wired correctly.
7138
+ - Once this works, richer room, session, or lock logic becomes a normal extension instead of a blind leap.
7139
+
7140
+ ##### Example — A tiny object and one worker path
7141
+
7142
+ ###### File — src/do.counter.ts
7143
+
7144
+ ```ts
7145
+ import { DurableObject } from 'cloudflare:workers'
7146
+
7147
+ export class Counter extends DurableObject<DevflareEnv> {
7148
+ async increment(amount = 1): Promise<number> {
7149
+ const current = (await this.ctx.storage.get<number>('value')) ?? 0
7150
+ const next = current + amount
7151
+ await this.ctx.storage.put('value', next)
7152
+ return next
7153
+ }
7154
+
7155
+ async getValue(): Promise<number> {
7156
+ return (await this.ctx.storage.get<number>('value')) ?? 0
7157
+ }
7158
+ }
7159
+ ```
7089
7160
 
7090
- ##### ExampleA tiny object and fetch path
7161
+ ###### Filesrc/fetch.ts
7091
7162
 
7092
7163
  ```ts
7093
7164
  import { env } from 'devflare'
7094
7165
 
7095
- // src/do/counter.ts should increment a stored value and return the new count.
7166
+ export async function fetch(request: Request): Promise<Response> {
7167
+ const url = new URL(request.url)
7168
+ const counter = env.COUNTER.getByName('main')
7096
7169
 
7097
- export async function fetch(): Promise<Response> {
7098
- const id = env.COUNTER.idFromName('global')
7099
- const stub = env.COUNTER.get(id)
7100
- return stub.fetch('https://counter/increment')
7170
+ if (url.pathname === '/value') {
7171
+ return Response.json({ value: await counter.getValue() })
7172
+ }
7173
+
7174
+ return Response.json({ value: await counter.increment() })
7101
7175
  }
7102
7176
  ```
7103
7177
 
7104
7178
  #### Lock in the behavior with one small test or smoke path
7105
7179
 
7106
- > **Note — The tiny state machine is enough**
7180
+ > **Note — This is the valuable bit**
7107
7181
  >
7108
- > You do not need a chat app to learn Durable Objects. One counter proves the important mechanics without burying them.
7182
+ > You do not need a chat app to feel the Devflare advantage. One counter already proves that DO files, env bindings, and tests stay part of one simple loop.
7109
7183
 
7110
- ##### Example — A matching local test
7184
+ ##### Example — A direct test that shows the Devflare payoff immediately
7111
7185
 
7112
7186
  ```ts
7113
7187
  import { afterAll, beforeAll, expect, test } from 'bun:test'
@@ -7117,11 +7191,13 @@ import { env } from 'devflare'
7117
7191
  beforeAll(() => createTestContext())
7118
7192
  afterAll(() => env.dispose())
7119
7193
 
7120
- test('GET / increments the counter object', async () => {
7121
- const first = await cf.worker.get('/')
7122
- const second = await cf.worker.get('/')
7123
- expect(await first.text()).toBe('1')
7124
- expect(await second.text()).toBe('2')
7194
+ test('the same counter works directly in tests and through the worker', async () => {
7195
+ const counter = env.COUNTER.getByName('main')
7196
+ expect(await counter.increment()).toBe(1)
7197
+ expect(await counter.increment()).toBe(2)
7198
+
7199
+ const response = await cf.worker.get('/value')
7200
+ expect(await response.json()).toEqual({ value: 2 })
7125
7201
  })
7126
7202
  ```
7127
7203
 
@@ -7133,7 +7209,7 @@ test('GET / increments the counter object', async () => {
7133
7209
 
7134
7210
  | Field | Value |
7135
7211
  | --- | --- |
7136
- | Route | [`/docs/queue-binding`](/docs/queue-binding) |
7212
+ | Route | [`/docs/bindings/queues`](/docs/bindings/queues) |
7137
7213
  | Group | Bindings |
7138
7214
  | Navigation title | Queues |
7139
7215
  | Eyebrow | Binding reference |
@@ -7218,9 +7294,9 @@ Cloudflare Queues docs is the platform reference. This page is the Devflare tran
7218
7294
 
7219
7295
  ##### Highlights
7220
7296
 
7221
- - **Queues internals** — See normalization, Wrangler `queues.producers` and `queues.consumers`, and the preview or runtime details behind the authored shape. ([link](/docs/queue-internals))
7222
- - **Testing Queues** — Start from `createTestContext()` plus `cf.queue.trigger()` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/queue-testing))
7223
- - **Queues example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/queue-example))
7297
+ - **Queues internals** — See normalization, Wrangler `queues.producers` and `queues.consumers`, and the preview or runtime details behind the authored shape. ([link](/docs/bindings/queues/internals))
7298
+ - **Testing Queues** — Start from `createTestContext()` plus `cf.queue.trigger()` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/bindings/queues/testing))
7299
+ - **Queues example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/bindings/queues/example))
7224
7300
 
7225
7301
  ---
7226
7302
 
@@ -7230,7 +7306,7 @@ Cloudflare Queues docs is the platform reference. This page is the Devflare tran
7230
7306
 
7231
7307
  | Field | Value |
7232
7308
  | --- | --- |
7233
- | Route | [`/docs/queue-internals`](/docs/queue-internals) |
7309
+ | Route | [`/docs/bindings/queues/internals`](/docs/bindings/queues/internals) |
7234
7310
  | Group | Bindings |
7235
7311
  | Navigation title | Queues internals |
7236
7312
  | Eyebrow | Under the hood |
@@ -7322,7 +7398,7 @@ export default defineConfig({
7322
7398
 
7323
7399
  | Field | Value |
7324
7400
  | --- | --- |
7325
- | Route | [`/docs/queue-testing`](/docs/queue-testing) |
7401
+ | Route | [`/docs/bindings/queues/testing`](/docs/bindings/queues/testing) |
7326
7402
  | Group | Bindings |
7327
7403
  | Navigation title | Testing Queues |
7328
7404
  | Eyebrow | Testing |
@@ -7393,7 +7469,7 @@ test('queue consumer stores a processed result', async () => {
7393
7469
 
7394
7470
  | Field | Value |
7395
7471
  | --- | --- |
7396
- | Route | [`/docs/queue-example`](/docs/queue-example) |
7472
+ | Route | [`/docs/bindings/queues/example`](/docs/bindings/queues/example) |
7397
7473
  | Group | Bindings |
7398
7474
  | Navigation title | Queues example |
7399
7475
  | Eyebrow | Starter example |
@@ -7485,18 +7561,339 @@ test('queue work writes a result record', async () => {
7485
7561
 
7486
7562
  ---
7487
7563
 
7564
+ ### Use service bindings to keep multi-worker apps explicit instead of magical
7565
+
7566
+ > The fast Devflare payoff is simple: wire one worker to another with `ref()`, call it through `env.MATH_SERVICE`, and prove the same relationship locally in one test.
7567
+
7568
+ | Field | Value |
7569
+ | --- | --- |
7570
+ | Route | [`/docs/bindings/services`](/docs/bindings/services) |
7571
+ | Group | Bindings |
7572
+ | Navigation title | Services |
7573
+ | Eyebrow | Binding reference |
7574
+
7575
+ This is the clean lane for apps that genuinely need more than one worker. Devflare keeps the worker family explicit in config, resolves the referenced surface, and lets local tests use the same service binding contract instead of copied worker names or hand-built internal URLs.
7576
+
7577
+ #### At a glance
7578
+
7579
+ | Fact | Value |
7580
+ | --- | --- |
7581
+ | Config key | bindings.services |
7582
+ | Authoring shape | Record<string, { service: string; environment?: string; entrypoint?: string }> \| ref().worker(...) |
7583
+ | Best for | Multi-worker systems, internal RPC boundaries, and explicit service composition |
7584
+
7585
+ #### Author it in the simplest shape that still says what you mean
7586
+
7587
+ The easiest honest starting point is one gateway worker, one referenced worker, and one service binding in config.
7588
+
7589
+ `ref()` is especially useful because it keeps the dependency explicit while still giving Devflare enough structure to resolve, type, and boot the linked worker locally later.
7590
+
7591
+ ##### Example — Service binding authoring with `ref()`
7592
+
7593
+ ```ts
7594
+ import { defineConfig, ref } from 'devflare/config'
7595
+
7596
+ const mathService = ref(() => import('../math-service/devflare.config'))
7597
+
7598
+ export default defineConfig({
7599
+ name: 'gateway',
7600
+ bindings: {
7601
+ services: {
7602
+ MATH_SERVICE: mathService.worker,
7603
+ ADMIN: mathService.worker('AdminEntrypoint')
7604
+ }
7605
+ }
7606
+ })
7607
+ ```
7608
+
7609
+ #### When this binding fits best
7610
+
7611
+ ##### Key points
7612
+
7613
+ - Use service bindings when another worker is a real dependency, not when one large worker is merely inconvenient to think about.
7614
+ - They are a strong fit for internal APIs, admin surfaces, search workers, and explicit worker-family boundaries.
7615
+ - If the dependency is actually shared data rather than another service boundary, a direct binding like D1, KV, or DO may stay simpler.
7616
+
7617
+ #### Notes worth keeping visible
7618
+
7619
+ ##### Key points
7620
+
7621
+ - Preview isolation follows resolved worker names, not just whatever branch or alias string you passed to a deploy command.
7622
+ - Named entrypoints are modeled, but critical production wiring is still worth validating in compiled output.
7623
+ - Service bindings are references, not preview-managed account resources like KV, D1, or queues.
7624
+
7625
+ > **Note — A very good review question**
7626
+ >
7627
+ > Ask which worker names a preview will actually deploy before you assume the worker family is isolated.
7628
+
7629
+ #### Cloudflare docs vs the Devflare layer
7630
+
7631
+ Cloudflare Service bindings docs is the platform reference. This page is the Devflare translation layer: keep `bindings.services` readable in source, understand the typed env surface, and know which local, preview, or remote lane actually matches the binding.
7632
+
7633
+ ##### Highlights
7634
+
7635
+ - **Cloudflare Service bindings docs** — Platform reference for worker-to-worker bindings, service entrypoints, and the underlying runtime contract. ([link](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/))
7636
+
7637
+ ##### Reference table
7638
+
7639
+ | Question | Cloudflare docs | This Devflare page |
7640
+ | --- | --- | --- |
7641
+ | Primary focus | Platform reference for worker-to-worker bindings, service entrypoints, and the underlying runtime contract. | How to author `bindings.services`, what the runtime surface looks like, and how Services fits a Devflare project. |
7642
+ | Testing and runtime lens | Cloudflare’s docs focus on the raw binding API, product semantics, and platform limits for the binding itself. | First-class local runtime and multi-worker tests. Use the Devflare guidance when you need the honest local harness or the right remote gate instead of only the product API shape. |
7643
+ | When to open it | When you need the platform contract, limits, APIs, or account-level product details. | When you are wiring, testing, previewing, or reviewing the binding inside a Devflare app. |
7644
+
7645
+ #### Go deeper only if this one-page guide stops being enough
7646
+
7647
+ ##### Highlights
7648
+
7649
+ - **Services internals** — See normalization, Wrangler `services`, and the preview or runtime details behind the authored shape. ([link](/docs/bindings/services/internals))
7650
+ - **Testing Services** — Start from `createTestContext()` plus `env.MY_SERVICE` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/bindings/services/testing))
7651
+ - **Services example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/bindings/services/example))
7652
+
7653
+ ---
7654
+
7655
+ ### How Devflare wires Services from config to runtime
7656
+
7657
+ > Devflare resolves referenced worker configs, bundles the linked worker surfaces, and then exposes those services as local multi-worker bindings.
7658
+
7659
+ | Field | Value |
7660
+ | --- | --- |
7661
+ | Route | [`/docs/bindings/services/internals`](/docs/bindings/services/internals) |
7662
+ | Group | Bindings |
7663
+ | Navigation title | Services internals |
7664
+ | Eyebrow | Under the hood |
7665
+
7666
+ Service bindings feel more than cosmetic: the tooling follows the relationship far enough to keep local tests, type generation, and compiled output aligned.
7667
+
7668
+ #### At a glance
7669
+
7670
+ | Fact | Value |
7671
+ | --- | --- |
7672
+ | Normalization | Plain objects and `ref().worker(...)` values normalize into one service-binding model |
7673
+ | Compile target | Wrangler `services` |
7674
+ | Preview note | Preview can rewrite service names, but service bindings are not preview-managed resources like KV or D1 |
7675
+
7676
+ #### Devflare normalizes the authored shape before it does anything louder
7677
+
7678
+ Service bindings can be authored as plain binding objects or as `ref().worker(...)` results. Devflare normalizes those into one shape so compiler, type generation, and test setup can all reason about them consistently.
7679
+
7680
+ When a binding comes from `ref()`, Devflare can follow the referenced config, discover the relevant worker surface, and keep that relationship visible in local tooling.
7681
+
7682
+ ##### Example — Services from authored config to generated output
7683
+
7684
+ Keep the binding readable in source, then inspect only the Wrangler-facing slice Devflare emits when the config is compiled.
7685
+
7686
+ ###### File — devflare.config.ts
7687
+
7688
+ ```ts
7689
+ import { defineConfig, ref } from 'devflare/config'
7690
+
7691
+ const mathService = ref(() => import('../math-service/devflare.config'))
7692
+
7693
+ export default defineConfig({
7694
+ name: 'gateway',
7695
+ bindings: {
7696
+ services: {
7697
+ MATH_SERVICE: mathService.worker,
7698
+ ADMIN: mathService.worker('AdminEntrypoint')
7699
+ }
7700
+ }
7701
+ })
7702
+ ```
7703
+
7704
+ ###### File — .devflare/wrangler.jsonc
7705
+
7706
+ ```json
7707
+ {
7708
+ "services": [
7709
+ { "binding": "MATH_SERVICE", "service": "math-service" }
7710
+ ]
7711
+ }
7712
+ ```
7713
+
7714
+ #### Local runtime support depends on what Devflare can model directly
7715
+
7716
+ ##### Key points
7717
+
7718
+ - `resolveServiceBindings()` is responsible for following referenced configs and bundling the default `worker.ts` export or named entrypoints as needed.
7719
+ - Local multi-worker Miniflare wiring uses the resolved service metadata so a gateway worker can call another worker naturally in tests.
7720
+ - Type generation can emit service-specific interfaces; if that is not possible, the binding falls back to a generic `Fetcher` contract.
7721
+
7722
+ #### Compile, preview, and cleanup behavior
7723
+
7724
+ ##### Key points
7725
+
7726
+ - Compile emits the standard `services` array that Wrangler expects.
7727
+ - Preview flows can rewrite service names when the preview naming rules say they should, but there is no separate resource-provisioning lifecycle for services themselves.
7728
+ - Critical production wiring is still worth checking through `config print`, `build`, or dry-run deploy output.
7729
+
7730
+ > **Tip — This is configuration as architecture, not just syntax**
7731
+ >
7732
+ > Service bindings work well in Devflare because the relationships are explicit enough for tooling to follow, type, and test.
7733
+
7734
+ ---
7735
+
7736
+ ### Test Services the way Devflare expects it to run
7737
+
7738
+ > Service bindings are one of the clearest Devflare wins in multi-worker apps: you can keep the real worker boundary and still prove it through the default local harness.
7739
+
7740
+ | Field | Value |
7741
+ | --- | --- |
7742
+ | Route | [`/docs/bindings/services/testing`](/docs/bindings/services/testing) |
7743
+ | Group | Bindings |
7744
+ | Navigation title | Testing Services |
7745
+ | Eyebrow | Testing |
7746
+
7747
+ Start with `createTestContext()`, then call the bound service through the generated env shape. That proves the config relationship, the local worker family, and the callable contract in the same language the app itself uses.
7748
+
7749
+ #### At a glance
7750
+
7751
+ | Fact | Value |
7752
+ | --- | --- |
7753
+ | Best for | Gateway-to-service calls, entrypoint wiring, and typed multi-worker behavior |
7754
+ | Default harness | `createTestContext()` plus `env.MY_SERVICE` |
7755
+ | Escalate when | The risk is worker naming drift, preview topology, or compiled output correctness |
7756
+
7757
+ #### Start with the default test loop
7758
+
7759
+ The shortest honest test is usually one real service call through the generated env binding. That already proves the config relationship and the callable surface.
7760
+
7761
+ Keep one test for the default worker entry and one for any named entrypoint that matters operationally.
7762
+
7763
+ ##### Example — Testing a service binding through the env
7764
+
7765
+ ```ts
7766
+ import { afterAll, beforeAll, expect, test } from 'bun:test'
7767
+ import { createTestContext } from 'devflare/test'
7768
+ import { env } from 'devflare'
7769
+
7770
+ beforeAll(() => createTestContext())
7771
+ afterAll(() => env.dispose())
7772
+
7773
+ test('service binding calls the default worker export', async () => {
7774
+ expect(await env.MATH_SERVICE.add(5, 3)).toBe(8)
7775
+ })
7776
+ ```
7777
+
7778
+ #### The helper surface to remember
7779
+
7780
+ ##### Key points
7781
+
7782
+ - Use the bound env service directly when the service relationship is the thing you want to prove.
7783
+ - Keep named entrypoints explicit in tests so they do not quietly drift from the config contract.
7784
+ - Run `devflare types` whenever service entrypoints change so env autocomplete and generated types stay in sync.
7785
+
7786
+ #### When to move beyond the default harness
7787
+
7788
+ ##### Key points
7789
+
7790
+ - Local tests prove the callable relationship, not that your preview or production worker names are what you intended.
7791
+ - If the service graph is business-critical, validate compiled output before deploys as well.
7792
+ - Test naming and topology at preview or build time when those are the real failure modes.
7793
+
7794
+ > **Warning — A typed local call is not the whole deploy story**
7795
+ >
7796
+ > The local harness tells you the relationship is modeled correctly. A preview or build check tells you the resolved worker names are still the ones you expect.
7797
+
7798
+ ---
7799
+
7800
+ ### A small Services example you can adapt quickly
7801
+
7802
+ > This example shows the smallest useful service-binding loop: one `ref()`, one gateway route, and one local multi-worker test.
7803
+
7804
+ | Field | Value |
7805
+ | --- | --- |
7806
+ | Route | [`/docs/bindings/services/example`](/docs/bindings/services/example) |
7807
+ | Group | Bindings |
7808
+ | Navigation title | Services example |
7809
+ | Eyebrow | Starter example |
7810
+
7811
+ That is enough to show why Devflare helps here: the relationship stays explicit in config, typed in env, and testable without hand-assembling your own mini service mesh in the test file.
7812
+
7813
+ #### At a glance
7814
+
7815
+ | Fact | Value |
7816
+ | --- | --- |
7817
+ | Config focus | Explicit `ref()` wiring |
7818
+ | Runtime shape | One env service call from the gateway worker |
7819
+ | Best use | Internal APIs and worker-family boundaries |
7820
+
7821
+ #### Start by wiring the binding clearly in config
7822
+
7823
+ ##### Example — Gateway config with a service ref
7824
+
7825
+ ```ts
7826
+ import { defineConfig, ref } from 'devflare/config'
7827
+
7828
+ const mathService = ref(() => import('../math-service/devflare.config'))
7829
+
7830
+ export default defineConfig({
7831
+ name: 'gateway',
7832
+ files: {
7833
+ fetch: 'src/fetch.ts'
7834
+ },
7835
+ bindings: {
7836
+ services: {
7837
+ MATH_SERVICE: mathService.worker
7838
+ }
7839
+ }
7840
+ })
7841
+ ```
7842
+
7843
+ #### Then use it in one honest runtime path
7844
+
7845
+ ##### Key points
7846
+
7847
+ - Once this tiny path works, adding named entrypoints becomes an incremental extension, not a different architecture.
7848
+ - Keep one simple service example like this around if you want a smoke check for multi-worker wiring.
7849
+
7850
+ ##### Example — Use the service in the gateway worker
7851
+
7852
+ ```ts
7853
+ import { env } from 'devflare'
7854
+
7855
+ export async function fetch(): Promise<Response> {
7856
+ const result = await env.MATH_SERVICE.add(4, 5)
7857
+ return Response.json({ result })
7858
+ }
7859
+ ```
7860
+
7861
+ #### Lock in the behavior with one small test or smoke path
7862
+
7863
+ > **Important — This is the valuable bit**
7864
+ >
7865
+ > You do not need a whole microservice fleet to feel the Devflare value. One gateway call already proves that config refs, env bindings, and local multi-worker tests stay part of one coherent loop.
7866
+
7867
+ ##### Example — A single multi-worker test
7868
+
7869
+ ```ts
7870
+ import { afterAll, beforeAll, expect, test } from 'bun:test'
7871
+ import { createTestContext, cf } from 'devflare/test'
7872
+ import { env } from 'devflare'
7873
+
7874
+ beforeAll(() => createTestContext())
7875
+ afterAll(() => env.dispose())
7876
+
7877
+ test('GET / calls the math service', async () => {
7878
+ const response = await cf.worker.get('/')
7879
+ expect(await response.json()).toEqual({ result: 9 })
7880
+ })
7881
+ ```
7882
+
7883
+ ---
7884
+
7488
7885
  ### Use the AI binding when the worker needs real Workers AI inference, not just a local mock
7489
7886
 
7490
- > AI is a supported binding in Devflare, but it is intentionally treated as remote-oriented because real model inference lives on Cloudflare infrastructure.
7887
+ > Devflare makes Workers AI usable by keeping the binding tiny in config, the worker call obvious, and the remote smoke test explicit instead of fake.
7491
7888
 
7492
7889
  | Field | Value |
7493
7890
  | --- | --- |
7494
- | Route | [`/docs/ai-binding`](/docs/ai-binding) |
7891
+ | Route | [`/docs/bindings/ai`](/docs/bindings/ai) |
7495
7892
  | Group | Bindings |
7496
7893
  | Navigation title | AI |
7497
7894
  | Eyebrow | Binding reference |
7498
7895
 
7499
- That means the docs should be honest: Devflare can compile and type the binding cleanly, but meaningful tests usually need remote mode and real account access.
7896
+ AI is still remote-oriented, but the first useful path is simple: one worker route, one `env.AI.run(...)` call, and one skip-aware remote test that says clearly when the real platform was involved.
7500
7897
 
7501
7898
  #### At a glance
7502
7899
 
@@ -7508,9 +7905,9 @@ That means the docs should be honest: Devflare can compile and type the binding
7508
7905
 
7509
7906
  #### Author it in the simplest shape that still says what you mean
7510
7907
 
7511
- AI is a remote-oriented binding. The binding exists in config, the env is typed, and the deploy story is real but model inference itself still lives on Cloudflare infrastructure.
7908
+ AI is a remote-oriented binding, but the first worker path should still be tiny and concrete: receive one request, call one model, return one JSON response.
7512
7909
 
7513
- The testing story leans on remote mode rather than pretending Miniflare can be a credible stand-in for actual model execution.
7910
+ The Devflare-specific win is not fake local inference. It is that config, worker code, and remote test gating stay explicit enough that you know when the real platform was actually exercised.
7514
7911
 
7515
7912
  ##### Example — Workers AI binding authoring
7516
7913
 
@@ -7567,9 +7964,9 @@ Cloudflare Workers AI docs is the platform reference. This page is the Devflare
7567
7964
 
7568
7965
  ##### Highlights
7569
7966
 
7570
- - **AI internals** — See normalization, Wrangler `ai` binding, and the preview or runtime details behind the authored shape. ([link](/docs/ai-internals))
7571
- - **Testing AI** — Start from `createTestContext()` after remote mode is enabled, plus `shouldSkip.ai` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/ai-testing))
7572
- - **AI example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/ai-example))
7967
+ - **AI internals** — See normalization, Wrangler `ai` binding, and the preview or runtime details behind the authored shape. ([link](/docs/bindings/ai/internals))
7968
+ - **Testing AI** — Start from `createTestContext()` after remote mode is enabled, plus `shouldSkip.ai` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/bindings/ai/testing))
7969
+ - **AI example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/bindings/ai/example))
7573
7970
 
7574
7971
  ---
7575
7972
 
@@ -7579,7 +7976,7 @@ Cloudflare Workers AI docs is the platform reference. This page is the Devflare
7579
7976
 
7580
7977
  | Field | Value |
7581
7978
  | --- | --- |
7582
- | Route | [`/docs/ai-internals`](/docs/ai-internals) |
7979
+ | Route | [`/docs/bindings/ai/internals`](/docs/bindings/ai/internals) |
7583
7980
  | Group | Bindings |
7584
7981
  | Navigation title | AI internals |
7585
7982
  | Eyebrow | Under the hood |
@@ -7658,7 +8055,7 @@ export default defineConfig({
7658
8055
 
7659
8056
  | Field | Value |
7660
8057
  | --- | --- |
7661
- | Route | [`/docs/ai-testing`](/docs/ai-testing) |
8058
+ | Route | [`/docs/bindings/ai/testing`](/docs/bindings/ai/testing) |
7662
8059
  | Group | Bindings |
7663
8060
  | Navigation title | Testing AI |
7664
8061
  | Eyebrow | Testing |
@@ -7728,16 +8125,16 @@ describe.skipIf(skipAI)('AI binding', () => {
7728
8125
 
7729
8126
  ### A small AI example you can adapt quickly
7730
8127
 
7731
- > This example keeps the AI path tiny: one binding, one inference call, one JSON response.
8128
+ > This example keeps the AI story honest and useful: one binding, one tiny inference route, and one skip-aware remote smoke test.
7732
8129
 
7733
8130
  | Field | Value |
7734
8131
  | --- | --- |
7735
- | Route | [`/docs/ai-example`](/docs/ai-example) |
8132
+ | Route | [`/docs/bindings/ai/example`](/docs/bindings/ai/example) |
7736
8133
  | Group | Bindings |
7737
8134
  | Navigation title | AI example |
7738
8135
  | Eyebrow | Starter example |
7739
8136
 
7740
- That is enough to prove the worker can talk to Workers AI without burying the example inside a whole chat product.
8137
+ That is enough to show the Devflare value: config stays tiny, the worker code stays normal, and the test tells you clearly when remote AI was really available.
7741
8138
 
7742
8139
  #### At a glance
7743
8140
 
@@ -7789,26 +8186,48 @@ export async function fetch(): Promise<Response> {
7789
8186
  }
7790
8187
  ```
7791
8188
 
7792
- #### Keep the first version boring
8189
+ #### Lock in the behavior with one small test or smoke path
7793
8190
 
7794
- > **WarningThis example still needs remote access**
8191
+ > **ImportantThe Devflare win is the explicit remote gate**
7795
8192
  >
7796
- > It is a minimal worker example, not a promise of local AI emulation. Treat account access and cost control as part of the example setup.
8193
+ > A clear skip condition is more trustworthy than a fake local AI emulator that never touched the real platform. That honesty is part of what makes the Devflare AI story usable.
8194
+
8195
+ ##### Example — A skip-aware remote smoke test
8196
+
8197
+ ```ts
8198
+ import { afterAll, beforeAll, describe, expect, test } from 'bun:test'
8199
+ import { createTestContext, cf, env, shouldSkip } from 'devflare/test'
8200
+
8201
+ beforeAll(() => createTestContext())
8202
+ afterAll(() => env.dispose())
8203
+
8204
+ const skipAI = await shouldSkip.ai
8205
+
8206
+ describe.skipIf(skipAI)('AI route', () => {
8207
+ test('calls Workers AI through the worker boundary', async () => {
8208
+ const response = await cf.worker.get('/')
8209
+ expect(response.ok).toBe(true)
8210
+
8211
+ const body = await response.json()
8212
+ expect(body.result).toBeDefined()
8213
+ })
8214
+ })
8215
+ ```
7797
8216
 
7798
8217
  ---
7799
8218
 
7800
8219
  ### Use Vectorize when the worker really owns similarity search, not just string matching
7801
8220
 
7802
- > Vectorize is fully modeled in Devflare config and preview naming, but meaningful tests are still remote-oriented because the index lives on Cloudflare infrastructure.
8221
+ > Devflare makes Vectorize usable by keeping the index name explicit in config, preview naming honest, and the real smoke test explicit instead of buried under mocks.
7803
8222
 
7804
8223
  | Field | Value |
7805
8224
  | --- | --- |
7806
- | Route | [`/docs/vectorize-binding`](/docs/vectorize-binding) |
8225
+ | Route | [`/docs/bindings/vectorize`](/docs/bindings/vectorize) |
7807
8226
  | Group | Bindings |
7808
8227
  | Navigation title | Vectorize |
7809
8228
  | Eyebrow | Binding reference |
7810
8229
 
7811
- That makes the docs pattern similar to AI: compile support is strong, preview lifecycle is explicit, and tests should be honest about when they are using the real index versus a fake.
8230
+ The right first path is small: one binding, one tiny upsert-and-query route, and one skip-aware remote smoke test that tells the truth about whether the real index was involved.
7812
8231
 
7813
8232
  #### At a glance
7814
8233
 
@@ -7881,9 +8300,9 @@ Cloudflare Vectorize docs is the platform reference. This page is the Devflare t
7881
8300
 
7882
8301
  ##### Highlights
7883
8302
 
7884
- - **Vectorize internals** — See normalization, Wrangler `vectorize`, and the preview or runtime details behind the authored shape. ([link](/docs/vectorize-internals))
7885
- - **Testing Vectorize** — Start from `createTestContext()` in remote mode plus `shouldSkip.vectorize` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/vectorize-testing))
7886
- - **Vectorize example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/vectorize-example))
8303
+ - **Vectorize internals** — See normalization, Wrangler `vectorize`, and the preview or runtime details behind the authored shape. ([link](/docs/bindings/vectorize/internals))
8304
+ - **Testing Vectorize** — Start from `createTestContext()` in remote mode plus `shouldSkip.vectorize` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/bindings/vectorize/testing))
8305
+ - **Vectorize example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/bindings/vectorize/example))
7887
8306
 
7888
8307
  ---
7889
8308
 
@@ -7893,7 +8312,7 @@ Cloudflare Vectorize docs is the platform reference. This page is the Devflare t
7893
8312
 
7894
8313
  | Field | Value |
7895
8314
  | --- | --- |
7896
- | Route | [`/docs/vectorize-internals`](/docs/vectorize-internals) |
8315
+ | Route | [`/docs/bindings/vectorize/internals`](/docs/bindings/vectorize/internals) |
7897
8316
  | Group | Bindings |
7898
8317
  | Navigation title | Vectorize internals |
7899
8318
  | Eyebrow | Under the hood |
@@ -7973,7 +8392,7 @@ export default defineConfig({
7973
8392
 
7974
8393
  | Field | Value |
7975
8394
  | --- | --- |
7976
- | Route | [`/docs/vectorize-testing`](/docs/vectorize-testing) |
8395
+ | Route | [`/docs/bindings/vectorize/testing`](/docs/bindings/vectorize/testing) |
7977
8396
  | Group | Bindings |
7978
8397
  | Navigation title | Testing Vectorize |
7979
8398
  | Eyebrow | Testing |
@@ -8042,16 +8461,16 @@ describe.skipIf(skipVectorize)('Vectorize binding', () => {
8042
8461
 
8043
8462
  ### A small Vectorize example you can adapt quickly
8044
8463
 
8045
- > This example keeps Vectorize honest: one index binding, one upsert, and one query against the same worker path.
8464
+ > This example keeps Vectorize honest and usable: one index binding, one upsert-and-query route, and one skip-aware remote smoke test.
8046
8465
 
8047
8466
  | Field | Value |
8048
8467
  | --- | --- |
8049
- | Route | [`/docs/vectorize-example`](/docs/vectorize-example) |
8468
+ | Route | [`/docs/bindings/vectorize/example`](/docs/bindings/vectorize/example) |
8050
8469
  | Group | Bindings |
8051
8470
  | Navigation title | Vectorize example |
8052
8471
  | Eyebrow | Starter example |
8053
8472
 
8054
- That is enough to show the binding shape without requiring a whole retrieval stack in the very first example.
8473
+ That is enough to show the binding shape, the worker contract, and the Devflare remote gate without dragging in a whole retrieval stack on page one.
8055
8474
 
8056
8475
  #### At a glance
8057
8476
 
@@ -8111,11 +8530,33 @@ export async function fetch(): Promise<Response> {
8111
8530
  }
8112
8531
  ```
8113
8532
 
8114
- #### Keep the first version boring
8533
+ #### Lock in the behavior with one small test or smoke path
8115
8534
 
8116
- > **Warning — The remote index still has to exist**
8535
+ > **Important — The Devflare win is honest lifecycle plus honest gating**
8117
8536
  >
8118
- > This example is intentionally small, but it is not fictional. The named index has to exist and match the vector shape you send.
8537
+ > The named index still has to exist, but Devflare keeps that reality visible in config, preview naming, and skip-aware tests instead of hiding it behind fake local success.
8538
+
8539
+ ##### Example — A skip-aware remote Vectorize smoke test
8540
+
8541
+ ```ts
8542
+ import { afterAll, beforeAll, describe, expect, test } from 'bun:test'
8543
+ import { createTestContext, cf, env, shouldSkip } from 'devflare/test'
8544
+
8545
+ beforeAll(() => createTestContext())
8546
+ afterAll(() => env.dispose())
8547
+
8548
+ const skipVectorize = await shouldSkip.vectorize
8549
+
8550
+ describe.skipIf(skipVectorize)('Vectorize route', () => {
8551
+ test('hits the configured index through the worker boundary', async () => {
8552
+ const response = await cf.worker.get('/')
8553
+ expect(response.ok).toBe(true)
8554
+
8555
+ const body = await response.json()
8556
+ expect(body.result).toBeDefined()
8557
+ })
8558
+ })
8559
+ ```
8119
8560
 
8120
8561
  ---
8121
8562
 
@@ -8125,7 +8566,7 @@ export async function fetch(): Promise<Response> {
8125
8566
 
8126
8567
  | Field | Value |
8127
8568
  | --- | --- |
8128
- | Route | [`/docs/hyperdrive-binding`](/docs/hyperdrive-binding) |
8569
+ | Route | [`/docs/bindings/hyperdrive`](/docs/bindings/hyperdrive) |
8129
8570
  | Group | Bindings |
8130
8571
  | Navigation title | Hyperdrive |
8131
8572
  | Eyebrow | Binding reference |
@@ -8156,7 +8597,7 @@ export default defineConfig({
8156
8597
  bindings: {
8157
8598
  hyperdrive: {
8158
8599
  DB: 'app-postgres',
8159
- ANALYTICS_DB: { id: 'hyperdrive-id' }
8600
+ ANALYTICS_DB: { id: 'hyperdrive-id' }
8160
8601
  }
8161
8602
  }
8162
8603
  })
@@ -8202,9 +8643,9 @@ Cloudflare Hyperdrive docs is the platform reference. This page is the Devflare
8202
8643
 
8203
8644
  ##### Highlights
8204
8645
 
8205
- - **Hyperdrive internals** — See normalization, Wrangler `hyperdrive`, and the preview or runtime details behind the authored shape. ([link](/docs/hyperdrive-internals))
8206
- - **Testing Hyperdrive** — Start from `createTestContext()` plus small binding or smoke checks and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/hyperdrive-testing))
8207
- - **Hyperdrive example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/hyperdrive-example))
8646
+ - **Hyperdrive internals** — See normalization, Wrangler `hyperdrive`, and the preview or runtime details behind the authored shape. ([link](/docs/bindings/hyperdrive/internals))
8647
+ - **Testing Hyperdrive** — Start from `createTestContext()` plus small binding or smoke checks and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/bindings/hyperdrive/testing))
8648
+ - **Hyperdrive example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/bindings/hyperdrive/example))
8208
8649
 
8209
8650
  ---
8210
8651
 
@@ -8214,7 +8655,7 @@ Cloudflare Hyperdrive docs is the platform reference. This page is the Devflare
8214
8655
 
8215
8656
  | Field | Value |
8216
8657
  | --- | --- |
8217
- | Route | [`/docs/hyperdrive-internals`](/docs/hyperdrive-internals) |
8658
+ | Route | [`/docs/bindings/hyperdrive/internals`](/docs/bindings/hyperdrive/internals) |
8218
8659
  | Group | Bindings |
8219
8660
  | Navigation title | Hyperdrive internals |
8220
8661
  | Eyebrow | Under the hood |
@@ -8249,7 +8690,7 @@ export default defineConfig({
8249
8690
  bindings: {
8250
8691
  hyperdrive: {
8251
8692
  DB: 'app-postgres',
8252
- ANALYTICS_DB: { id: 'hyperdrive-id' }
8693
+ ANALYTICS_DB: { id: 'hyperdrive-id' }
8253
8694
  }
8254
8695
  }
8255
8696
  })
@@ -8293,7 +8734,7 @@ export default defineConfig({
8293
8734
 
8294
8735
  | Field | Value |
8295
8736
  | --- | --- |
8296
- | Route | [`/docs/hyperdrive-testing`](/docs/hyperdrive-testing) |
8737
+ | Route | [`/docs/bindings/hyperdrive/testing`](/docs/bindings/hyperdrive/testing) |
8297
8738
  | Group | Bindings |
8298
8739
  | Navigation title | Testing Hyperdrive |
8299
8740
  | Eyebrow | Testing |
@@ -8358,7 +8799,7 @@ test('Hyperdrive binding exposes connection info', () => {
8358
8799
 
8359
8800
  | Field | Value |
8360
8801
  | --- | --- |
8361
- | Route | [`/docs/hyperdrive-example`](/docs/hyperdrive-example) |
8802
+ | Route | [`/docs/bindings/hyperdrive/example`](/docs/bindings/hyperdrive/example) |
8362
8803
  | Group | Bindings |
8363
8804
  | Navigation title | Hyperdrive example |
8364
8805
  | Eyebrow | Starter example |
@@ -8423,16 +8864,16 @@ export async function fetch(): Promise<Response> {
8423
8864
 
8424
8865
  ### Use Browser Rendering when the worker really needs a headless browser path
8425
8866
 
8426
- > Devflare supports Browser Rendering, but there is exactly one browser binding today, and the best-supported local story lives in dev-server and integration flows.
8867
+ > Browser Rendering shines in Devflare’s bridge-backed dev story: keep one browser binding, one narrow worker route, and one smoke path that proves launch works.
8427
8868
 
8428
8869
  | Field | Value |
8429
8870
  | --- | --- |
8430
- | Route | [`/docs/browser-binding`](/docs/browser-binding) |
8871
+ | Route | [`/docs/bindings/browser-rendering`](/docs/bindings/browser-rendering) |
8431
8872
  | Group | Bindings |
8432
8873
  | Navigation title | Browser Rendering |
8433
8874
  | Eyebrow | Binding reference |
8434
8875
 
8435
- Browser work can live in the same docs library as every other binding, just with clear caveats about limits and testing style.
8876
+ The platform limit is still real exactly one browser binding but Devflare adds the missing local ergonomics through the browser shim, binding worker, and integration-friendly route model.
8436
8877
 
8437
8878
  #### At a glance
8438
8879
 
@@ -8505,9 +8946,9 @@ Cloudflare Browser Rendering docs is the platform reference. This page is the De
8505
8946
 
8506
8947
  ##### Highlights
8507
8948
 
8508
- - **Browser Rendering internals** — See normalization, Wrangler `browser` binding, and the preview or runtime details behind the authored shape. ([link](/docs/browser-internals))
8509
- - **Testing Browser Rendering** — Start from A narrow browser route exercised through the dev server, a preview URL, or another integration-style path and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/browser-testing))
8510
- - **Browser Rendering example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/browser-example))
8949
+ - **Browser Rendering internals** — See normalization, Wrangler `browser` binding, and the preview or runtime details behind the authored shape. ([link](/docs/bindings/browser-rendering/internals))
8950
+ - **Testing Browser Rendering** — Start from A narrow browser route exercised through the dev server, a preview URL, or another integration-style path and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/bindings/browser-rendering/testing))
8951
+ - **Browser Rendering example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/bindings/browser-rendering/example))
8511
8952
 
8512
8953
  ---
8513
8954
 
@@ -8517,7 +8958,7 @@ Cloudflare Browser Rendering docs is the platform reference. This page is the De
8517
8958
 
8518
8959
  | Field | Value |
8519
8960
  | --- | --- |
8520
- | Route | [`/docs/browser-internals`](/docs/browser-internals) |
8961
+ | Route | [`/docs/bindings/browser-rendering/internals`](/docs/bindings/browser-rendering/internals) |
8521
8962
  | Group | Bindings |
8522
8963
  | Navigation title | Browser Rendering internals |
8523
8964
  | Eyebrow | Under the hood |
@@ -8584,9 +9025,11 @@ export default defineConfig({
8584
9025
  - Preview logic can materialize names, but Devflare does not provision or delete browser “resources” because they are not account-managed the same way storage bindings are.
8585
9026
  - The browser path can also warn about missing local WebSocket support when the environment lacks the `ws` dependency needed for proxying.
8586
9027
 
8587
- > **Note — The honest browser story**
9028
+ > **Note — Local browser-rendering shim**
9029
+ >
9030
+ > The dev-side endpoint Devflare exposes for `@cloudflare/puppeteer` is the **local browser-rendering shim**. It accepts only loopback browser origins (e.g. `http://127.0.0.1:*`, `http://localhost:*`) plus origin-less tool traffic such as Puppeteer or curl.
8588
9031
  >
8589
- > Browser support is real, but it is infrastructural. Expect a stronger dev-server story than a tiny one-function local helper story.
9032
+ > This loopback-only posture is the security model of the shim itself — it is devflare’s protected helper endpoint for the local Browser Rendering binding. It is **not** a policy applied to your normal worker routes; user app routes still follow whatever request and CORS rules the worker code itself defines.
8590
9033
 
8591
9034
  ---
8592
9035
 
@@ -8596,7 +9039,7 @@ export default defineConfig({
8596
9039
 
8597
9040
  | Field | Value |
8598
9041
  | --- | --- |
8599
- | Route | [`/docs/browser-testing`](/docs/browser-testing) |
9042
+ | Route | [`/docs/bindings/browser-rendering/testing`](/docs/bindings/browser-rendering/testing) |
8600
9043
  | Group | Bindings |
8601
9044
  | Navigation title | Testing Browser Rendering |
8602
9045
  | Eyebrow | Testing |
@@ -8656,16 +9099,16 @@ test('browser-backed route responds', async () => {
8656
9099
 
8657
9100
  ### A small Browser Rendering example you can adapt quickly
8658
9101
 
8659
- > This example shows the real browser shape most people care about: launch a browser, read one page title, close the browser cleanly.
9102
+ > This example shows the real browser path people actually need: one binding, one title-read route, and one smoke check through the dev server.
8660
9103
 
8661
9104
  | Field | Value |
8662
9105
  | --- | --- |
8663
- | Route | [`/docs/browser-example`](/docs/browser-example) |
9106
+ | Route | [`/docs/bindings/browser-rendering/example`](/docs/bindings/browser-rendering/example) |
8664
9107
  | Group | Bindings |
8665
9108
  | Navigation title | Browser Rendering example |
8666
9109
  | Eyebrow | Starter example |
8667
9110
 
8668
- It is intentionally smaller than a full PDF pipeline, but it uses the same worker-side idea: the browser binding is real infrastructure, not a pretend local object.
9111
+ It is intentionally smaller than a full PDF pipeline, but it uses the same Devflare idea: a narrow worker route on top of a bridge-backed local browser lane.
8669
9112
 
8670
9113
  #### At a glance
8671
9114
 
@@ -8721,11 +9164,27 @@ export async function fetch(): Promise<Response> {
8721
9164
  }
8722
9165
  ```
8723
9166
 
8724
- #### Keep the first version boring
9167
+ #### Lock in the behavior with one small test or smoke path
8725
9168
 
8726
- > **Warning — The example is small, not cheap**
9169
+ > **Important — The Devflare value is the bridge-backed local lane**
8727
9170
  >
8728
- > Browser work is still heavier than most bindings. Keep your first path focused enough that failures are easy to diagnose.
9171
+ > Browser work is still heavier than most bindings, but Devflare gives it a real local/dev story instead of forcing you to document only the production path. Keep the first route narrow enough that launch failures are easy to diagnose.
9172
+
9173
+ ##### Example — A dev-server smoke check for the browser route
9174
+
9175
+ ```ts
9176
+ import { expect, test } from 'bun:test'
9177
+
9178
+ const baseUrl = process.env.DEVFLARE_TEST_URL ?? 'http://127.0.0.1:8787'
9179
+
9180
+ test('browser route returns a title', async () => {
9181
+ const response = await fetch(new URL('/', baseUrl))
9182
+ expect(response.ok).toBe(true)
9183
+
9184
+ const body = await response.json()
9185
+ expect(body.title).toBeTruthy()
9186
+ })
9187
+ ```
8729
9188
 
8730
9189
  ---
8731
9190
 
@@ -8735,7 +9194,7 @@ export async function fetch(): Promise<Response> {
8735
9194
 
8736
9195
  | Field | Value |
8737
9196
  | --- | --- |
8738
- | Route | [`/docs/analytics-engine-binding`](/docs/analytics-engine-binding) |
9197
+ | Route | [`/docs/bindings/analytics-engine`](/docs/bindings/analytics-engine) |
8739
9198
  | Group | Bindings |
8740
9199
  | Navigation title | Analytics Engine |
8741
9200
  | Eyebrow | Binding reference |
@@ -8813,9 +9272,9 @@ Cloudflare Workers Analytics Engine docs is the platform reference. This page is
8813
9272
 
8814
9273
  ##### Highlights
8815
9274
 
8816
- - **Analytics Engine internals** — See normalization, Wrangler `analytics_engine_datasets`, and the preview or runtime details behind the authored shape. ([link](/docs/analytics-engine-internals))
8817
- - **Testing Analytics Engine** — Start from A thin worker test or explicit mock around `writeDataPoint()` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/analytics-engine-testing))
8818
- - **Analytics Engine example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/analytics-engine-example))
9275
+ - **Analytics Engine internals** — See normalization, Wrangler `analytics_engine_datasets`, and the preview or runtime details behind the authored shape. ([link](/docs/bindings/analytics-engine/internals))
9276
+ - **Testing Analytics Engine** — Start from A thin worker test or explicit mock around `writeDataPoint()` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/bindings/analytics-engine/testing))
9277
+ - **Analytics Engine example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/bindings/analytics-engine/example))
8819
9278
 
8820
9279
  ---
8821
9280
 
@@ -8825,7 +9284,7 @@ Cloudflare Workers Analytics Engine docs is the platform reference. This page is
8825
9284
 
8826
9285
  | Field | Value |
8827
9286
  | --- | --- |
8828
- | Route | [`/docs/analytics-engine-internals`](/docs/analytics-engine-internals) |
9287
+ | Route | [`/docs/bindings/analytics-engine/internals`](/docs/bindings/analytics-engine/internals) |
8829
9288
  | Group | Bindings |
8830
9289
  | Navigation title | Analytics Engine internals |
8831
9290
  | Eyebrow | Under the hood |
@@ -8905,7 +9364,7 @@ export default defineConfig({
8905
9364
 
8906
9365
  | Field | Value |
8907
9366
  | --- | --- |
8908
- | Route | [`/docs/analytics-engine-testing`](/docs/analytics-engine-testing) |
9367
+ | Route | [`/docs/bindings/analytics-engine/testing`](/docs/bindings/analytics-engine/testing) |
8909
9368
  | Group | Bindings |
8910
9369
  | Navigation title | Testing Analytics Engine |
8911
9370
  | Eyebrow | Testing |
@@ -8972,7 +9431,7 @@ test('records an analytics point', () => {
8972
9431
 
8973
9432
  | Field | Value |
8974
9433
  | --- | --- |
8975
- | Route | [`/docs/analytics-engine-example`](/docs/analytics-engine-example) |
9434
+ | Route | [`/docs/bindings/analytics-engine/example`](/docs/bindings/analytics-engine/example) |
8976
9435
  | Group | Bindings |
8977
9436
  | Navigation title | Analytics Engine example |
8978
9437
  | Eyebrow | Starter example |
@@ -9045,7 +9504,7 @@ export async function fetch(): Promise<Response> {
9045
9504
 
9046
9505
  | Field | Value |
9047
9506
  | --- | --- |
9048
- | Route | [`/docs/send-email-binding`](/docs/send-email-binding) |
9507
+ | Route | [`/docs/bindings/send-email`](/docs/bindings/send-email) |
9049
9508
  | Group | Bindings |
9050
9509
  | Navigation title | Send Email |
9051
9510
  | Eyebrow | Binding reference |
@@ -9127,9 +9586,9 @@ Cloudflare send_email binding docs is the platform reference. This page is the D
9127
9586
 
9128
9587
  ##### Highlights
9129
9588
 
9130
- - **Send Email internals** — See normalization, Wrangler `send_email`, and the preview or runtime details behind the authored shape. ([link](/docs/send-email-internals))
9131
- - **Testing Send Email** — Start from `createTestContext()` plus `env.TRANSACTIONAL_EMAIL.send(...)` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/send-email-testing))
9132
- - **Send Email example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/send-email-example))
9589
+ - **Send Email internals** — See normalization, Wrangler `send_email`, and the preview or runtime details behind the authored shape. ([link](/docs/bindings/send-email/internals))
9590
+ - **Testing Send Email** — Start from `createTestContext()` plus `env.TRANSACTIONAL_EMAIL.send(...)` and only escalate when the binding or deployment model genuinely needs it. ([link](/docs/bindings/send-email/testing))
9591
+ - **Send Email example** — Adapt one small end-to-end path before you hide the binding behind a bigger abstraction. ([link](/docs/bindings/send-email/example))
9133
9592
 
9134
9593
  ---
9135
9594
 
@@ -9139,7 +9598,7 @@ Cloudflare send_email binding docs is the platform reference. This page is the D
9139
9598
 
9140
9599
  | Field | Value |
9141
9600
  | --- | --- |
9142
- | Route | [`/docs/send-email-internals`](/docs/send-email-internals) |
9601
+ | Route | [`/docs/bindings/send-email/internals`](/docs/bindings/send-email/internals) |
9143
9602
  | Group | Bindings |
9144
9603
  | Navigation title | Send Email internals |
9145
9604
  | Eyebrow | Under the hood |
@@ -9223,7 +9682,7 @@ export default defineConfig({
9223
9682
 
9224
9683
  | Field | Value |
9225
9684
  | --- | --- |
9226
- | Route | [`/docs/send-email-testing`](/docs/send-email-testing) |
9685
+ | Route | [`/docs/bindings/send-email/testing`](/docs/bindings/send-email/testing) |
9227
9686
  | Group | Bindings |
9228
9687
  | Navigation title | Testing Send Email |
9229
9688
  | Eyebrow | Testing |
@@ -9292,7 +9751,7 @@ test('sends an outbound transactional email', async () => {
9292
9751
 
9293
9752
  | Field | Value |
9294
9753
  | --- | --- |
9295
- | Route | [`/docs/send-email-example`](/docs/send-email-example) |
9754
+ | Route | [`/docs/bindings/send-email/example`](/docs/bindings/send-email/example) |
9296
9755
  | Group | Bindings |
9297
9756
  | Navigation title | Send Email example |
9298
9757
  | Eyebrow | Starter example |