devflare 1.0.0-next.19 → 1.0.0-next.20

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 (360) hide show
  1. package/LLM.md +6807 -888
  2. package/README.md +375 -957
  3. package/dist/account-05zgta47.js +475 -0
  4. package/dist/account-b2ag1esh.js +475 -0
  5. package/dist/account-bxtcz61a.js +475 -0
  6. package/dist/account-gyfqg964.js +475 -0
  7. package/dist/account-q6pvs9d9.js +475 -0
  8. package/dist/account-rp4zbvw1.js +475 -0
  9. package/dist/bridge/client.d.ts +5 -0
  10. package/dist/bridge/client.d.ts.map +1 -1
  11. package/dist/bridge/gateway-runtime.d.ts +1 -1
  12. package/dist/bridge/gateway-runtime.d.ts.map +1 -1
  13. package/dist/bridge/miniflare.d.ts +67 -0
  14. package/dist/bridge/miniflare.d.ts.map +1 -1
  15. package/dist/bridge/proxy.d.ts +2 -1
  16. package/dist/bridge/proxy.d.ts.map +1 -1
  17. package/dist/bridge/server.d.ts.map +1 -1
  18. package/dist/browser.d.ts +2520 -40
  19. package/dist/browser.d.ts.map +1 -1
  20. package/dist/browser.js +3 -3
  21. package/dist/build-2s5paw5p.js +54 -0
  22. package/dist/build-4c350cp7.js +54 -0
  23. package/dist/build-e7wym63t.js +54 -0
  24. package/dist/build-ge6qp3t4.js +54 -0
  25. package/dist/build-ta8c6t11.js +54 -0
  26. package/dist/build-wvjj8f28.js +54 -0
  27. package/dist/build-ypg6f2kw.js +54 -0
  28. package/dist/build-yts8wwgf.js +54 -0
  29. package/dist/build-yzkdqexs.js +54 -0
  30. package/dist/cli/build-manifest.d.ts +12 -0
  31. package/dist/cli/build-manifest.d.ts.map +1 -1
  32. package/dist/cli/commands/deploy/metadata.d.ts +18 -0
  33. package/dist/cli/commands/deploy/metadata.d.ts.map +1 -0
  34. package/dist/cli/commands/deploy/prepare.d.ts +23 -0
  35. package/dist/cli/commands/deploy/prepare.d.ts.map +1 -0
  36. package/dist/cli/commands/deploy/runtime.d.ts +4 -0
  37. package/dist/cli/commands/deploy/runtime.d.ts.map +1 -0
  38. package/dist/cli/commands/deploy/verification.d.ts +36 -0
  39. package/dist/cli/commands/deploy/verification.d.ts.map +1 -0
  40. package/dist/cli/commands/deploy.d.ts +2 -2
  41. package/dist/cli/commands/deploy.d.ts.map +1 -1
  42. package/dist/cli/commands/secrets.d.ts +4 -0
  43. package/dist/cli/commands/secrets.d.ts.map +1 -0
  44. package/dist/cli/commands/type-generation/generator.d.ts +67 -1
  45. package/dist/cli/commands/type-generation/generator.d.ts.map +1 -1
  46. package/dist/cli/help-pages/pages/core.d.ts +1 -1
  47. package/dist/cli/help-pages/pages/core.d.ts.map +1 -1
  48. package/dist/cli/help-pages/shared.d.ts +1 -1
  49. package/dist/cli/help-pages/shared.d.ts.map +1 -1
  50. package/dist/cli/index.d.ts.map +1 -1
  51. package/dist/cli/index.js +2 -2
  52. package/dist/cli/package-metadata.d.ts.map +1 -1
  53. package/dist/cli/preview-bindings.d.ts.map +1 -1
  54. package/dist/cloudflare/index.js +2 -2
  55. package/dist/cloudflare/preview-registry-store.d.ts +1 -1
  56. package/dist/cloudflare/preview-registry-store.d.ts.map +1 -1
  57. package/dist/cloudflare/types.d.ts +1 -1
  58. package/dist/cloudflare/types.d.ts.map +1 -1
  59. package/dist/config/binding-resolution-helpers.d.ts +5 -0
  60. package/dist/config/binding-resolution-helpers.d.ts.map +1 -1
  61. package/dist/config/compiler/bindings.d.ts +14 -0
  62. package/dist/config/compiler/bindings.d.ts.map +1 -0
  63. package/dist/config/compiler/core-helpers.d.ts +6 -0
  64. package/dist/config/compiler/core-helpers.d.ts.map +1 -0
  65. package/dist/config/compiler/do-workers.d.ts +34 -0
  66. package/dist/config/compiler/do-workers.d.ts.map +1 -0
  67. package/dist/config/compiler/paths.d.ts +18 -0
  68. package/dist/config/compiler/paths.d.ts.map +1 -0
  69. package/dist/config/compiler/types.d.ts +267 -0
  70. package/dist/config/compiler/types.d.ts.map +1 -0
  71. package/dist/config/compiler.d.ts +11 -175
  72. package/dist/config/compiler.d.ts.map +1 -1
  73. package/dist/config/deploy-resources.d.ts.map +1 -1
  74. package/dist/config/index.d.ts +1 -1
  75. package/dist/config/index.d.ts.map +1 -1
  76. package/dist/config/local-dev-vars.d.ts +15 -0
  77. package/dist/config/local-dev-vars.d.ts.map +1 -0
  78. package/dist/config/preview-resources.d.ts.map +1 -1
  79. package/dist/config/preview.d.ts.map +1 -1
  80. package/dist/config/resolve.d.ts.map +1 -1
  81. package/dist/config/resource-resolution.d.ts.map +1 -1
  82. package/dist/config/schema-bindings.d.ts +559 -19
  83. package/dist/config/schema-bindings.d.ts.map +1 -1
  84. package/dist/config/schema-env.d.ts +1306 -34
  85. package/dist/config/schema-env.d.ts.map +1 -1
  86. package/dist/config/schema-normalization.d.ts +97 -1
  87. package/dist/config/schema-normalization.d.ts.map +1 -1
  88. package/dist/config/schema-runtime.d.ts +245 -7
  89. package/dist/config/schema-runtime.d.ts.map +1 -1
  90. package/dist/config/schema.d.ts +2976 -57
  91. package/dist/config/schema.d.ts.map +1 -1
  92. package/dist/config-6m0n7d84.js +59 -0
  93. package/dist/config-7cf004ag.js +59 -0
  94. package/dist/config-b98dp58n.js +59 -0
  95. package/dist/config-cf3djhqy.js +59 -0
  96. package/dist/config-entry.js +1 -1
  97. package/dist/config-wa7hm0w9.js +59 -0
  98. package/dist/deploy-1jfagtn9.js +1055 -0
  99. package/dist/deploy-2afw0jfg.js +1055 -0
  100. package/dist/deploy-2fzj68kq.js +1055 -0
  101. package/dist/deploy-57nzn9wj.js +1045 -0
  102. package/dist/deploy-asyryrvm.js +1055 -0
  103. package/dist/deploy-hc927rw6.js +1045 -0
  104. package/dist/deploy-pnnf8tgy.js +1045 -0
  105. package/dist/deploy-q33bw715.js +1055 -0
  106. package/dist/deploy-tmdgecs3.js +1055 -0
  107. package/dist/deploy-v0y8kczr.js +1055 -0
  108. package/dist/deploy-xhj6zbcx.js +1055 -0
  109. package/dist/dev-1mvcts8w.js +2515 -0
  110. package/dist/dev-2a283xts.js +2515 -0
  111. package/dist/dev-62nhytf8.js +2505 -0
  112. package/dist/dev-75acm2xj.js +2478 -0
  113. package/dist/dev-802rg9dp.js +2515 -0
  114. package/dist/dev-d1bb2t0f.js +2515 -0
  115. package/dist/dev-dwry8494.js +2489 -0
  116. package/dist/dev-g6112y4w.js +2515 -0
  117. package/dist/dev-h2kneh95.js +2496 -0
  118. package/dist/dev-kybq3mwr.js +2489 -0
  119. package/dist/dev-n8qndkyg.js +2512 -0
  120. package/dist/dev-p32fkbwf.js +2489 -0
  121. package/dist/dev-qm9d4mfh.js +2478 -0
  122. package/dist/dev-rcthnse5.js +2473 -0
  123. package/dist/dev-server/dev-server-state.d.ts +1 -0
  124. package/dist/dev-server/dev-server-state.d.ts.map +1 -1
  125. package/dist/dev-server/miniflare-bindings.d.ts +44 -1
  126. package/dist/dev-server/miniflare-bindings.d.ts.map +1 -1
  127. package/dist/dev-server/miniflare-dev-config.d.ts +1 -0
  128. package/dist/dev-server/miniflare-dev-config.d.ts.map +1 -1
  129. package/dist/dev-server/miniflare-log.d.ts +8 -0
  130. package/dist/dev-server/miniflare-log.d.ts.map +1 -1
  131. package/dist/dev-server/miniflare-worker-config.d.ts +31 -1
  132. package/dist/dev-server/miniflare-worker-config.d.ts.map +1 -1
  133. package/dist/dev-server/server.d.ts.map +1 -1
  134. package/dist/dev-server/vite-process.d.ts +1 -0
  135. package/dist/dev-server/vite-process.d.ts.map +1 -1
  136. package/dist/dev-tgwja5mz.js +2496 -0
  137. package/dist/doctor-2shhdak6.js +245 -0
  138. package/dist/doctor-5g73w40j.js +245 -0
  139. package/dist/doctor-gamefzcs.js +245 -0
  140. package/dist/doctor-rn53ctfs.js +245 -0
  141. package/dist/index-01kehw41.js +348 -0
  142. package/dist/index-06bg0z9y.js +185 -0
  143. package/dist/index-0d7tw5r4.js +136 -0
  144. package/dist/index-0m6e4mxz.js +133 -0
  145. package/dist/index-0vah20er.js +1410 -0
  146. package/dist/index-0wa0ebm1.js +68 -0
  147. package/dist/index-1714y3cz.js +1410 -0
  148. package/dist/index-1qs5gcm7.js +895 -0
  149. package/dist/index-29k04v43.js +574 -0
  150. package/dist/index-2jywf4pz.js +1372 -0
  151. package/dist/index-2qhk9nbx.js +1372 -0
  152. package/dist/index-2vq6bveq.js +574 -0
  153. package/dist/index-36h8gkhb.js +1088 -0
  154. package/dist/index-38fq7pww.js +560 -0
  155. package/dist/index-3bxqn033.js +1410 -0
  156. package/dist/index-3jme4hgw.js +1234 -0
  157. package/dist/index-3p7s9mk9.js +360 -0
  158. package/dist/index-47w35sft.js +244 -0
  159. package/dist/index-4by4c7rm.js +52 -0
  160. package/dist/index-4phjwd6h.js +412 -0
  161. package/dist/index-4z5jrw0j.js +594 -0
  162. package/dist/index-51mzqy0d.js +895 -0
  163. package/dist/index-53pqqpq9.js +74 -0
  164. package/dist/index-5enq8ntr.js +1766 -0
  165. package/dist/index-5fnq9r9m.js +1410 -0
  166. package/dist/index-5w9f2b17.js +695 -0
  167. package/dist/index-627srx16.js +45 -0
  168. package/dist/index-6bqgf5x8.js +227 -0
  169. package/dist/index-6xknvbyk.js +1088 -0
  170. package/dist/index-7ef3ktz5.js +1372 -0
  171. package/dist/index-7hpjfdzh.js +185 -0
  172. package/dist/index-8052df4m.js +627 -0
  173. package/dist/index-82epjzrr.js +1410 -0
  174. package/dist/index-82z7rvz6.js +1238 -0
  175. package/dist/index-8atc1yb9.js +68 -0
  176. package/dist/index-8tj0awnv.js +476 -0
  177. package/dist/index-8x745h59.js +1069 -0
  178. package/dist/index-9bawzcny.js +574 -0
  179. package/dist/index-9bjjqdfc.js +236 -0
  180. package/dist/index-9d7x3vfr.js +236 -0
  181. package/dist/index-9nf8zs4p.js +1069 -0
  182. package/dist/index-acwbmagz.js +412 -0
  183. package/dist/index-aqjdaem7.js +74 -0
  184. package/dist/index-b6448fd0.js +133 -0
  185. package/dist/index-b9j55r7q.js +240 -0
  186. package/dist/index-bdatd1za.js +1372 -0
  187. package/dist/index-c3nxftnp.js +699 -0
  188. package/dist/index-c643s0gv.js +488 -0
  189. package/dist/index-d2md1j3d.js +185 -0
  190. package/dist/index-dbr6bfz6.js +528 -0
  191. package/dist/index-dd1g0g7e.js +360 -0
  192. package/dist/index-dktb9az5.js +1372 -0
  193. package/dist/index-dm9q84c7.js +360 -0
  194. package/dist/index-f51mkh13.js +1088 -0
  195. package/dist/index-f86n1fpd.js +55 -0
  196. package/dist/index-fnk0tkw7.js +412 -0
  197. package/dist/index-g5aq66bj.js +1534 -0
  198. package/dist/index-gj5qh491.js +54 -0
  199. package/dist/index-gq39t0rx.js +895 -0
  200. package/dist/index-h5dqna7q.js +1410 -0
  201. package/dist/index-hjs9j2g9.js +895 -0
  202. package/dist/index-hn5nbxbt.js +147 -0
  203. package/dist/index-hpjh0qjx.js +1723 -0
  204. package/dist/index-hs6ekcfs.js +412 -0
  205. package/dist/index-jdzrvnfj.js +52 -0
  206. package/dist/index-jg720mq7.js +476 -0
  207. package/dist/index-jrzddxvt.js +2167 -0
  208. package/dist/index-kgstnk6g.js +239 -0
  209. package/dist/index-khnw972v.js +117 -0
  210. package/dist/index-kwqff3ba.js +1410 -0
  211. package/dist/index-m2v0fj08.js +74 -0
  212. package/dist/index-mjve6tqn.js +447 -0
  213. package/dist/index-mkxzgn0q.js +1372 -0
  214. package/dist/index-mzmq3v0d.js +1088 -0
  215. package/dist/index-ng9n3znd.js +1372 -0
  216. package/dist/index-nhbkm2ba.js +467 -0
  217. package/dist/index-nrfhk0k5.js +1088 -0
  218. package/dist/index-p0zppqxm.js +467 -0
  219. package/dist/index-pkxf6h87.js +895 -0
  220. package/dist/index-pqp4312v.js +52 -0
  221. package/dist/index-pw9jn6kz.js +574 -0
  222. package/dist/index-q31ne0xa.js +412 -0
  223. package/dist/index-qf2dkqxh.js +249 -0
  224. package/dist/index-qmtdf7k5.js +639 -0
  225. package/dist/index-qwgr4q7s.js +37 -0
  226. package/dist/index-rab2dfh3.js +494 -0
  227. package/dist/index-rz7rx80s.js +1410 -0
  228. package/dist/index-s37h3jgk.js +572 -0
  229. package/dist/index-sb705m7d.js +52 -0
  230. package/dist/index-syscwrjp.js +1576 -0
  231. package/dist/index-t14zr0ys.js +1063 -0
  232. package/dist/index-tjc99447.js +68 -0
  233. package/dist/index-v35460hf.js +574 -0
  234. package/dist/index-v7q00d1e.js +1410 -0
  235. package/dist/index-vkkmx4xe.js +1372 -0
  236. package/dist/index-vrps1gky.js +2202 -0
  237. package/dist/index-w4c9vmvg.js +1517 -0
  238. package/dist/index-wqd8n2qk.js +574 -0
  239. package/dist/index-x12e6fzy.js +476 -0
  240. package/dist/index-xagpz645.js +2199 -0
  241. package/dist/index-xbth1r6e.js +572 -0
  242. package/dist/index-xm9fqhcb.js +447 -0
  243. package/dist/index-y59hnmd0.js +132 -0
  244. package/dist/index-y7mkb00x.js +133 -0
  245. package/dist/index-z40mjts9.js +212 -0
  246. package/dist/index-z5k5bjc7.js +1218 -0
  247. package/dist/index-z73sytma.js +895 -0
  248. package/dist/index-zjv6apef.js +1410 -0
  249. package/dist/index.js +8 -8
  250. package/dist/init-cwpergap.js +180 -0
  251. package/dist/login-83bjfhvz.js +77 -0
  252. package/dist/login-ddw888xb.js +77 -0
  253. package/dist/login-e7pytkdc.js +77 -0
  254. package/dist/login-fe0brfcr.js +77 -0
  255. package/dist/login-h7sm5trm.js +77 -0
  256. package/dist/login-vd0m3xr4.js +77 -0
  257. package/dist/previews-2wfvsjfy.js +1337 -0
  258. package/dist/previews-31feb8r3.js +1337 -0
  259. package/dist/previews-3w4pxqby.js +1337 -0
  260. package/dist/previews-93ttrf5f.js +1337 -0
  261. package/dist/previews-bdrefjzx.js +1337 -0
  262. package/dist/previews-cfcn56b4.js +1337 -0
  263. package/dist/previews-mssq1hrm.js +1337 -0
  264. package/dist/previews-tcaz1gt8.js +1337 -0
  265. package/dist/productions-4h80j2c7.js +505 -0
  266. package/dist/productions-86jaqt7m.js +505 -0
  267. package/dist/productions-bn2q31my.js +505 -0
  268. package/dist/productions-dv8g7f6g.js +505 -0
  269. package/dist/productions-e2m9s4tr.js +505 -0
  270. package/dist/productions-fgshs1m7.js +505 -0
  271. package/dist/productions-hphmt68n.js +505 -0
  272. package/dist/productions-vhq7yx86.js +505 -0
  273. package/dist/runtime/index.js +8 -8
  274. package/dist/secrets/local-secrets.d.ts +46 -0
  275. package/dist/secrets/local-secrets.d.ts.map +1 -0
  276. package/dist/secrets-8wcj47nh.js +91 -0
  277. package/dist/secrets-b2ww34ta.js +91 -0
  278. package/dist/secrets-b7g4z621.js +91 -0
  279. package/dist/shims/local-media-bindings.d.ts +19 -0
  280. package/dist/shims/local-media-bindings.d.ts.map +1 -0
  281. package/dist/shims/local-worker-loader.d.ts +3 -0
  282. package/dist/shims/local-worker-loader.d.ts.map +1 -0
  283. package/dist/sveltekit/index.js +163 -26
  284. package/dist/sveltekit/local-bindings.d.ts +4 -0
  285. package/dist/sveltekit/local-bindings.d.ts.map +1 -0
  286. package/dist/sveltekit/platform.d.ts +8 -0
  287. package/dist/sveltekit/platform.d.ts.map +1 -1
  288. package/dist/test/ai-search.d.ts +39 -0
  289. package/dist/test/ai-search.d.ts.map +1 -0
  290. package/dist/test/binding-hints.d.ts.map +1 -1
  291. package/dist/test/cf.d.ts +3 -3
  292. package/dist/test/containers.d.ts +87 -0
  293. package/dist/test/containers.d.ts.map +1 -0
  294. package/dist/test/index.d.ts +4 -1
  295. package/dist/test/index.d.ts.map +1 -1
  296. package/dist/test/index.js +2833 -543
  297. package/dist/test/local-worker-loader.d.ts +3 -0
  298. package/dist/test/local-worker-loader.d.ts.map +1 -0
  299. package/dist/test/offline-bindings.d.ts +65 -0
  300. package/dist/test/offline-bindings.d.ts.map +1 -0
  301. package/dist/test/queue.d.ts.map +1 -1
  302. package/dist/test/remote-ai.d.ts.map +1 -1
  303. package/dist/test/should-skip.d.ts +14 -0
  304. package/dist/test/should-skip.d.ts.map +1 -1
  305. package/dist/test/simple-context-bindings.d.ts.map +1 -1
  306. package/dist/test/simple-context-durable-objects.d.ts.map +1 -1
  307. package/dist/test/simple-context-gateway-script.d.ts +1 -1
  308. package/dist/test/simple-context-gateway-script.d.ts.map +1 -1
  309. package/dist/test/simple-context-lifecycle.d.ts.map +1 -1
  310. package/dist/test/simple-context-mfconfig.d.ts +4 -1
  311. package/dist/test/simple-context-mfconfig.d.ts.map +1 -1
  312. package/dist/test/simple-context-multi-worker.d.ts.map +1 -1
  313. package/dist/test/simple-context-startup.d.ts.map +1 -1
  314. package/dist/test/tail.d.ts.map +1 -1
  315. package/dist/test/utilities/artifacts.d.ts +11 -0
  316. package/dist/test/utilities/artifacts.d.ts.map +1 -0
  317. package/dist/test/utilities/context.d.ts +39 -0
  318. package/dist/test/utilities/context.d.ts.map +1 -0
  319. package/dist/test/utilities/d1.d.ts +21 -0
  320. package/dist/test/utilities/d1.d.ts.map +1 -0
  321. package/dist/test/utilities/env.d.ts +40 -0
  322. package/dist/test/utilities/env.d.ts.map +1 -0
  323. package/dist/test/utilities/kv.d.ts +11 -0
  324. package/dist/test/utilities/kv.d.ts.map +1 -0
  325. package/dist/test/utilities/media.d.ts +16 -0
  326. package/dist/test/utilities/media.d.ts.map +1 -0
  327. package/dist/test/utilities/platform.d.ts +38 -0
  328. package/dist/test/utilities/platform.d.ts.map +1 -0
  329. package/dist/test/utilities/queue.d.ts +5 -0
  330. package/dist/test/utilities/queue.d.ts.map +1 -0
  331. package/dist/test/utilities/r2.d.ts +12 -0
  332. package/dist/test/utilities/r2.d.ts.map +1 -0
  333. package/dist/test/utilities/workflows.d.ts +26 -0
  334. package/dist/test/utilities/workflows.d.ts.map +1 -0
  335. package/dist/test/utilities.d.ts +10 -106
  336. package/dist/test/utilities.d.ts.map +1 -1
  337. package/dist/types-2ejrbba1.js +695 -0
  338. package/dist/types-7jkbm95a.js +695 -0
  339. package/dist/types-a2fk9yns.js +695 -0
  340. package/dist/types-dyb3c6zw.js +695 -0
  341. package/dist/types-e2n9f3pd.js +695 -0
  342. package/dist/types-j4s6qcrc.js +695 -0
  343. package/dist/utils/send-email.d.ts.map +1 -1
  344. package/dist/utils/send-email.js +1 -1
  345. package/dist/vite/index.js +6 -6
  346. package/dist/vite/plugin-context.d.ts.map +1 -1
  347. package/dist/worker-663em30d.js +513 -0
  348. package/dist/worker-argxc7fb.js +513 -0
  349. package/dist/worker-entry/composed-worker.d.ts.map +1 -1
  350. package/dist/worker-entry/surface-paths.d.ts +2 -0
  351. package/dist/worker-entry/surface-paths.d.ts.map +1 -1
  352. package/dist/worker-fcdsnj14.js +513 -0
  353. package/dist/worker-fk42rzse.js +513 -0
  354. package/dist/worker-jkemk8d2.js +513 -0
  355. package/dist/worker-m4ze8djx.js +513 -0
  356. package/dist/worker-wnan5dca.js +513 -0
  357. package/dist/worker-yw3atfb1.js +513 -0
  358. package/dist/workflows/local-workflow-entrypoints.d.ts +7 -0
  359. package/dist/workflows/local-workflow-entrypoints.d.ts.map +1 -0
  360. package/package.json +13 -12
package/README.md CHANGED
@@ -1,957 +1,375 @@
1
- # Devflare
2
-
3
- **Build Cloudflare Workers like an application, not a pile of glue.**
4
-
5
- Devflare is a developer-first layer on top of Cloudflare Workers, Miniflare, Bun, Vite, and Wrangler-compatible config.
6
-
7
- It gives you:
8
-
9
- - typed config with `defineConfig()`
10
- - convention-friendly worker surfaces
11
- - local orchestration for multi-surface Worker apps
12
- - first-class Durable Object and multi-worker workflows
13
- - test helpers that mirror real handler surfaces
14
- - worker-safe runtime helpers under `devflare/runtime`
15
- - optional Vite and SvelteKit integration when your package actually uses them
16
-
17
- Miniflare gives you a local runtime.
18
-
19
- Devflare turns that runtime into a **coherent development system**.
20
-
21
- For the deeper public contract, caveats, and current feature boundaries, see [`LLM.md`](./LLM.md).
22
-
23
- ---
24
-
25
- ## Monorepo contributor workflow
26
-
27
- When you are working on `packages/devflare` inside this monorepo, use the repo-root Turbo scripts instead of assembling ad-hoc commands by hand:
28
-
29
- - `bun run devflare:dev`
30
- - `bun run devflare:test:watch`
31
- - `bun run devflare:build`
32
- - `bun run devflare:typecheck`
33
- - `bun run devflare:test`
34
- - `bun run devflare:types`
35
- - `bun run devflare:check`
36
- - `bun run devflare:ci`
37
-
38
- These scripts intentionally keep the default shared lane focused on the parts of the workspace that are currently stable in local development and CI. In particular, the shared test lane excludes `@devflare/case5-multi-worker`, and the shared check lane stays centered on `apps/documentation` because `cases/case18` still expects Cloudflare-backed resource resolution outside the default contributor workflow.
39
-
40
- ---
41
-
42
- ## Install
43
-
44
- For a worker-only project, the smallest install is just Devflare:
45
-
46
- ```bash
47
- bun add -d devflare vite @cloudflare/vite-plugin
48
- ```
49
- A local `vite.config.*` opts that package into Vite-backed flows. Without one, Devflare stays in worker-only mode.
50
-
51
- ---
52
-
53
- ## Quick start
54
-
55
- ### 1. Create a config
56
-
57
- ```ts
58
- // devflare.config.ts
59
- import { defineConfig } from 'devflare/config'
60
-
61
- export default defineConfig({
62
- name: 'hello-worker',
63
- compatibilityDate: '2026-03-17',
64
- files: {
65
- fetch: 'src/fetch.ts'
66
- }
67
- })
68
- ```
69
-
70
- Use `devflare/config` for config files so Bun only loads the lightweight config helpers instead of the full Node-side Devflare barrel.
71
-
72
- ### 2. Add a fetch handler
73
-
74
- ```ts
75
- // src/fetch.ts
76
- import type { FetchEvent } from 'devflare/runtime'
77
-
78
- export async function fetch({ url }: FetchEvent): Promise<Response> {
79
- return new Response(`Hello from Devflare: ${url.pathname}`)
80
- }
81
- ```
82
-
83
- ### 3. Generate types
84
-
85
- ```bash
86
- bunx --bun devflare types
87
- ```
88
-
89
- ### 4. Start development
90
-
91
- ```bash
92
- bunx --bun devflare dev
93
- ```
94
-
95
- ### 5. Add a test
96
-
97
- ```ts
98
- // tests/worker.test.ts
99
- import { beforeAll, afterAll, describe, expect, test } from 'bun:test'
100
- import { createTestContext, cf } from 'devflare/test'
101
- import { env } from 'devflare'
102
-
103
- beforeAll(() => createTestContext())
104
- afterAll(() => env.dispose())
105
-
106
- describe('hello-worker', () => {
107
- test('GET / returns text', async () => {
108
- const response = await cf.worker.get('/')
109
- expect(response.status).toBe(200)
110
- expect(await response.text()).toBe('Hello from Devflare')
111
- })
112
- })
113
- ```
114
-
115
- ---
116
-
117
- ## Package entrypoints
118
-
119
- Use subpaths intentionally.
120
-
121
- | Import | Use for |
122
- |---|---|
123
- | `devflare` | main package entrypoint: `defineConfig`, `defineWorker`, `ref()`, the unified `env`/`ctx`/`event`/`locals` proxies, `sequence`, `defineFetchHandler`, decorators |
124
- | `devflare/config` | lightweight config-only entry for `devflare.config.ts` files (Bun loads only the config helpers, not the full Node-side barrel) |
125
- | `devflare/runtime` | worker-safe runtime helpers: strict `env`, `ctx`, `event`, `locals`, event types/getters, middleware helpers |
126
- | `devflare/test` | `createTestContext`, `cf.*`, mock helpers (`createMockKV`/`createMockD1`/`createMockR2`/`createMockEnv`/`createMockTestContext`/`withTestContext`) |
127
- | `devflare/vite` | Vite integration |
128
- | `devflare/sveltekit` | SvelteKit integration |
129
- | `devflare/cloudflare` | Cloudflare account/auth/usage/limits/preferences helpers |
130
- | `devflare/decorators` | decorators only |
131
-
132
- Internal bridge and transform helpers are intentionally not re-exported from bare `'devflare'`. If you previously imported them from the main entry, switch to the matching subpath — see "Public API surface and migration notes" below.
133
-
134
- ### Runtime import rule of thumb
135
-
136
- - use `import { env } from 'devflare/runtime'` for **strict request-scoped runtime access**
137
- - use `import { env } from 'devflare'` when you want the **unified proxy** that can fall back to test or bridge context outside a live request
138
-
139
- The reduced worker-safe main entry for `devflare` is selected through the package `browser` export condition. `devflare/runtime` is the direct worker-safe runtime subpath.
140
-
141
- ---
142
-
143
- ## Event-first handlers
144
-
145
- Fresh Devflare code should be event-first:
146
-
147
- - `fetch(event: FetchEvent)`
148
- - `queue(event: QueueEvent)`
149
- - `scheduled(event: ScheduledEvent)`
150
- - `email(event: EmailEvent)`
151
- - Durable Object lifecycle handlers with their matching event types
152
-
153
- Devflare stores the active event in `AsyncLocalStorage`, and Devflare-managed entrypoints establish that context for you before your handler runs. That includes generated worker wrappers, the local dev server, and `createTestContext()` helper surfaces.
154
-
155
- Helpers deeper in the same call trail can recover the current surface with getters like:
156
-
157
- - `getFetchEvent()`
158
- - `getQueueEvent()`
159
- - `getScheduledEvent()`
160
- - `getEmailEvent()`
161
- - `getDurableObjectFetchEvent()`
162
-
163
- Every getter also exposes `.safe()`, which returns `null` instead of throwing.
164
-
165
- In normal app code you should not need to call `runWithEventContext()` or `runWithContext()` yourself.
166
-
167
- ---
168
-
169
- ## HTTP structure that matches the runtime today
170
-
171
- The built-in HTTP story now has **two cooperating layers**:
172
-
173
- 1. an optional global fetch module at `src/fetch.ts`
174
- 2. a built-in file router rooted at `src/routes/**`
175
-
176
- Use `src/fetch.ts` for request-wide middleware and whole-app HTTP concerns.
177
- Use `src/routes/**` for leaf handlers.
178
-
179
- ### Request-wide middleware
180
-
181
- Use `sequence(...)` with a single exported primary fetch entry:
182
-
183
- ```ts
184
- import { sequence } from 'devflare/runtime'
185
- import type { FetchEvent, ResolveFetch } from 'devflare/runtime'
186
-
187
- async function corsHandle(event: FetchEvent, resolve: ResolveFetch): Promise<Response> {
188
- if (event.request.method === 'OPTIONS') {
189
- return new Response(null, {
190
- headers: {
191
- 'Access-Control-Allow-Origin': '*',
192
- 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
193
- 'Access-Control-Allow-Headers': 'Content-Type, Authorization'
194
- }
195
- })
196
- }
197
-
198
- const response = await resolve(event)
199
- const next = new Response(response.body, response)
200
- next.headers.set('Access-Control-Allow-Origin', '*')
201
- return next
202
- }
203
-
204
- async function appFetch({ url }: FetchEvent): Promise<Response> {
205
- return Response.json({ path: url.pathname })
206
- }
207
-
208
- export const handle = sequence(corsHandle, appFetch)
209
- ```
210
-
211
- Important rules:
212
-
213
- - `fetch` and `handle` are two names for the same primary HTTP entry
214
- - export **one** of them from a given module, never both
215
- - if `src/fetch.ts` exports same-module `GET()` / `POST()` handlers, those run before file routes for matching methods
216
- - for route-tree apps, keep `src/fetch.ts` focused on request-wide middleware and put leaf handlers in `src/routes/**`
217
-
218
- ### File router
219
-
220
- `src/routes/**` is now a real built-in router.
221
-
222
- By default, Devflare discovers `src/routes/**` automatically when that directory exists.
223
-
224
- You can customize or disable it with `files.routes`:
225
-
226
- ```ts
227
- export default {
228
- name: 'api-worker',
229
- files: {
230
- fetch: 'src/fetch.ts',
231
- routes: {
232
- dir: 'src/routes',
233
- prefix: '/api'
234
- }
235
- }
236
- }
237
- ```
238
-
239
- - `files.routes.dir` changes the route root
240
- - `files.routes.prefix` mounts the route tree under a fixed prefix
241
- - `files.routes: false` disables automatic route discovery entirely
242
-
243
- Route conventions:
244
-
245
- - `src/routes/index.ts` `/`
246
- - `src/routes/users/index.ts` → `/users`
247
- - `src/routes/users/[id].ts` `/users/:id`
248
- - `src/routes/blog/[...slug].ts` `/blog/*` with `params.slug = 'a/b'`
249
- - `src/routes/docs/[[...slug]].ts` optional catch-all, including `/docs`
250
- - files or directories that start with `_` are ignored so you can keep route-local helpers nearby
251
-
252
- Route module exports use the same fetch-module rules as `src/fetch.ts`:
253
-
254
- - `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`, `ALL`
255
- - route-local `fetch(event)` / `handle(event, resolve)` if you want per-route middleware
256
- - `HEAD` falls back to `GET` when no explicit `HEAD` export exists
257
-
258
- Route params are available on `event.params`.
259
-
260
- ```ts
261
- // src/routes/users/[id].ts
262
- export async function GET(event): Promise<Response> {
263
- return Response.json({ id: event.params.id })
264
- }
265
- ```
266
-
267
- ### Resolution order
268
-
269
- When a request comes in, Devflare resolves HTTP in this order:
270
-
271
- 1. create the initial fetch event and populate `event.params` from the matched file route, if any
272
- 2. run the primary `src/fetch.ts` `fetch` / `handle` export if present
273
- 3. inside `resolve(event)`, try same-module method handlers from `src/fetch.ts`
274
- 4. if no same-module handler matched, dispatch to the matched route module from `src/routes/**`
275
- 5. return `404 Not Found` if nothing matched
276
-
277
- That means global middleware can see `event.params`, while route files remain the main leaf-handler story.
278
-
279
- For example:
280
-
281
- ```ts
282
- // src/fetch.ts
283
- import { sequence } from 'devflare/runtime'
284
-
285
- export const handle = sequence(async (event, resolve) => {
286
- const response = await resolve(event)
287
- const next = new Response(response.body, response)
288
- next.headers.set('x-user-id', event.params.id ?? 'none')
289
- return next
290
- })
291
- ```
292
-
293
- ---
294
-
295
- ## Config highlights
296
-
297
- Devflare looks for these config filenames:
298
-
299
- - `devflare.config.ts`
300
- - `devflare.config.mts`
301
- - `devflare.config.js`
302
- - `devflare.config.mjs`
303
-
304
- The most important top-level keys are:
305
-
306
- - `name`
307
- - `accountId`
308
- - `compatibilityDate`
309
- - `compatibilityFlags`
310
- - `previews`
311
- - `files`
312
- - `bindings`
313
- - `triggers`
314
- - `vars`
315
- - `secrets`
316
- - `routes`
317
- - `wsRoutes`
318
- - `assets`
319
- - `limits`
320
- - `observability`
321
- - `migrations`
322
- - `rolldown`
323
- - `vite`
324
- - `env`
325
- - `wrangler.passthrough`
326
-
327
- ### `vars` vs `secrets`
328
-
329
- Keep these separate:
330
-
331
- - `vars` are **string-valued config bindings** that compile into generated Wrangler config
332
- - `secrets` are **declarations of expected runtime secret bindings**
333
-
334
- `loadConfig()` loads the nearest workspace-root `.env` before evaluating `devflare.config.*`.
335
-
336
- When Devflare finds an ancestor `package.json` with `workspaces`, it uses that directory's `.env` file as the shared config-time source for nested packages. If no workspace root is found, it falls back to the nearest ancestor `.env`. Explicit process env values still win over `.env` entries.
337
-
338
- Important boundary:
339
-
340
- - `.env` is treated as a config/build-time input for `devflare.config.*` evaluation
341
- - Devflare does **not** currently provide first-class semantics for `.env.dev` or `.env.<name>`
342
- - Devflare does **not** currently provide a first-class `.dev.vars*` loader for worker-only dev mode or `createTestContext()`
343
- - example files like `.env.example` and `.dev.vars.example` are a team convention, not a Devflare feature
344
-
345
- Practical convention:
346
-
347
- - use `.env.example` for config-time/build-time variables read from `process.env`
348
- - use `.dev.vars.example` only if your project intentionally relies on upstream `.dev.vars` local-runtime workflows
349
- - keep non-secret infrastructure names such as R2 bucket names and D1 database names in `devflare.config.*`, not in `secrets` or ad-hoc CI env vars
350
-
351
- ### `config.env`
352
-
353
- `config.env` is a Devflare merge layer, not a raw Wrangler env mirror.
354
-
355
- When you select `--env name`, Devflare merges `config.env[name]` into the base config before compiling.
356
-
357
- ### D1 by name and resolved config reuse
358
-
359
- `bindings.d1` accepts three shapes:
360
-
361
- - `'database-name'`
362
- - `{ id: 'database-id' }`
363
- - `{ name: 'database-name' }`
364
-
365
- String shorthand is the stable-name form, so `'database-name'` is equivalent to `{ name: 'database-name' }`.
366
-
367
- Use string shorthand or `{ name }` when you want `devflare.config.*` to stay the source of truth for stable D1 naming.
368
-
369
- - local dev and tests normalize string and `{ name }` bindings into a stable local identifier, so you do **not** need Cloudflare auth just to run locally
370
- - `build`, `deploy`, `devflare/vite`, and `devflare config print` resolve string and `{ name }` bindings into a real Cloudflare D1 database id before they emit Wrangler-facing config
371
- - `compileConfig()` can only emit Wrangler `d1_databases` from concrete ids, so Node-side automation should call `loadResolvedConfig()` or `resolveConfigResources()` first
372
-
373
- That means stable names stay in config, while opaque Cloudflare ids are resolved only for the flows that actually need them.
374
-
375
- If you want to inspect or reuse those resolved values in automation, use either:
376
-
377
- - `bunx --bun devflare config print --json`
378
- - `bunx --bun devflare config print --json --format wrangler`
379
- - `loadResolvedConfig()` from Node-side tooling
380
-
381
- ```ts
382
- import { loadResolvedConfig } from 'devflare'
383
-
384
- const config = await loadResolvedConfig({
385
- cwd: process.cwd(),
386
- environment: 'production'
387
- })
388
-
389
- console.log(config.bindings?.r2?.ASSETS)
390
- console.log(config.bindings?.d1?.DB)
391
- ```
392
-
393
- If you need Cloudflare account/resource data while computing config, use an async config with `devflare/cloudflare` helpers:
394
-
395
- ```ts
396
- import { defineConfig } from 'devflare/config'
397
- import { account } from 'devflare/cloudflare'
398
-
399
- export default defineConfig(async () => {
400
- const primary = await account.getPrimaryAccount()
401
- const buckets = await account.r2(primary.id)
402
-
403
- if (!buckets.some((bucket) => bucket.name === 'app-assets')) {
404
- throw new Error('Missing R2 bucket "app-assets" in the selected Cloudflare account')
405
- }
406
-
407
- return {
408
- accountId: primary.id,
409
- name: 'app-worker',
410
- compatibilityDate: '2026-03-17',
411
- bindings: {
412
- d1: {
413
- DB: { name: 'app-db' }
414
- },
415
- r2: {
416
- ASSETS: 'app-assets'
417
- }
418
- }
419
- }
420
- })
421
- ```
422
-
423
- ### Native config vs Wrangler coverage
424
-
425
- Devflare natively models the Worker config it actively composes around:
426
-
427
- - handler/file surfaces
428
- - core bindings and service composition
429
- - routes, assets, migrations, observability, and limits
430
- - Vite and Rolldown metadata
431
- - environment overlays
432
-
433
- It does **not** try to re-model every Wrangler key as a first-class Devflare schema field.
434
- For unsupported Wrangler options, use `wrangler.passthrough`.
435
-
436
- Current compile order is:
437
-
438
- 1. Devflare compiles native config into Wrangler-compatible output
439
- 2. `wrangler.passthrough` is shallow-merged on top
440
- 3. if the same key exists in both places, the passthrough value wins
441
-
442
- ```ts
443
- export default defineConfig({
444
- name: 'advanced-worker',
445
- files: {
446
- fetch: 'src/fetch.ts'
447
- },
448
- wrangler: {
449
- passthrough: {
450
- placement: {
451
- mode: 'smart'
452
- }
453
- }
454
- }
455
- })
456
- ```
457
-
458
- Special case: `wrangler.passthrough.main` tells higher-level `build`, `deploy`, and `devflare/vite` flows to stop generating a composed `.devflare/worker-entrypoints/main.ts` and use your explicit main entry instead.
459
-
460
- ---
461
-
462
- ## Bindings
463
-
464
- Devflare natively models:
465
-
466
- - KV
467
- - D1
468
- - R2
469
- - Durable Objects
470
- - Queues
471
- - Services
472
- - AI
473
- - Vectorize
474
- - Hyperdrive
475
- - Browser Rendering
476
- - Analytics Engine
477
- - `sendEmail`
478
-
479
- ### Caveats worth knowing up front
480
-
481
- - KV, D1, R2, Durable Objects, queues, and the core test/runtime flow are the strongest surfaces
482
- - AI and Vectorize are remote-oriented bindings
483
- - named service entrypoints are modeled at the Devflare layer, but validate generated deployment output if they are critical to your app
484
- - browser bindings use a named-map authoring shape such as `browser: { BROWSER: 'browser' }`, but current compile/deploy flows allow exactly one browser binding because Wrangler only supports one
485
- - `sendEmail` is modeled through config compilation, generated env types, and local runtime/test flows
486
- - R2 bindings are real in local dev/test/runtime flows, but Devflare does **not** publish a stable browser-facing local bucket URL contract; browser-visible local asset flows should go through your Worker routes
487
-
488
- For R2 delivery strategy guidance, use the `R2 uploads & delivery` page in the documentation site.
489
-
490
- For D1 and Hyperdrive, prefer stable config names when you can:
491
-
492
- ```ts
493
- export default {
494
- bindings: {
495
- d1: {
496
- DB: { name: 'app-db' },
497
- AUDIT: { id: 'existing-d1-id' }
498
- },
499
- hyperdrive: {
500
- DB: 'app-postgres',
501
- ANALYTICS_DB: { id: 'existing-hyperdrive-id' }
502
- },
503
- r2: {
504
- ASSETS: 'app-assets'
505
- }
506
- }
507
- }
508
- ```
509
-
510
- Use `.env*` and `secrets` for values that are actually secret or genuinely process-specific. Do **not** move stable bucket/database/Hyperdrive names into env vars just to make other tooling happy.
511
-
512
- ---
513
-
514
- ## Dev, build, deploy, Vite, and Rolldown
515
-
516
- Devflare is worker-only first.
517
-
518
- ### Mode selection
519
-
520
- - a local `vite.config.*` or a non-empty `config.vite` opts the current package into **Vite-backed** flows
521
- - Vite-related dependencies without either a local config or inline `config.vite` do **not** switch the package into Vite mode
522
- - without a local `vite.config.*` and without inline `config.vite`, `dev`, `build`, and `deploy` stay in **worker-only** mode
523
-
524
- ### Mental model
525
-
526
- Vite and Rolldown both matter here, but they do different jobs:
527
-
528
- - **Vite** is the optional outer app/framework host. Devflare enters Vite-backed mode when the current package has a local `vite.config.*` or a non-empty `config.vite`, and then Devflare merges that config into the actual Vite config it runs.
529
- - **Rolldown** is the inner builder Devflare uses when Devflare itself needs to transform Worker code into runnable bundles. Today that covers worker-only main-worker bundles and Durable Object bundles.
530
-
531
- Short version:
532
-
533
- - no local `vite.config.*` and no inline `config.vite` → no Vite process; Devflare stays worker-only
534
- - `.svelte` imported by a worker-only fetch/route/queue/scheduled/email surface or by a Durable Object → that compilation belongs to the Rolldown plugin pipeline, not to the main Vite app build
535
- - generated `.devflare/worker-entrypoints/main.ts` is separate Devflare glue that composes worker surfaces when needed
536
-
537
- ### Current behavior that matters
538
-
539
- - worker-only `dev` is a real first-class path
540
- - `build` and `deploy` skip Vite only when the current package has no effective Vite config (`vite.config.*` or inline `config.vite`)
541
- - when Devflare runs Vite, `config.vite` is merged into the actual Vite config, and Devflare writes a generated `.devflare/vite.config.mjs` when it needs one
542
- - higher-level `build`, `deploy`, and `devflare/vite` flows currently synthesize `.devflare/worker-entrypoints/main.ts` whenever a fetch, route tree, queue, scheduled, or email surface is discovered
543
- - `wrangler.passthrough.main` disables that composed-entry generation path
544
- - in worker-only mode, Devflare now bundles the composed main worker to `.devflare/worker-entrypoints/main.js` via Rolldown before handing it to Miniflare or Wrangler
545
- - Rolldown still rebuilds Durable Object worker code in unified Vite dev flows where Vite hosts the outer app
546
-
547
- For the full contract-level explanation and a concrete Rolldown + Svelte example, see the generated [`LLM.md`](./LLM.md) handbook entries for workflow modes and Svelte in workers.
548
-
549
- ---
550
-
551
- ## Deploys, previews, tokens, and GitHub Actions
552
-
553
- ### Production deploys vs same-Worker previews
554
-
555
- `devflare deploy` publishes production the usual Wrangler way.
556
-
557
- `devflare deploy --preview` is different: it uploads a **new version of the same Worker** with `wrangler versions upload` instead of creating a separate Worker environment.
558
-
559
- Named preview deploys are now the primary preview model:
560
-
561
- - each preview scope deploys its own dedicated Worker (or Worker family)
562
- - preview-scoped bindings and resources can be assigned only to that scope
563
- - feature branches and PRs get stable preview URLs from the scope name itself
564
-
565
- Preview scope names should still be lowercase and dash-friendly so they map cleanly into Worker names and `workers.dev` URLs.
566
-
567
- Useful preview examples:
568
-
569
- ```bash
570
- bunx --bun devflare deploy --preview next
571
- bunx --bun devflare deploy --preview pr-42
572
- ```
573
-
574
- When available, Devflare prints the Worker version id and preview URL outputs after the deploy finishes.
575
-
576
- ### Login and preview scope helpers
577
-
578
- `devflare login` is the thin authentication wrapper for Cloudflare.
579
-
580
- - by default it reuses existing auth when Devflare can already resolve a Cloudflare API token
581
- - `devflare login --force` opens `wrangler login` again even when auth is already present
582
- - after login, Devflare prints the primary account when Cloudflare account discovery succeeds
583
-
584
- `devflare previews` is the config-aware preview-scope surface for dedicated preview Workers.
585
-
586
- Useful commands:
587
-
588
- ```bash
589
- bunx --bun devflare previews
590
- bunx --bun devflare previews bindings --scope next
591
- bunx --bun devflare previews cleanup --scope next --apply
592
- bunx --bun devflare previews cleanup --all --apply
593
- ```
594
-
595
- Current behavior:
596
-
597
- - `devflare previews` lists stable workers plus discovered dedicated preview scopes for the current worker family using live Cloudflare Worker names
598
- - `devflare previews bindings` resolves preview-scoped resources for one scope and shows how many deployed workers reference them
599
- - `devflare previews cleanup` deletes dedicated preview Workers plus preview-scoped KV, D1, R2, Queue, Vectorize, and reusable Hyperdrive resources for one scope or every discovered scope; it is a dry run unless `--apply` is present
600
- - `devflare deploy` still performs best-effort internal preview metadata synchronization after successful deploys so cleanup flows can remove deleted preview workers cleanly without extra CI glue
601
-
602
- ### Manage Devflare tokens
603
-
604
- `devflare tokens <bootstrap-token>` manages Devflare-owned account API tokens using a bootstrap token that already has Cloudflare API-token-management permission.
605
-
606
- The command:
607
-
608
- - resolves the effective account id from `--account`, workspace preference, or the bootstrap token's primary account
609
- - normalizes managed token names to the `devflare-` prefix, so `preview` becomes `devflare-preview` while `devflare-preview` stays unchanged
610
- - `--new [token-name]` prompts for a token name when it is omitted, then creates a new Devflare-managed account-owned token from the curated Devflare permission set
611
- - `--new [token-name] --all-flags` uses every reusable account-scoped permission group visible to the bootstrap token except `Account API Tokens*`, because Cloudflare does not allow sub-tokens to inherit token-management permission and account-owned tokens skip incompatible zone/user-scoped groups automatically
612
- - `--list` lists only the Devflare-managed tokens in the selected account
613
- - `--delete [token-name]` deletes the matching Devflare-managed token after normalizing the name to the `devflare-` prefix
614
- - `--delete-all` deletes every Devflare-managed token in the selected account while leaving non-Devflare account tokens untouched
615
- - prints a new token value once, because Cloudflare only returns the secret a single time
616
-
617
- Examples:
618
-
619
- ```bash
620
- bunx --bun devflare tokens <bootstrap-token> --new preview
621
- bunx --bun devflare tokens <bootstrap-token> --new preview --all-flags
622
- bunx --bun devflare tokens <bootstrap-token> --list
623
- bunx --bun devflare tokens <bootstrap-token> --delete preview
624
- bunx --bun devflare tokens <bootstrap-token> --delete-all
625
- ```
626
-
627
- ### Thin GitHub Action and caller workflows
628
-
629
- The repo ships a reusable composite action at [`.github/actions/devflare-deploy`](../../.github/actions/devflare-deploy).
630
-
631
- The repo also ships a shared workspace setup action at [`.github/actions/devflare-setup-workspace`](../../.github/actions/devflare-setup-workspace) so one workflow job can install dependencies once and then deploy multiple preview targets from the same checkout.
632
-
633
- The repo also ships a GitHub-feedback action at [`.github/actions/devflare-github-feedback`](../../.github/actions/devflare-github-feedback) for publishing deployment results back into GitHub.
634
-
635
- The action stays intentionally thin:
636
-
637
- - the caller workflow owns the runner, triggers, permissions, and environments
638
- - Cloudflare credentials must be passed in explicitly
639
- - by default, the action asks `devflare deploy` to verify Cloudflare control-plane state before the step is considered successful
640
- - the caller workflow should pass a deterministic `preview-scope`, such as the branch name or `pr-<number>`, for stable dedicated preview Worker naming across PR, push, and manual workflows
641
-
642
- The reporting split is also intentional:
643
-
644
- - GitHub PR feedback should use a stable PR comment because PRs are issue-backed conversations
645
- - GitHub branch feedback should use Deployments + deployment statuses because GitHub does not provide first-class branch comments
646
- - one preview workflow can publish both branch deployment feedback and the shared PR comment in the same run when a pushed branch already belongs to an open pull request
647
-
648
- Current action inputs that matter most:
649
-
650
- - `working-directory`
651
- - `environment`
652
- - `production`
653
- - `preview-scope`
654
- - `skip-setup`
655
- - `skip-install`
656
- - `verify-deployment` (defaults to `true`)
657
- - `cloudflare-api-token`
658
- - `cloudflare-account-id`
659
-
660
- When `verify-deployment` is enabled, the action fails if Devflare cannot confirm the uploaded version in Cloudflare, or for non-preview deploys, cannot confirm that a live deployment now references that version.
661
-
662
- Action outputs:
663
-
664
- - `preview-url`
665
- - `version-id`
666
- - `status`
667
- - `exit-code`
668
- - `log-excerpt`
669
-
670
- Those extra outputs are especially useful when the caller workflow uses `continue-on-error: true` on the deploy step so it can still post a failure comment or deployment status before failing the job.
671
-
672
- Minimal preview step:
673
-
674
- ```yaml
675
- - id: deploy
676
- uses: ./.github/actions/devflare-deploy
677
- with:
678
- working-directory: apps/documentation
679
- preview-scope: ${{ github.head_ref || github.ref_name }}
680
- cloudflare-api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
681
- cloudflare-account-id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
682
- ```
683
-
684
- This repository now keeps preview delivery in one shared workflow plus one production workflow:
685
-
686
- - [`.github/workflows/preview.yml`](../../.github/workflows/preview.yml) handles documentation + testing previews, push + PR lifecycle triggers, branch + PR targets, and cleanup flows from one place
687
- - [`.github/workflows/documentation-production.yml`](../../.github/workflows/documentation-production.yml) handles production deploys from the repository default branch plus GitHub deployment statuses
688
- - [`.github/workflow-examples/branch-preview-cleanup.example.yml`](../../.github/workflow-examples/branch-preview-cleanup.example.yml) remains as a copyable delete-triggered preview-scope cleanup template for downstream repos that want a smaller starting point
689
-
690
- The live workflows now rely on the deploy action's control-plane verification for deploy success.
691
-
692
- If you want other feedback modes in your own repo, the supported patterns are:
693
-
694
- - PR-only preview feedback: `mode: comment`
695
- - branch-only preview feedback: `mode: deployment`
696
- - combined branch deployment + PR comment feedback: either `mode: both` with `resolve-pr-from-ref: 'true'`, or separate deployment/comment steps inside one shared preview workflow when you want finer control over grouped PR comments
697
-
698
- Repository-specific runtime checks still exist where they are testing app
699
- behavior rather than deploy success. For example,
700
- [`preview.yml`](../../.github/workflows/preview.yml)
701
- deploys testing previews for both branch and PR scopes from one prepared job
702
- when a pushed branch already belongs to an open pull request, while still
703
- keeping its deployed-binding verification because it is validating runtime
704
- bindings and deployment-channel wiring rather than merely asking whether
705
- Cloudflare accepted the upload.
706
-
707
- For branch-scoped real preview deploys such as `apps/testing`, Devflare now
708
- automatically omits shared queue consumers from the deployed Wrangler config,
709
- and it omits cron triggers by default, when it detects the branch-preview
710
- strategy (`--env preview` plus branch scope, without `--preview`). That keeps
711
- previews from colliding on singleton Cloudflare resources while leaving the
712
- authoring config itself fully exhaustive for local dev, tests, and production
713
- deploys.
714
-
715
- If a branch-scoped preview really should keep its cron schedule, opt in with:
716
-
717
- ```ts
718
- export default defineConfig({
719
- previews: {
720
- includeCrons: true
721
- }
722
- })
723
- ```
724
-
725
- If those previews also need preview-owned Cloudflare resources, use
726
- `preview.scope()` in the config authoring layer:
727
-
728
- ```ts
729
- import { defineConfig, preview } from 'devflare/config'
730
-
731
- const pv = preview.scope()
732
-
733
- export default defineConfig({
734
- bindings: {
735
- kv: {
736
- CACHE: pv('my-cache-kv')
737
- },
738
- r2: {
739
- ASSETS: pv('my-assets-bucket')
740
- }
741
- }
742
- })
743
- ```
744
-
745
- Devflare resolves those opaque markers to base names outside preview
746
- environments, and to preview-scoped names such as `my-cache-kv-preview` (or a
747
- branch-derived suffix when `DEVFLARE_PREVIEW_BRANCH`, `DEVFLARE_PREVIEW_PR`, or
748
- `DEVFLARE_PREVIEW_IDENTIFIER` is present) for preview resolution and deploys.
749
- During `devflare deploy --env preview`, Devflare also provisions missing
750
- preview-scoped KV, D1, R2, Queue, and Vectorize resources automatically before
751
- the Wrangler deploy runs. Preview-scoped Hyperdrive names are reused when the
752
- matching preview config already exists, and otherwise Devflare falls back to the
753
- base Hyperdrive config because Cloudflare does not expose stored Hyperdrive
754
- credentials for cloning preview configs automatically. Use
755
- `devflare previews cleanup --env preview --apply` during PR-close or
756
- branch-delete cleanup to delete the preview-owned resources again.
757
- Service bindings created through `ref()` still follow the referenced worker
758
- names, so branch-scoped worker naming remains the way to isolate preview
759
- service bindings.
760
-
761
- ---
762
-
763
- ## Repo examples
764
-
765
- - [`apps/documentation/`](../../apps/documentation/) is the executable SvelteKit example for dev, build, preview deploys, production deploys, workflow automation, and browser validation
766
- - [`apps/testing/`](../../apps/testing/) is the exhaustive binding-matrix example for the config contract itself, including `preview.scope()`-driven preview resource names, production overrides where bindings differ by deployment channel, and a tiny `src/fetch.ts` smoke Worker exercised by repository integration tests through `devflare/test`
767
-
768
- ---
769
-
770
- ## Testing
771
-
772
- Use `devflare/test`.
773
-
774
- The high-level entrypoint is `createTestContext()`, and the unified helper surface is `cf`:
775
-
776
- - `cf.worker`
777
- - `cf.queue`
778
- - `cf.scheduled`
779
- - `cf.email`
780
- - `cf.tail`
781
-
782
- ### `createTestContext()` autodiscovery
783
-
784
- If you omit the config path, `createTestContext()` walks upward from the calling test file and looks for the nearest supported config filename:
785
-
786
- - `devflare.config.ts`
787
- - `devflare.config.mts`
788
- - `devflare.config.js`
789
- - `devflare.config.mjs`
790
-
791
- It also auto-detects conventional `src/fetch.ts`, `src/queue.ts`, `src/scheduled.ts`, `src/email.ts`, built-in `src/routes/**`, and `src/tail.ts` when they are present.
792
-
793
- ### Important current testing truth
794
-
795
- - `cf.worker.fetch()` returns when the handler resolves and does **not** eagerly wait for all `waitUntil()` work
796
- - `cf.worker.fetch()` and the shorthand helpers dispatch through both `src/fetch.ts` and built-in `src/routes/**` file routes when present
797
- - `cf.queue.trigger()` and `cf.scheduled.trigger()` do wait for queued background work before they return
798
- - `cf.tail.trigger()` is exported, and `createTestContext()` auto-detects `src/tail.ts` when present; there is still no public `files.tail` config key
799
- - `cf.email.send()` invokes the configured email handler in `createTestContext()`-backed tests and otherwise falls back to the local email endpoint; for ingress-fidelity-sensitive flows, validate with a higher-level integration test
800
- - remote mode is mainly about AI and Vectorize, not “make every binding remote”
801
-
802
- ### Choosing pure mocks vs Miniflare-backed `createTestContext()`
803
-
804
- `devflare/test` ships two complementary lanes. Pick by what you are validating:
805
-
806
- - **Pure mocks** (`createMockKV`, `createMockD1`, `createMockR2`, `createMockEnv`, `createMockTestContext`, `withTestContext`):
807
- - Fast, in-process, no Miniflare boot
808
- - Use when you are unit-testing a function that reads or writes a single binding and you control the inputs
809
- - Behavior is approximate: KV is binary-safe, D1 supports `SELECT`/`INSERT` per-table fixtures, R2 stores bytes — anything beyond those primitives will diverge from production
810
- - **`createTestContext()` (Miniflare-backed)**:
811
- - Boots a real Workers runtime locally with your `devflare.config.ts`
812
- - Use when you are testing handler dispatch, multi-binding flows, queues/scheduled/email/Durable Objects, route discovery, middleware composition, or anything that needs accurate Workers semantics
813
- - Slower per test, so reuse one context per test file when possible
814
-
815
- Rule of thumb: if the assertion is "given inputs X, my function returns Y", reach for the mocks. If the assertion is "the worker behaves correctly when this binding/handler/route fires", use `createTestContext()`.
816
-
817
- ---
818
-
819
- ## Public API surface and migration notes
820
-
821
- Devflare's bare `'devflare'` import is intentionally narrow and only exposes the documented public API. Internal helpers for the bridge, transform, and test runner are reachable from dedicated subpaths instead:
822
-
823
- - `devflare` — primary public API (`defineConfig`, `defineWorker`, `sequence`, `defineFetchHandler`, runtime context accessors, etc.)
824
- - `devflare/test` — `createTestContext`, `cf`, mock factories
825
- - `devflare/runtime` — runtime accessors (`env`, `ctx`, `event`, `locals`, helpers)
826
- - `devflare/cloudflare` — Cloudflare API helpers
827
- - `devflare/sveltekit` — SvelteKit platform glue
828
- - `devflare/decorators` — `@durableObject` and other decorators
829
-
830
- If you previously imported internal helpers (e.g., bridge serialization or transform helpers) from bare `'devflare'`, switch to the matching subpath. The internal modules are not considered stable public API and may change between minor versions.
831
-
832
- ---
833
-
834
- ## CLI
835
-
836
- Every top-level command supports `--help`, and nested command groups support both:
837
-
838
- - `bunx --bun devflare <command> --help`
839
- - `bunx --bun devflare <command> <subcommand> --help`
840
- - `bunx --bun devflare help <command> [subcommand]`
841
-
842
- | Command | What it does |
843
- |---|---|
844
- | `devflare init` | scaffold a project using `src/fetch.ts` and explicit `files.fetch` |
845
- | `devflare dev` | start the worker-only dev server, enabling Vite only when the current package has a local `vite.config.*` |
846
- | `devflare build` | resolve config locally, preserve named bindings in generated build artifacts, and run `vite build` only for Vite-backed packages |
847
- | `devflare deploy` | build or reuse a prior artifact via `--build`, provision named deploy resources, and deploy with Wrangler, including same-Worker preview uploads via `--preview` |
848
- | `devflare types` | generate `env.d.ts` |
849
- | `devflare doctor` | check project configuration plus generated artifact locations such as `.devflare/wrangler.jsonc`, `.devflare/build/wrangler.jsonc`, and `.wrangler/deploy/config.json` |
850
- | `devflare config` | print resolved Devflare config or resolved Wrangler JSON |
851
- | `devflare account` | inspect accounts, resources, usage, and limits |
852
- | `devflare login` | authenticate with Cloudflare via Wrangler, reusing existing auth unless `--force` is passed |
853
- | `devflare previews` | inspect and clean dedicated preview Workers plus preview-owned scope resources |
854
- | `devflare productions` | inspect live production Workers, list recent versions, roll back, or delete a live Worker script |
855
- | `devflare worker` | run Worker control-plane actions such as remote renaming and local config sync |
856
- | `devflare tokens` | create, list, and delete Devflare-managed account-owned tokens from a bootstrap token with API-token-management permission |
857
- | `devflare help` | print the command overview or the detailed help page for a command path |
858
- | `devflare version` | print the installed Devflare version |
859
- | `devflare ai` | show Workers AI model pricing info |
860
- | `devflare remote` | manage remote test mode |
861
-
862
- Command defaults:
863
-
864
- - `devflare config` defaults to `devflare config print`
865
- - `devflare previews` defaults to `devflare previews list`
866
- - `devflare productions` defaults to `devflare productions list`
867
-
868
- ### Command groups
869
-
870
- | Group | Subcommands / operations |
871
- |---|---|
872
- | `account` | `info`, `workers`, `kv`, `d1`, `r2`, `vectorize`, `usage`, `limits`, `limits set`, `limits enable`, `limits disable`, `global`, `workspace` |
873
- | `config` | `print` |
874
- | `previews` | `list`, `bindings`, `cleanup` |
875
- | `productions` | `list`, `versions`, `rollback`, `delete` |
876
- | `remote` | `status`, `enable`, `disable` |
877
- | `worker` | `rename` |
878
- | `tokens` | `--list`, `--new`, `--roll`, `--delete`, `--delete-all` (flag-driven operations rather than subcommands) |
879
-
880
- Useful flags:
881
-
882
- - `build --env <name>`
883
- - `deploy --build <path>`
884
- - `deploy --env <name>`
885
- - `deploy --dry-run`
886
- - `deploy --preview <name>`
887
- - `login --force`
888
- - `previews`
889
- - `previews cleanup --scope <name> --apply`
890
- - `config print --json`
891
- - `config print --format wrangler`
892
- - `types --output <path>`
893
- - `doctor --config <path>`
894
- - `account --account <id>`
895
- - `tokens <bootstrap-token> --new [name]`
896
- - `tokens <bootstrap-token> --list`
897
-
898
- Recommended invocation style:
899
-
900
- ```bash
901
- bunx --bun devflare dev
902
- bunx --bun devflare types
903
- bunx --bun devflare build
904
- bunx --bun devflare help account limits set
905
- bunx --bun devflare previews cleanup --help
906
- ```
907
-
908
- ---
909
-
910
- ## Generated artifacts
911
-
912
- Treat these as generated output, not source of truth:
913
-
914
- - `.devflare/wrangler.jsonc`
915
- - `.devflare/build/wrangler.jsonc`
916
- - `.devflare/worker-entrypoints/main.ts`
917
- - `.devflare/worker-entrypoints/main.js`
918
- - `.devflare/vite.config.mjs`
919
- - `.wrangler/deploy/config.json`
920
- - `env.d.ts`
921
-
922
- `devflare build` keeps name-based bindings as names in these generated artifacts. `devflare deploy` is the step that resolves or provisions the concrete Cloudflare resources and rewrites the generated Wrangler config with the IDs Wrangler needs.
923
-
924
- The source of truth is still:
925
-
926
- - `devflare.config.ts`
927
- - your source files under `src/`
928
- - your tests
929
-
930
- ---
931
-
932
- ## Maintainer scripts
933
-
934
- These scripts live in `packages/devflare/scripts/` and are intended for Devflare maintainers, not for end-user applications.
935
-
936
- ### `refresh-permission-groups`
937
-
938
- Fetches the live Cloudflare permission-group catalog and rewrites `src/cloudflare/known-permission-group-ids.generated.ts` so the symbolic Devflare permission-group names (`WORKERS_SCRIPTS_WRITE`, etc.) map to verified Cloudflare UUIDs instead of falling back to display-name matching.
939
-
940
- ```sh
941
- # from the repo root
942
- CLOUDFLARE_API_TOKEN=... CLOUDFLARE_ACCOUNT_ID=... bun run --cwd packages/devflare refresh-permission-groups
943
- ```
944
-
945
- Flags:
946
-
947
- - `--dry-run` — print the would-be generated file to stdout instead of writing to disk; useful for CI drift checks.
948
- - `--keep-existing` — keep the previously-known UUID for entries missing from the API response, instead of clearing them to `null`.
949
- - `--output <path>` — override the destination file; defaults to `packages/devflare/src/cloudflare/known-permission-group-ids.generated.ts`.
950
-
951
- The API token must have permission to read `/accounts/:id/tokens/permission_groups`. The script never touches `tokens.ts` directly, so the public matcher API and its display-name fallback continue to work even when the generated file ships with all-`null` entries.
952
-
953
- ---
954
-
955
- ## In one sentence
956
-
957
- **Devflare helps you build Cloudflare Workers with clearer structure, better local tooling, and a development workflow that stays coherent as the app grows.**
1
+ # Devflare
2
+
3
+ Devflare is a developer-first toolkit for Cloudflare Workers. It keeps config,
4
+ runtime helpers, local development, testing, preview deploys, and Cloudflare
5
+ operations in one package without pretending Cloudflare boundaries disappear.
6
+
7
+ The docs app is the authored long-form source. This README is intentionally the
8
+ short package map: install, first Worker, import/API map, config and CLI
9
+ surface, support stances, and links into the deeper docs. `LLM.md` is generated
10
+ from the same docs model and shipped with the package for flattened reading.
11
+
12
+ ## Install
13
+
14
+ For a worker-only project, install only Devflare:
15
+
16
+ ```bash
17
+ bun add -d devflare
18
+ ```
19
+
20
+ For Vite-backed apps, add Vite and the Cloudflare Vite plugin:
21
+
22
+ ```bash
23
+ bun add -d devflare vite @cloudflare/vite-plugin
24
+ ```
25
+
26
+ Assumptions used by the examples: Wrangler 4, Miniflare 4,
27
+ `@cloudflare/workers-types` 4, Bun 1.1+, and Node 20+.
28
+
29
+ ## Cloudflare toolchain support
30
+
31
+ Devflare targets Wrangler 4, Miniflare 4, and @cloudflare/workers-types 4.
32
+ Devflare does not support Wrangler 3 in new projects. The package manifest pins
33
+ the exact ranges that scaffolds, local runtime behavior, and generated types
34
+ are validated against in CI.
35
+
36
+ ## Quick Start
37
+
38
+ Create a config:
39
+
40
+ ```ts
41
+ // devflare.config.ts
42
+ import { defineConfig } from 'devflare/config'
43
+
44
+ export default defineConfig({
45
+ name: 'hello-worker',
46
+ compatibilityDate: '2026-03-17',
47
+ files: {
48
+ fetch: 'src/fetch.ts'
49
+ }
50
+ })
51
+ ```
52
+
53
+ Add a fetch handler:
54
+
55
+ ```ts
56
+ // src/fetch.ts
57
+ import type { FetchEvent } from 'devflare/runtime'
58
+
59
+ export async function fetch(_event: FetchEvent): Promise<Response> {
60
+ return new Response('Hello from Devflare')
61
+ }
62
+ ```
63
+
64
+ Generate types and start local dev:
65
+
66
+ ```bash
67
+ bunx --bun devflare types
68
+ bunx --bun devflare dev
69
+ ```
70
+
71
+ Add the first runtime-shaped test:
72
+
73
+ ```ts
74
+ // tests/worker.test.ts
75
+ import { afterAll, beforeAll, expect, test } from 'bun:test'
76
+ import { cf, createTestContext, env } from 'devflare/test'
77
+
78
+ beforeAll(() => createTestContext())
79
+ afterAll(() => env.dispose())
80
+
81
+ test('GET / returns text', async () => {
82
+ const response = await cf.worker.get('/')
83
+
84
+ expect(response.status).toBe(200)
85
+ expect(await response.text()).toBe('Hello from Devflare')
86
+ })
87
+ ```
88
+
89
+ Run it:
90
+
91
+ ```bash
92
+ bun test tests/worker.test.ts
93
+ ```
94
+
95
+ ## Choose Your Next Path
96
+
97
+ | Need | Open |
98
+ | --- | --- |
99
+ | Add route files | `/docs/first-route-tree`, then `/docs/http-routing` |
100
+ | Add one binding | `/docs/first-bindings`, then `/docs/binding-chooser` |
101
+ | Pick a test helper | `/docs/test-helper-reference` |
102
+ | Deploy safely | `/docs/deploy-command-recipes` |
103
+ | Check support stance | `/docs/feature-index` |
104
+ | Copy a larger example | `/docs/recipe-packs` or `cases/README.md` |
105
+
106
+ ## Package Entrypoints
107
+
108
+ | Import | Use |
109
+ | --- | --- |
110
+ | `devflare` | Node-side utilities: `defineConfig`, `preview`, `loadConfig`, `loadResolvedConfig`, `compileConfig`, `stringifyConfig`, `configSchema`, `ref()`, `workerName`, `env`, `durableObject`, `getDurableObjectOptions`, `runCli`, `parseArgs` |
111
+ | `devflare/config` | Config and compiler utilities: `defineConfig`, `preview`, `ref`, `loadConfig`, `loadResolvedConfig`, `compileConfig`, `stringifyConfig`, `configSchema`, `resolveResources`, `writeWranglerConfig`, `readWranglerConfig`, `prepareConfigResourcesForDeploy`, `prepareMaterializedConfigResourcesForDeploy`, `resolveConfigPath`, `resolveConfigForEnvironment`, `resolvePreviewIdentifier`, `materializePreviewScopedConfig`, `materializePreviewScopedString`, `isPreviewScopedName`, `resolveMaterializedConfigResources`, `compileBuildConfig`, `validateServiceBindings`, `collectReferencedServiceNames`, `getLocalKVNamespaceIdentifier`, `getLocalD1DatabaseIdentifier`, `getLocalHyperdriveConfigIdentifier`, `getSingleBrowserBindingName`, `normalizeKVBinding`, `normalizeD1Binding`, `normalizeDOBinding`, `normalizeHyperdriveBinding`, `normalizeMtlsCertificateBinding`, `normalizeDispatchNamespaceBinding`, `normalizeWorkflowBinding`, `normalizePipelineBinding`, `normalizeImagesBinding`, `normalizeMediaBinding`, `normalizeSecretsStoreBinding`, `normalizeArtifactsBinding` |
112
+ | `devflare/runtime` | Worker-safe runtime helpers: `env`, `ctx`, `event`, `locals`, `sequence`, `defineFetchHandler`, `defineQueueHandler`, `defineScheduledHandler`, `markResolveStyle`, `markWorkerStyle`, `createResolveFetch`, `invokeFetchHandler`, `invokeFetchModule`, `matchFetchRoute`, `invokeRouteModules`, `createRouteResolve`, event creators and getters |
113
+ | `devflare/test` | Testing helpers: `createTestContext`, `env`, `cf`, `worker`, `queue`, `scheduled`, `email`, `tail`, `shouldSkip`, `createOfflineEnv`, `createOfflineBindings`, `describeOfflineSupport`, `getOfflineSupportMatrix`, `containers`, `detectContainerEngine`, `getContainerSkipReason`, `stopActiveContainers`, `createMockEnv`, `createMockKV`, `createMockD1`, `createMockR2`, `createMockQueue`, `createMockRateLimit`, `createMockVersionMetadata`, `createMockHyperdrive`, `createMockWorkerLoader`, `createMockMTLSCertificate`, `createMockDispatchNamespace`, `createMockWorkflow`, `createMockPipeline`, `createMockImagesBinding`, `createMockMediaBinding`, `createMockArtifacts`, `createMockAISearchInstance`, `createMockAISearchNamespace`, `createMockTestContext`, `withTestContext`, `resolveServiceBindings`, `resolveDOBindings`, `clearBundleCache` |
114
+ | `devflare/vite` | Vite integration: `devflarePlugin`, `getCloudflareConfig`, `getDevflareConfigs`, `getPluginContext`, `hasInlineViteConfig`, `resolveEffectiveViteProject`, `resolveViteUserConfig`, `writeGeneratedViteConfig` |
115
+ | `devflare/sveltekit` | SvelteKit integration: `createDevflarePlatform`, `createHandle`, `handle`, `getBridgePort`, `isDevflareDev`, `resetPlatform`, `resetConfigCache` |
116
+ | `devflare/cloudflare` | Cloudflare account and preview registry helpers: `account`, `ensurePreviewRegistry`, `cleanupPreviewRegistry`, `getPreviewRegistryContext`, `listTrackedRegistryState`, `listTrackedPreviewRecords`, `listTrackedPreviewScopeRecords`, `listTrackedDeploymentRecords`, `reconcilePreviewRegistry`, `retirePreviewRegistry` |
117
+ | `devflare/decorators` | Durable Object decorators: `durableObject`, `getDurableObjectOptions` |
118
+
119
+ Runtime import rule of thumb:
120
+
121
+ - Use `devflare/config` in config files.
122
+ - Use `devflare/runtime` in Worker code.
123
+ - Use `devflare/test` in tests.
124
+ - Use bare `devflare` for Node-side package tooling and the unified env proxy only when that is intentional.
125
+
126
+ ## Config Map
127
+
128
+ The most important top-level keys are:
129
+
130
+ - `accountId`
131
+ - `assets`
132
+ - `baseDir`
133
+ - `bindings`
134
+ - `compatibilityDate`
135
+ - `compatibilityFlags`
136
+ - `containers`
137
+ - `env`
138
+ - `files`
139
+ - `findAdditionalModules`
140
+ - `limits`
141
+ - `migrations`
142
+ - `name`
143
+ - `observability`
144
+ - `placement`
145
+ - `preserveFileNames`
146
+ - `previews`
147
+ - `rolldown`
148
+ - `routes`
149
+ - `rules`
150
+ - `secrets`
151
+ - `secretsStoreId`
152
+ - `tailConsumers`
153
+ - `triggers`
154
+ - `vars`
155
+ - `vite`
156
+ - `wrangler.passthrough`
157
+ - `wsRoutes`
158
+
159
+ Open `/docs/full-config`, `/docs/config-basics`, and `/docs/generated-types`
160
+ for examples with file paths.
161
+
162
+ ## CLI
163
+
164
+ | Command | Use |
165
+ | --- | --- |
166
+ | `devflare account` | inspect Cloudflare account resources, limits, and usage |
167
+ | `devflare ai` | inspect Workers AI model pricing information |
168
+ | `devflare build` | generate deploy-ready local artifacts |
169
+ | `devflare config` | print resolved Devflare or Wrangler-facing config |
170
+ | `devflare deploy` | deploy explicitly to production or preview |
171
+ | `devflare dev` | start local development |
172
+ | `devflare doctor` | inspect local project health |
173
+ | `devflare help` | print help for root or nested commands |
174
+ | `devflare init` | scaffold a starter project |
175
+ | `devflare login` | authenticate through Wrangler |
176
+ | `devflare previews` | inspect and clean preview scopes |
177
+ | `devflare productions` | inspect or manage production Worker versions |
178
+ | `devflare remote` | manage remote test mode |
179
+ | `devflare secrets` | manage local Secrets Store values |
180
+ | `devflare tokens` | create and manage Devflare-scoped API tokens |
181
+ | `devflare types` | generate `env.d.ts` |
182
+ | `devflare version` | print the installed version |
183
+ | `devflare worker` | run Worker control-plane helpers |
184
+
185
+ ## Support Stance Index
186
+
187
+ The full support matrix is in `/docs/feature-index`. The short version is:
188
+ offline-first when deterministic local behavior is meaningful, remote-gated
189
+ when Cloudflare owns the product behavior, and explicit skip helpers when CI
190
+ cannot safely run the dependency.
191
+
192
+ ### AutoRAG migration stance
193
+
194
+ AutoRAG is documented under AI Search. The previous `env.AI.autorag()` binding
195
+ shape should move to native AI Search config. Use `bindings.aiSearchNamespaces`
196
+ or `bindings.aiSearch` so the binding is visible in config, generated types,
197
+ and tests.
198
+
199
+ ### AI Gateway binding methods
200
+
201
+ AI Gateway does not use a separate Wrangler binding. It is a method surface on
202
+ Workers AI: `env.AI.gateway(id)` exposes `patchLog()`, `getLog()`, `getUrl()`,
203
+ and `run()`.
204
+
205
+ ### Browser Run product boundary
206
+
207
+ Browser Run is the current product name for Browser Rendering. Devflare runs a
208
+ local browser-rendering shim for the ordinary dev and test loop, but Devflare
209
+ does not manage Live View URLs, Human in the Loop handoff, recordings, browser
210
+ session storage, or Browser Run account-level product state.
211
+
212
+ ### Containers local testing
213
+
214
+ Devflare supports native top-level `containers` config and local container
215
+ testing helpers. Containers have full local support when Docker or Podman is
216
+ available: Devflare can build local Dockerfile paths, run prebuilt image tags,
217
+ and interact with instances through fetch, logs, state, stop, and cleanup
218
+ helpers. Devflare container tests are offline-first by default when the image
219
+ already exists locally or the Dockerfile can build from cached layers. Set
220
+ `DEVFLARE_CONTAINER_TESTS=1` for container lanes, and gate them with
221
+ `shouldSkip.containers` because GitHub Actions or Cloudflare runners may not
222
+ have Docker/Podman. Cloudflare still owns the deployed Containers control plane,
223
+ managed registry rollout, SSH, scaling, and hosted platform behavior.
224
+
225
+ ### Cloudflare Builds stance
226
+
227
+ Cloudflare Builds is CI/CD orchestration, not a Worker runtime binding.
228
+ Devflare does not connect Git repositories, manage build hooks, own Cloudflare
229
+ Builds project settings, or replace GitHub Actions workflows.
230
+
231
+ ### Workers for Platforms lifecycle stance
232
+
233
+ Devflare supports dispatch namespace bindings, not the tenant Worker control
234
+ plane. Devflare does not upload user Workers, manage Worker metadata, own tenant
235
+ routing policy, or provide the Workers for Platforms lifecycle API.
236
+
237
+ ### Hyperdrive local connection stance
238
+
239
+ Hyperdrive has full local support when a binding has a local database connection
240
+ string. Devflare passes `localConnectionString` or
241
+ `CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_<BINDING>` into Miniflare and
242
+ also exposes `createMockHyperdrive()` for pure tests. Cloudflare still owns
243
+ hosted pooling, placement, production credentials, and account state.
244
+
245
+ ### Worker Loaders local payload stance
246
+
247
+ Worker Loaders have full local support through Miniflare worker loader bindings
248
+ and explicit pure-test stubs. Devflare does not upload, discover, or lifecycle
249
+ manage hosted dynamic Worker payloads.
250
+
251
+ ### Secrets Store local values stance
252
+
253
+ Secrets Store has full local support through Miniflare wiring, local
254
+ `devflare secrets --local` values, and explicit fixture values in
255
+ `createOfflineEnv()` or `createMockSecretsStoreSecret()`. The local runtime is
256
+ read-only from Worker code: write values through the CLI, keep config to store
257
+ IDs and secret names, and let dev/test runs seed Miniflare from
258
+ `.devflare/secrets.local.json`. Devflare does not read, provision, or sync
259
+ remote account secret values.
260
+
261
+ ### Workflows local simulation stance
262
+
263
+ Workflows have full local support through Miniflare wiring, WorkflowEntrypoint
264
+ examples, and deterministic pure mocks. Use deployed or Wrangler-backed tests
265
+ for production Workflow lifecycle behavior, retries, durability, and platform
266
+ scheduling.
267
+
268
+ ### Pipelines source and sink lifecycle stance
269
+
270
+ Pipelines local tests are useful for producer-code assertions. Devflare does not
271
+ create streams, pipelines, SQL transformations, sinks, or R2 buckets for the
272
+ deployed product lifecycle.
273
+
274
+ ### Images transformation testability stance
275
+
276
+ Images have full local support for Worker transformation flows through
277
+ Miniflare wiring and deterministic pure mocks. Devflare does not provision
278
+ hosted Images storage, variants, signed URLs, or custom delivery rules.
279
+
280
+ ### Media Transformations local shim stance
281
+
282
+ Media Transformations have full local support for Worker call chains through
283
+ Miniflare wiring and deterministic pure mocks. Devflare does not configure
284
+ zone-level transformation enablement, source origins, signed URL policy, cache
285
+ behavior, or billing controls.
286
+
287
+ ### Artifacts persistence and deployment stance
288
+
289
+ Artifacts pure mocks are in-memory and process-local. Devflare does not create
290
+ Artifacts namespaces, persist local Git repositories, or emulate Git-over-HTTPS
291
+ remotes.
292
+
293
+ ### Preview resource lifecycle policy
294
+
295
+ Devflare preview provisioning is intentionally limited to KV, D1, R2, Queues,
296
+ Vectorize, and the documented Hyperdrive reuse/resolve paths. Preview cleanup
297
+ does not delete Workflows, Pipelines, Images, Media Transformations, Artifacts,
298
+ AI Search, AI Gateway, Browser Run, Containers, Secrets Store, mTLS
299
+ certificates, or dispatch namespace resources.
300
+
301
+ ### Cross-feature implementation decisions
302
+
303
+ Remote mode decisions are per feature, not global. Generated types are emitted
304
+ only for native binding keys. Test helpers exist when Devflare provides a
305
+ deterministic local mock or useful pure assertion surface. Every native binding
306
+ documented above includes a minimal config and Env usage example. Move from
307
+ `wrangler.passthrough` to native config when a binding appears in the native
308
+ list. Cloudflare dependency CI targets the pinned current Wrangler, Miniflare,
309
+ and workers-types majors documented in Cloudflare toolchain support.
310
+
311
+ ### Offline-first testing support matrix
312
+
313
+ `createOfflineEnv(config, fixtures)` derives a deterministic pure-test `env`
314
+ from Devflare config. Offline-native means Devflare or Miniflare can run a
315
+ useful local simulator. Offline-fixture means Devflare provides an explicit
316
+ in-memory or handler-backed mock. Remote-boundary means meaningful behavior
317
+ lives in Cloudflare.
318
+
319
+ Use `shouldSkip.aiSearch`, `shouldSkip.aiGateway`,
320
+ `shouldSkip.mtlsCertificates`, `shouldSkip.artifacts`, and `shouldSkip.builds`
321
+ for remote-boundary lanes. Offline-first tests should not claim to cover real
322
+ Workers AI inference, Vectorize search semantics, AI Search indexing/ranking/
323
+ crawling, final Media Transformations codec fidelity, mTLS certificate
324
+ presentation, Artifacts Git remotes, Browser Run live/HITL/recordings,
325
+ Cloudflare Builds, or the deployed Containers control plane.
326
+
327
+ ## Machine-Checked Support Statements
328
+
329
+ These statements are intentionally exact because the docs tests use them as
330
+ public stance guards:
331
+
332
+ - Use `bindings.aiSearchNamespaces` or `bindings.aiSearch`.
333
+ - `env.AI.gateway(id)` exposes `patchLog()`, `getLog()`, `getUrl()`, and `run()`.
334
+ - Devflare does not manage Live View URLs, Human in the Loop handoff.
335
+ - Set `DEVFLARE_CONTAINER_TESTS=1`.
336
+ - Containers have full local support when Docker or Podman is available.
337
+ - Cloudflare still owns the deployed Containers control plane.
338
+ - Devflare does not connect Git repositories, manage build hooks.
339
+ - Devflare supports dispatch namespace bindings, not the tenant Worker control plane.
340
+ - Devflare does not upload user Workers, manage Worker metadata.
341
+ - Hyperdrive has full local support when a binding has a local database connection string.
342
+ - Worker Loaders have full local support through Miniflare worker loader bindings.
343
+ - Secrets Store has full local support through Miniflare wiring, local `devflare secrets --local` values, and explicit fixture values.
344
+ - Workflows have full local support through Miniflare wiring.
345
+ - Use deployed or Wrangler-backed tests for production Workflow lifecycle behavior.
346
+ - Devflare does not create streams, pipelines, SQL transformations, sinks, or R2 buckets.
347
+ - Images have full local support for Worker transformation flows.
348
+ - Devflare does not provision hosted Images storage, variants, signed URLs, or custom delivery rules.
349
+ - Media Transformations have full local support for Worker call chains.
350
+ - Devflare does not configure zone-level transformation enablement, source origins, signed URL policy, cache behavior, or billing controls.
351
+ - Devflare does not create Artifacts namespaces, persist local Git repositories, or emulate Git-over-HTTPS remotes.
352
+ - Devflare preview provisioning is intentionally limited to KV, D1, R2, Queues, Vectorize, and the documented Hyperdrive reuse/resolve paths.
353
+ - Preview cleanup does not delete Workflows, Pipelines, Images, Media Transformations, Artifacts, AI Search, AI Gateway, Browser Run, Containers, Secrets Store, mTLS certificates, or dispatch namespace resources.
354
+ - Generated types are emitted only for native binding keys.
355
+ - Test helpers exist when Devflare provides a deterministic local mock or useful pure assertion surface.
356
+ - Every native binding documented above includes a minimal config and Env usage example.
357
+ - Move from `wrangler.passthrough` to native config when a binding appears in the native list.
358
+ - Cloudflare dependency CI targets the pinned current Wrangler, Miniflare, and workers-types majors documented in Cloudflare toolchain support.
359
+ - `createOfflineEnv(config, fixtures)` derives a deterministic pure-test `env` from Devflare config.
360
+ - Offline-native means Devflare or Miniflare can run a useful local simulator.
361
+ - Offline-fixture means Devflare provides an explicit in-memory or handler-backed mock.
362
+ - Remote-boundary means meaningful behavior lives in Cloudflare.
363
+ - `shouldSkip.aiSearch`, `shouldSkip.aiGateway`, `shouldSkip.mtlsCertificates`, `shouldSkip.artifacts`, and `shouldSkip.builds`.
364
+ - real Workers AI inference, Vectorize search semantics, AI Search indexing/ranking/crawling, final Media Transformations codec fidelity, mTLS certificate presentation, Artifacts Git remotes, Browser Run live/HITL/recordings, Cloudflare Builds, or the deployed Containers control plane.
365
+
366
+ ## Verification
367
+
368
+ Docs and README drift are covered by:
369
+
370
+ ```bash
371
+ bun run devflare:docs-integrity
372
+ ```
373
+
374
+ The package publish path regenerates `packages/devflare/LLM.md` from the docs
375
+ model through `bun run --cwd packages/devflare llm:generate`.