alchemy 0.45.5 → 0.46.0

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 (346) hide show
  1. package/README.md +2 -2
  2. package/bin/alchemy.mjs +19285 -15137
  3. package/bin/alchemy.ts +14 -56
  4. package/bin/commands/create.ts +307 -137
  5. package/bin/commands/deploy.ts +23 -0
  6. package/bin/commands/destroy.ts +19 -0
  7. package/bin/commands/dev.ts +21 -0
  8. package/bin/commands/login.ts +66 -0
  9. package/bin/commands/run.ts +29 -0
  10. package/bin/services/dependencies.ts +0 -5
  11. package/bin/services/execute-alchemy.ts +160 -0
  12. package/bin/services/git.ts +27 -0
  13. package/bin/services/github-workflow.ts +229 -0
  14. package/bin/services/package-manager.ts +51 -68
  15. package/bin/services/template-manager.ts +10 -21
  16. package/bin/trpc.ts +3 -0
  17. package/bin/types.ts +4 -2
  18. package/lib/apply.d.ts +2 -0
  19. package/lib/apply.d.ts.map +1 -1
  20. package/lib/apply.js +26 -8
  21. package/lib/apply.js.map +1 -1
  22. package/lib/build-date.d.ts +1 -1
  23. package/lib/build-date.js +1 -1
  24. package/lib/cloudflare/ai.d.ts +8 -4
  25. package/lib/cloudflare/ai.d.ts.map +1 -1
  26. package/lib/cloudflare/ai.js +6 -8
  27. package/lib/cloudflare/ai.js.map +1 -1
  28. package/lib/cloudflare/analytics-engine.d.ts +11 -7
  29. package/lib/cloudflare/analytics-engine.d.ts.map +1 -1
  30. package/lib/cloudflare/analytics-engine.js +11 -9
  31. package/lib/cloudflare/analytics-engine.js.map +1 -1
  32. package/lib/cloudflare/{types.d.ts → api-response.d.ts} +6 -1
  33. package/lib/cloudflare/api-response.d.ts.map +1 -0
  34. package/lib/cloudflare/api-response.js +38 -0
  35. package/lib/cloudflare/api-response.js.map +1 -0
  36. package/lib/cloudflare/auth-wrangler.d.ts +25 -0
  37. package/lib/cloudflare/auth-wrangler.d.ts.map +1 -0
  38. package/lib/cloudflare/auth-wrangler.js +224 -0
  39. package/lib/cloudflare/auth-wrangler.js.map +1 -0
  40. package/lib/cloudflare/auth.d.ts.map +1 -1
  41. package/lib/cloudflare/auth.js +7 -116
  42. package/lib/cloudflare/auth.js.map +1 -1
  43. package/lib/cloudflare/browser-rendering.d.ts +12 -3
  44. package/lib/cloudflare/browser-rendering.d.ts.map +1 -1
  45. package/lib/cloudflare/browser-rendering.js +12 -2
  46. package/lib/cloudflare/browser-rendering.js.map +1 -1
  47. package/lib/cloudflare/bundle/fs.d.ts.map +1 -1
  48. package/lib/cloudflare/bundle/fs.js +3 -0
  49. package/lib/cloudflare/bundle/fs.js.map +1 -1
  50. package/lib/cloudflare/bundle/internal-worker-bundle.d.ts +6 -0
  51. package/lib/cloudflare/bundle/internal-worker-bundle.d.ts.map +1 -0
  52. package/lib/cloudflare/bundle/internal-worker-bundle.js +14 -0
  53. package/lib/cloudflare/bundle/internal-worker-bundle.js.map +1 -0
  54. package/lib/cloudflare/compatibility-presets.d.ts +22 -0
  55. package/lib/cloudflare/compatibility-presets.d.ts.map +1 -0
  56. package/lib/cloudflare/compatibility-presets.js +27 -0
  57. package/lib/cloudflare/compatibility-presets.js.map +1 -0
  58. package/lib/cloudflare/container.d.ts +6 -2
  59. package/lib/cloudflare/container.d.ts.map +1 -1
  60. package/lib/cloudflare/container.js +48 -4
  61. package/lib/cloudflare/container.js.map +1 -1
  62. package/lib/cloudflare/dispatch-namespace.d.ts +5 -0
  63. package/lib/cloudflare/dispatch-namespace.d.ts.map +1 -1
  64. package/lib/cloudflare/dispatch-namespace.js +8 -0
  65. package/lib/cloudflare/dispatch-namespace.js.map +1 -1
  66. package/lib/cloudflare/durable-object-namespace.d.ts +23 -15
  67. package/lib/cloudflare/durable-object-namespace.d.ts.map +1 -1
  68. package/lib/cloudflare/durable-object-namespace.js +22 -21
  69. package/lib/cloudflare/durable-object-namespace.js.map +1 -1
  70. package/lib/cloudflare/hyperdrive.d.ts +19 -5
  71. package/lib/cloudflare/hyperdrive.d.ts.map +1 -1
  72. package/lib/cloudflare/hyperdrive.js +14 -0
  73. package/lib/cloudflare/hyperdrive.js.map +1 -1
  74. package/lib/cloudflare/images.d.ts +27 -17
  75. package/lib/cloudflare/images.d.ts.map +1 -1
  76. package/lib/cloudflare/images.js +13 -8
  77. package/lib/cloudflare/images.js.map +1 -1
  78. package/lib/cloudflare/index.d.ts +1 -3
  79. package/lib/cloudflare/index.d.ts.map +1 -1
  80. package/lib/cloudflare/index.js +1 -3
  81. package/lib/cloudflare/index.js.map +1 -1
  82. package/lib/cloudflare/miniflare/miniflare.d.ts +3 -3
  83. package/lib/cloudflare/miniflare/miniflare.d.ts.map +1 -1
  84. package/lib/cloudflare/miniflare/miniflare.js +7 -7
  85. package/lib/cloudflare/miniflare/miniflare.js.map +1 -1
  86. package/lib/cloudflare/miniflare/{mixed-mode.d.ts → remote-binding-proxy.d.ts} +5 -5
  87. package/lib/cloudflare/miniflare/remote-binding-proxy.d.ts.map +1 -0
  88. package/lib/cloudflare/miniflare/{mixed-mode.js → remote-binding-proxy.js} +16 -52
  89. package/lib/cloudflare/miniflare/remote-binding-proxy.js.map +1 -0
  90. package/lib/cloudflare/state.d.ts +26 -0
  91. package/lib/cloudflare/state.d.ts.map +1 -0
  92. package/lib/cloudflare/state.js +14 -0
  93. package/lib/cloudflare/state.js.map +1 -0
  94. package/lib/cloudflare/user.d.ts +2 -2
  95. package/lib/cloudflare/user.d.ts.map +1 -1
  96. package/lib/cloudflare/user.js +7 -21
  97. package/lib/cloudflare/user.js.map +1 -1
  98. package/lib/cloudflare/vectorize-index.d.ts.map +1 -1
  99. package/lib/cloudflare/vectorize-index.js +5 -2
  100. package/lib/cloudflare/vectorize-index.js.map +1 -1
  101. package/lib/cloudflare/version-metadata.d.ts +15 -3
  102. package/lib/cloudflare/version-metadata.d.ts.map +1 -1
  103. package/lib/cloudflare/version-metadata.js +11 -2
  104. package/lib/cloudflare/version-metadata.js.map +1 -1
  105. package/lib/cloudflare/vite.d.ts.map +1 -1
  106. package/lib/cloudflare/vite.js +2 -1
  107. package/lib/cloudflare/vite.js.map +1 -1
  108. package/lib/cloudflare/worker-metadata.d.ts +13 -2
  109. package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
  110. package/lib/cloudflare/worker-metadata.js +10 -15
  111. package/lib/cloudflare/worker-metadata.js.map +1 -1
  112. package/lib/cloudflare/worker-subdomain.d.ts +7 -0
  113. package/lib/cloudflare/worker-subdomain.d.ts.map +1 -1
  114. package/lib/cloudflare/worker-subdomain.js +17 -22
  115. package/lib/cloudflare/worker-subdomain.js.map +1 -1
  116. package/lib/cloudflare/{worker/tail.d.ts → worker-tail.d.ts} +2 -2
  117. package/lib/cloudflare/worker-tail.d.ts.map +1 -0
  118. package/lib/cloudflare/{worker/tail.js → worker-tail.js} +11 -9
  119. package/lib/cloudflare/worker-tail.js.map +1 -0
  120. package/lib/cloudflare/worker.d.ts +18 -8
  121. package/lib/cloudflare/worker.d.ts.map +1 -1
  122. package/lib/cloudflare/worker.js +32 -8
  123. package/lib/cloudflare/worker.js.map +1 -1
  124. package/lib/cloudflare/workflow.d.ts +22 -11
  125. package/lib/cloudflare/workflow.d.ts.map +1 -1
  126. package/lib/cloudflare/workflow.js +23 -18
  127. package/lib/cloudflare/workflow.js.map +1 -1
  128. package/lib/context.d.ts +2 -2
  129. package/lib/context.d.ts.map +1 -1
  130. package/lib/docker/api.d.ts.map +1 -1
  131. package/lib/docker/api.js +30 -8
  132. package/lib/docker/api.js.map +1 -1
  133. package/lib/fs/file-system-state-store.d.ts +5 -20
  134. package/lib/fs/file-system-state-store.d.ts.map +1 -1
  135. package/lib/fs/file-system-state-store.js +5 -121
  136. package/lib/fs/file-system-state-store.js.map +1 -1
  137. package/lib/fs/index.d.ts +0 -1
  138. package/lib/fs/index.d.ts.map +1 -1
  139. package/lib/fs/index.js +0 -1
  140. package/lib/fs/index.js.map +1 -1
  141. package/lib/llms.cloudflare.txt +6 -5
  142. package/lib/planetscale/password.js +1 -1
  143. package/lib/planetscale/password.js.map +1 -1
  144. package/lib/scope.d.ts.map +1 -1
  145. package/lib/scope.js +3 -6
  146. package/lib/scope.js.map +1 -1
  147. package/lib/state/cloudflare-state-store.d.ts +34 -0
  148. package/lib/state/cloudflare-state-store.d.ts.map +1 -0
  149. package/lib/state/cloudflare-state-store.js +116 -0
  150. package/lib/state/cloudflare-state-store.js.map +1 -0
  151. package/lib/state/d1-state-store.d.ts +15 -0
  152. package/lib/state/d1-state-store.d.ts.map +1 -0
  153. package/lib/{cloudflare → state}/d1-state-store.js +31 -27
  154. package/lib/state/d1-state-store.js.map +1 -0
  155. package/lib/{cloudflare/do-state-store/types.d.ts → state/dofs-state-store/api.d.ts} +1 -1
  156. package/lib/state/dofs-state-store/api.d.ts.map +1 -0
  157. package/lib/state/dofs-state-store/api.js +1 -0
  158. package/lib/state/dofs-state-store/api.js.map +1 -0
  159. package/lib/{cloudflare/do-state-store/store.d.ts → state/dofs-state-store/index.d.ts} +10 -5
  160. package/lib/state/dofs-state-store/index.d.ts.map +1 -0
  161. package/lib/{cloudflare/do-state-store/store.js → state/dofs-state-store/index.js} +15 -11
  162. package/lib/state/dofs-state-store/index.js.map +1 -0
  163. package/lib/{cloudflare/do-state-store/internal.d.ts → state/dofs-state-store/store.d.ts} +4 -5
  164. package/lib/state/dofs-state-store/store.d.ts.map +1 -0
  165. package/lib/{cloudflare/do-state-store/internal.js → state/dofs-state-store/store.js} +7 -22
  166. package/lib/state/dofs-state-store/store.js.map +1 -0
  167. package/lib/state/file-system-state-store.d.ts +21 -0
  168. package/lib/state/file-system-state-store.d.ts.map +1 -0
  169. package/lib/state/file-system-state-store.js +122 -0
  170. package/lib/state/file-system-state-store.js.map +1 -0
  171. package/lib/state/index.d.ts +7 -0
  172. package/lib/state/index.d.ts.map +1 -0
  173. package/lib/state/index.js +7 -0
  174. package/lib/state/index.js.map +1 -0
  175. package/lib/state/migrations.d.ts +2 -0
  176. package/lib/state/migrations.d.ts.map +1 -0
  177. package/lib/state/migrations.js +3 -0
  178. package/lib/state/migrations.js.map +1 -0
  179. package/lib/state/operations.d.ts +36 -0
  180. package/lib/state/operations.d.ts.map +1 -0
  181. package/lib/state/operations.js +126 -0
  182. package/lib/state/operations.js.map +1 -0
  183. package/lib/state/proxy.d.ts +53 -0
  184. package/lib/state/proxy.d.ts.map +1 -0
  185. package/lib/state/proxy.js +65 -0
  186. package/lib/state/proxy.js.map +1 -0
  187. package/lib/{cloudflare → state}/r2-rest-state-store.d.ts +3 -1
  188. package/lib/state/r2-rest-state-store.d.ts.map +1 -0
  189. package/lib/{cloudflare → state}/r2-rest-state-store.js +6 -4
  190. package/lib/state/r2-rest-state-store.js.map +1 -0
  191. package/lib/state/schema.d.ts.map +1 -0
  192. package/lib/state/schema.js.map +1 -0
  193. package/lib/{sqlite → state}/sqlite-state-store.d.ts +5 -3
  194. package/lib/state/sqlite-state-store.d.ts.map +1 -0
  195. package/lib/{sqlite → state}/sqlite-state-store.js +15 -6
  196. package/lib/state/sqlite-state-store.js.map +1 -0
  197. package/lib/test/vitest.d.ts.map +1 -1
  198. package/lib/test/vitest.js +3 -6
  199. package/lib/test/vitest.js.map +1 -1
  200. package/lib/util/detect-node-runtime.d.ts +3 -0
  201. package/lib/util/detect-node-runtime.d.ts.map +1 -0
  202. package/lib/util/detect-node-runtime.js +10 -0
  203. package/lib/util/detect-node-runtime.js.map +1 -0
  204. package/lib/util/detect-package-manager.d.ts +2 -2
  205. package/lib/util/detect-package-manager.d.ts.map +1 -1
  206. package/lib/util/detect-package-manager.js +15 -5
  207. package/lib/util/detect-package-manager.js.map +1 -1
  208. package/lib/util/http-server.d.ts.map +1 -0
  209. package/lib/{cloudflare/miniflare → util}/http-server.js +1 -1
  210. package/lib/util/http-server.js.map +1 -0
  211. package/lib/util/memoize.d.ts +2 -0
  212. package/lib/util/memoize.d.ts.map +1 -1
  213. package/lib/util/memoize.js +14 -7
  214. package/lib/util/memoize.js.map +1 -1
  215. package/lib/util/neverthrow.d.ts +9 -0
  216. package/lib/util/neverthrow.d.ts.map +1 -0
  217. package/lib/util/neverthrow.js +29 -0
  218. package/lib/util/neverthrow.js.map +1 -0
  219. package/package.json +20 -20
  220. package/src/apply.ts +31 -10
  221. package/src/build-date.ts +1 -1
  222. package/src/cloudflare/ai.ts +10 -5
  223. package/src/cloudflare/analytics-engine.ts +20 -11
  224. package/src/cloudflare/{types.ts → api-response.ts} +31 -0
  225. package/src/cloudflare/auth-wrangler.ts +314 -0
  226. package/src/cloudflare/auth.ts +8 -156
  227. package/src/cloudflare/browser-rendering.ts +16 -2
  228. package/src/cloudflare/bundle/fs.ts +5 -0
  229. package/src/cloudflare/bundle/internal-worker-bundle.ts +21 -0
  230. package/src/cloudflare/compatibility-presets.ts +34 -0
  231. package/src/cloudflare/container.ts +77 -6
  232. package/src/cloudflare/dispatch-namespace.ts +28 -0
  233. package/src/cloudflare/durable-object-namespace.ts +38 -27
  234. package/src/cloudflare/hyperdrive.ts +19 -5
  235. package/src/cloudflare/images.ts +32 -17
  236. package/src/cloudflare/index.ts +1 -3
  237. package/src/cloudflare/miniflare/miniflare.ts +10 -7
  238. package/src/cloudflare/miniflare/{mixed-mode.ts → remote-binding-proxy.ts} +25 -75
  239. package/src/cloudflare/state.ts +35 -0
  240. package/src/cloudflare/user.ts +55 -70
  241. package/src/cloudflare/vectorize-index.ts +7 -2
  242. package/src/cloudflare/version-metadata.ts +19 -2
  243. package/src/cloudflare/vite.ts +2 -1
  244. package/src/cloudflare/worker-metadata.ts +18 -43
  245. package/src/cloudflare/worker-subdomain.ts +43 -37
  246. package/src/cloudflare/{worker/tail.ts → worker-tail.ts} +13 -10
  247. package/src/cloudflare/worker.ts +66 -20
  248. package/src/cloudflare/workflow.ts +38 -19
  249. package/src/context.ts +2 -2
  250. package/src/docker/api.ts +33 -8
  251. package/src/fs/file-system-state-store.ts +5 -148
  252. package/src/fs/index.ts +0 -1
  253. package/src/llms.cloudflare.txt +6 -5
  254. package/src/planetscale/password.ts +1 -1
  255. package/src/scope.ts +3 -6
  256. package/src/state/cloudflare-state-store.ts +170 -0
  257. package/src/state/d1-state-store.ts +102 -0
  258. package/src/{cloudflare/do-state-store/store.ts → state/dofs-state-store/index.ts} +20 -13
  259. package/src/{cloudflare/do-state-store/internal.ts → state/dofs-state-store/store.ts} +9 -27
  260. package/src/state/file-system-state-store.ts +149 -0
  261. package/src/state/index.ts +6 -0
  262. package/src/state/migrations.ts +9 -0
  263. package/src/state/operations.ts +152 -0
  264. package/src/state/proxy.ts +132 -0
  265. package/src/{cloudflare → state}/r2-rest-state-store.ts +11 -8
  266. package/src/{sqlite → state}/sqlite-state-store.ts +18 -10
  267. package/src/test/vitest.ts +8 -6
  268. package/src/util/detect-node-runtime.ts +12 -0
  269. package/src/util/detect-package-manager.ts +19 -6
  270. package/src/{cloudflare/miniflare → util}/http-server.ts +1 -1
  271. package/src/util/memoize.ts +18 -7
  272. package/src/util/neverthrow.ts +36 -0
  273. package/templates/astro/package.json +3 -3
  274. package/templates/nuxt/package.json +3 -3
  275. package/templates/react-router/package.json +3 -3
  276. package/templates/rwsdk/alchemy.run.ts +1 -1
  277. package/templates/rwsdk/package.json +3 -3
  278. package/templates/sveltekit/package.json +3 -3
  279. package/templates/tanstack-start/package.json +3 -3
  280. package/templates/typescript/package.json +3 -2
  281. package/templates/typescript/tsconfig.json +1 -0
  282. package/templates/vite/package.json +3 -3
  283. package/workers/cloudflare-state-store.js +5638 -0
  284. package/workers/cloudflare-state-store.ts +108 -0
  285. package/workers/{do-state-store.js → dofs-state-store.js} +4 -4
  286. package/workers/{do-state-store.ts → dofs-state-store.ts} +12 -8
  287. package/workers/{mixed-mode-proxy-worker.js → remote-binding-proxy.js} +3 -3
  288. package/workers/remote-binding-proxy.ts +45 -0
  289. package/lib/cloudflare/d1-state-store.d.ts +0 -10
  290. package/lib/cloudflare/d1-state-store.d.ts.map +0 -1
  291. package/lib/cloudflare/d1-state-store.js.map +0 -1
  292. package/lib/cloudflare/do-state-store/index.d.ts +0 -2
  293. package/lib/cloudflare/do-state-store/index.d.ts.map +0 -1
  294. package/lib/cloudflare/do-state-store/index.js +0 -2
  295. package/lib/cloudflare/do-state-store/index.js.map +0 -1
  296. package/lib/cloudflare/do-state-store/internal.d.ts.map +0 -1
  297. package/lib/cloudflare/do-state-store/internal.js.map +0 -1
  298. package/lib/cloudflare/do-state-store/store.d.ts.map +0 -1
  299. package/lib/cloudflare/do-state-store/store.js.map +0 -1
  300. package/lib/cloudflare/do-state-store/types.d.ts.map +0 -1
  301. package/lib/cloudflare/do-state-store/types.js +0 -1
  302. package/lib/cloudflare/do-state-store/types.js.map +0 -1
  303. package/lib/cloudflare/miniflare/http-server.d.ts.map +0 -1
  304. package/lib/cloudflare/miniflare/http-server.js.map +0 -1
  305. package/lib/cloudflare/miniflare/mixed-mode.d.ts.map +0 -1
  306. package/lib/cloudflare/miniflare/mixed-mode.js.map +0 -1
  307. package/lib/cloudflare/r2-rest-state-store.d.ts.map +0 -1
  308. package/lib/cloudflare/r2-rest-state-store.js.map +0 -1
  309. package/lib/cloudflare/types.d.ts.map +0 -1
  310. package/lib/cloudflare/types.js +0 -19
  311. package/lib/cloudflare/types.js.map +0 -1
  312. package/lib/cloudflare/worker/shared.d.ts +0 -4
  313. package/lib/cloudflare/worker/shared.d.ts.map +0 -1
  314. package/lib/cloudflare/worker/shared.js +0 -21
  315. package/lib/cloudflare/worker/shared.js.map +0 -1
  316. package/lib/cloudflare/worker/tail.d.ts.map +0 -1
  317. package/lib/cloudflare/worker/tail.js.map +0 -1
  318. package/lib/sqlite/base-sqlite-state-store.d.ts +0 -31
  319. package/lib/sqlite/base-sqlite-state-store.d.ts.map +0 -1
  320. package/lib/sqlite/base-sqlite-state-store.js +0 -124
  321. package/lib/sqlite/base-sqlite-state-store.js.map +0 -1
  322. package/lib/sqlite/index.d.ts +0 -2
  323. package/lib/sqlite/index.d.ts.map +0 -1
  324. package/lib/sqlite/index.js +0 -2
  325. package/lib/sqlite/index.js.map +0 -1
  326. package/lib/sqlite/schema.d.ts.map +0 -1
  327. package/lib/sqlite/schema.js.map +0 -1
  328. package/lib/sqlite/sqlite-state-store.d.ts.map +0 -1
  329. package/lib/sqlite/sqlite-state-store.js.map +0 -1
  330. package/src/cloudflare/d1-state-store.ts +0 -105
  331. package/src/cloudflare/do-state-store/index.ts +0 -1
  332. package/src/cloudflare/worker/shared.ts +0 -30
  333. package/src/sqlite/base-sqlite-state-store.ts +0 -199
  334. package/src/sqlite/index.ts +0 -1
  335. package/templates/typescript/src/worker.js +0 -5
  336. package/workers/mixed-mode-proxy-worker.ts +0 -46
  337. /package/drizzle/{0000_busy_mauler.sql → default/0000_busy_mauler.sql} +0 -0
  338. /package/drizzle/{0001_concerned_iceman.sql → default/0001_concerned_iceman.sql} +0 -0
  339. /package/drizzle/{meta → default/meta}/0000_snapshot.json +0 -0
  340. /package/drizzle/{meta → default/meta}/0001_snapshot.json +0 -0
  341. /package/drizzle/{meta → default/meta}/_journal.json +0 -0
  342. /package/lib/{sqlite → state}/schema.d.ts +0 -0
  343. /package/lib/{sqlite → state}/schema.js +0 -0
  344. /package/lib/{cloudflare/miniflare → util}/http-server.d.ts +0 -0
  345. /package/src/{cloudflare/do-state-store/types.ts → state/dofs-state-store/api.ts} +0 -0
  346. /package/src/{sqlite → state}/schema.ts +0 -0
@@ -1,6 +1,7 @@
1
1
  import { assertNever } from "../util/assert-never.ts";
2
2
  import { logger } from "../util/logger.ts";
3
3
  import { memoize } from "../util/memoize.ts";
4
+ import { extractCloudflareResult } from "./api-response.ts";
4
5
  import type { CloudflareApi } from "./api.ts";
5
6
  import {
6
7
  Self,
@@ -200,7 +201,7 @@ export interface WorkerMetadata {
200
201
 
201
202
  export async function prepareWorkerMetadata(
202
203
  api: CloudflareApi,
203
- props: WorkerProps & {
204
+ props: Omit<WorkerProps, "entrypoint"> & {
204
205
  compatibilityDate: string;
205
206
  compatibilityFlags: string[];
206
207
  workerName: string;
@@ -210,6 +211,7 @@ export async function prepareWorkerMetadata(
210
211
  keepAssets?: boolean;
211
212
  assetConfig?: AssetsConfig;
212
213
  };
214
+ tags?: string[];
213
215
  unstable_cacheWorkerSettings?: boolean;
214
216
  },
215
217
  ): Promise<WorkerMetadata> {
@@ -226,7 +228,7 @@ export async function prepareWorkerMetadata(
226
228
  // we use Cloudflare Worker tags to store a mapping between Alchemy's stable identifier and the binding name
227
229
  // e.g.
228
230
  // {
229
- // BINDING_NAME: new DurableObjectNamespace("stable-id")
231
+ // BINDING_NAME: DurableObjectNamespace("stable-id")
230
232
  // }
231
233
  // will be stored as alchemy:do:stable-id:BINDING_NAME
232
234
  // TODO(sam): should we base64 encode to ensure no `:` collision risk?
@@ -323,6 +325,7 @@ export async function prepareWorkerMetadata(
323
325
  ),
324
326
  // encode the migraiton tag if there is one so we can avoid the failed PutWorker after adoption
325
327
  ...(newMigrationTag ? [`alchemy:migration-tag:${newMigrationTag}`] : []),
328
+ ...(props.tags ?? []),
326
329
  ],
327
330
  migrations: {
328
331
  old_tag: oldMigrationTag,
@@ -640,6 +643,7 @@ interface WorkerSettings {
640
643
  compatibility_date: string;
641
644
  compatibility_flags: string[];
642
645
  migrations: SingleStepMigration | MultiStepMigration;
646
+ tags: string[];
643
647
  [key: string]: any;
644
648
  }
645
649
 
@@ -648,51 +652,22 @@ const getWorkerSettingsWithCache = memoize(
648
652
  (api, workerName) => `${api.accountId}:${workerName}`,
649
653
  );
650
654
 
651
- async function getWorkerSettings(
655
+ export async function getWorkerSettings(
652
656
  api: CloudflareApi,
653
657
  workerName: string,
654
658
  ): Promise<WorkerSettings | undefined> {
655
659
  // Fetch the bindings for a worker by calling the Cloudflare API endpoint:
656
660
  // GET /accounts/:account_id/workers/scripts/:script_name/bindings
657
661
  // See: https://developers.cloudflare.com/api/resources/workers/subresources/scripts/subresources/script_and_version_settings/methods/get/
658
- const response = await api.get(
659
- `/accounts/${api.accountId}/workers/scripts/${workerName}/settings`,
660
- );
661
- if (response.status === 404) {
662
- return undefined;
663
- }
664
- if (!response.ok) {
665
- throw new Error(
666
- `Error getting worker bindings: ${response.status} ${response.statusText}`,
667
- );
668
- }
669
- // The result is an object with a "result" property containing the bindings array
670
- const { result, success, errors } = (await response.json()) as {
671
- result: {
672
- bindings: WorkerBindingSpec[];
673
- compatibility_date: string;
674
- compatibility_flags: string[];
675
- migrations: SingleStepMigration | MultiStepMigration;
676
- [key: string]: any;
677
- };
678
- success: boolean;
679
- errors: Array<{
680
- code: number;
681
- message: string;
682
- documentation_url: string;
683
- [key: string]: any;
684
- }>;
685
- messages: Array<{
686
- code: number;
687
- message: string;
688
- documentation_url: string;
689
- [key: string]: any;
690
- }>;
691
- };
692
- if (!success) {
693
- throw new Error(
694
- `Error getting worker bindings: ${response.status} ${response.statusText}\nErrors:\n${errors.map((e) => `- [${e.code}] ${e.message} (${e.documentation_url})`).join("\n")}`,
695
- );
696
- }
697
- return result;
662
+ return await extractCloudflareResult<WorkerSettings>(
663
+ `get worker settings for ${workerName}`,
664
+ api.get(
665
+ `/accounts/${api.accountId}/workers/scripts/${workerName}/settings`,
666
+ ),
667
+ ).catch((error) => {
668
+ if (error.status === 404) {
669
+ return undefined;
670
+ }
671
+ throw error;
672
+ });
698
673
  }
@@ -1,12 +1,12 @@
1
1
  import type { Context } from "../context.ts";
2
2
  import { Resource } from "../resource.ts";
3
+ import { memoize } from "../util/memoize.ts";
4
+ import { extractCloudflareResult } from "./api-response.ts";
3
5
  import {
4
6
  createCloudflareApi,
5
7
  type CloudflareApi,
6
8
  type CloudflareApiOptions,
7
9
  } from "./api.ts";
8
- import type { CloudflareApiResponse } from "./types.ts";
9
- import { getAccountSubdomain } from "./worker/shared.ts";
10
10
 
11
11
  interface WorkerSubdomainProps extends CloudflareApiOptions {
12
12
  /**
@@ -49,16 +49,7 @@ export const WorkerSubdomain = Resource(
49
49
  }
50
50
  return this.destroy();
51
51
  }
52
- await wrapFetch<SubdomainResponse>(
53
- `enable subdomain for "${props.scriptName}"`,
54
- api.post(
55
- `/accounts/${api.accountId}/workers/scripts/${props.scriptName}/subdomain`,
56
- { enabled: true, previews_enabled: true },
57
- {
58
- headers: { "Content-Type": "application/json" },
59
- },
60
- ),
61
- );
52
+ await enableWorkerSubdomain(api, props.scriptName);
62
53
  const subdomain = await getAccountSubdomain(api);
63
54
  const base = `${subdomain}.workers.dev`;
64
55
  let url: string;
@@ -77,7 +68,7 @@ export async function disableWorkerSubdomain(
77
68
  api: CloudflareApi,
78
69
  scriptName: string,
79
70
  ) {
80
- await wrapFetch<SubdomainResponse>(
71
+ await extractCloudflareResult<SubdomainResponse>(
81
72
  `disable subdomain for "${scriptName}"`,
82
73
  api.post(
83
74
  `/accounts/${api.accountId}/workers/scripts/${scriptName}/subdomain`,
@@ -91,33 +82,48 @@ export async function disableWorkerSubdomain(
91
82
  });
92
83
  }
93
84
 
85
+ export async function enableWorkerSubdomain(
86
+ api: CloudflareApi,
87
+ scriptName: string,
88
+ ) {
89
+ await extractCloudflareResult<SubdomainResponse>(
90
+ `enable subdomain for "${scriptName}"`,
91
+ api.post(
92
+ `/accounts/${api.accountId}/workers/scripts/${scriptName}/subdomain`,
93
+ { enabled: true, previews_enabled: true },
94
+ ),
95
+ );
96
+ }
97
+
98
+ export async function getWorkerSubdomain(
99
+ api: CloudflareApi,
100
+ scriptName: string,
101
+ ) {
102
+ return await extractCloudflareResult<SubdomainResponse>(
103
+ `get subdomain for "${scriptName}"`,
104
+ api.get(
105
+ `/accounts/${api.accountId}/workers/scripts/${scriptName}/subdomain`,
106
+ ),
107
+ ).catch((error): SubdomainResponse => {
108
+ if (error.status === 404) {
109
+ return { enabled: false, previews_enabled: false };
110
+ }
111
+ throw error;
112
+ });
113
+ }
114
+
94
115
  interface SubdomainResponse {
95
116
  enabled: boolean;
96
117
  previews_enabled: boolean;
97
118
  }
98
119
 
99
- async function wrapFetch<T>(
100
- label: string,
101
- promise: Promise<Response>,
102
- ): Promise<T> {
103
- const response = await promise.catch(() => {
104
- throw new Error(`Failed to ${label}: Failed to fetch`);
105
- });
106
- const json = (await response.json().catch(() => {
107
- throw new Error(
108
- `Failed to ${label} (${response.status}): The API returned an invalid response`,
120
+ export const getAccountSubdomain = memoize(
121
+ async (api: CloudflareApi) => {
122
+ const result = await extractCloudflareResult<{ subdomain: string }>(
123
+ `get subdomain for account ${api.accountId}`,
124
+ api.get(`/accounts/${api.accountId}/workers/subdomain`),
109
125
  );
110
- })) as CloudflareApiResponse<T>;
111
- if (json.success) {
112
- return json.result;
113
- } else {
114
- const error = new Error(
115
- `Failed to ${label} (${response.status}): ${json.errors.map((e) => `${e.code}: ${e.message}`).join(", ")}`,
116
- );
117
- Error.captureStackTrace(error, wrapFetch);
118
- Object.assign(error, {
119
- status: response.status,
120
- });
121
- throw error;
122
- }
123
- }
126
+ return result.subdomain;
127
+ },
128
+ (api) => api.accountId,
129
+ );
@@ -1,8 +1,8 @@
1
1
  import kleur from "kleur";
2
2
  import { WebSocket } from "ws";
3
- import { logger } from "../../util/logger.ts";
4
- import type { CloudflareApi } from "../api.ts";
5
- import type { CloudflareApiResponse } from "../types.ts";
3
+ import { logger } from "../util/logger.ts";
4
+ import type { CloudflareApiResponse } from "./api-response.ts";
5
+ import type { CloudflareApi } from "./api.ts";
6
6
 
7
7
  export const createTail = async (
8
8
  api: CloudflareApi,
@@ -47,7 +47,12 @@ class TailClient {
47
47
  }
48
48
  const res = await this.api.post(
49
49
  `/accounts/${this.api.accountId}/workers/scripts/${this.scriptName}/tails`,
50
- {},
50
+ { filters: [] },
51
+ {
52
+ headers: {
53
+ "Content-Type": "application/json",
54
+ },
55
+ },
51
56
  );
52
57
  const json = (await res.json()) as CloudflareApiResponse<Tail>;
53
58
  if (!json.success) {
@@ -72,11 +77,7 @@ class TailClient {
72
77
  throw new Error(`Failed to connect to tail for ${this.scriptName}`);
73
78
  }
74
79
  const tail = await this.create();
75
- const ws = new WebSocket(tail.url, {
76
- headers: {
77
- "Sec-WebSocket-Protocol": "trace-v1",
78
- },
79
- });
80
+ const ws = new WebSocket(tail.url, "trace-v1");
80
81
  ws.on("open", () => {
81
82
  this.ping(ws);
82
83
  if (DEBUG) {
@@ -92,7 +93,9 @@ class TailClient {
92
93
  return;
93
94
  }
94
95
  logger.log(`reconnecting to tail for "${this.scriptName}"`);
95
- this.connect(attempt + 1);
96
+ setTimeout(() => {
97
+ this.connect(attempt + 1);
98
+ }, 1000);
96
99
  });
97
100
  ws.on("error", (event) => {
98
101
  logger.error(`error on tail for "${this.scriptName}": ${event}`);
@@ -48,6 +48,10 @@ import {
48
48
  normalizeWorkerBundle,
49
49
  } from "./bundle/index.ts";
50
50
  import { wrap } from "./bundle/normalize.ts";
51
+ import {
52
+ type CompatibilityPreset,
53
+ unionCompatibilityFlags,
54
+ } from "./compatibility-presets.ts";
51
55
  import { type Container, ContainerApplication } from "./container.ts";
52
56
  import { CustomDomain } from "./custom-domain.ts";
53
57
  import { isD1Database } from "./d1-database.ts";
@@ -81,7 +85,7 @@ import {
81
85
  } from "./worker-metadata.ts";
82
86
  import { WorkerStub, isWorkerStub } from "./worker-stub.ts";
83
87
  import { WorkerSubdomain, disableWorkerSubdomain } from "./worker-subdomain.ts";
84
- import { createTail } from "./worker/tail.ts";
88
+ import { createTail } from "./worker-tail.ts";
85
89
  import { Workflow, isWorkflow, upsertWorkflow } from "./workflow.ts";
86
90
 
87
91
  /**
@@ -215,6 +219,15 @@ export interface BaseWorkerProps<
215
219
  */
216
220
  compatibilityFlags?: string[];
217
221
 
222
+ /**
223
+ * Compatibility preset to automatically include common compatibility flags
224
+ *
225
+ * - "node": Includes nodejs_compat flag for Node.js compatibility
226
+ *
227
+ * @default undefined (no preset)
228
+ */
229
+ compatibility?: CompatibilityPreset;
230
+
218
231
  /**
219
232
  * Configuration for static assets
220
233
  */
@@ -618,8 +631,8 @@ export function WorkerRef<
618
631
  * @example
619
632
  * // Create a real-time chat worker using Durable Objects
620
633
  * // for state management:
621
- * const chatRooms = new DurableObjectNamespace("chat-rooms");
622
- * const userStore = new DurableObjectNamespace("user-store");
634
+ * const chatRooms = DurableObjectNamespace("chat-rooms");
635
+ * const userStore = DurableObjectNamespace("user-store");
623
636
  *
624
637
  * const chat = await Worker("chat", {
625
638
  * name: "chat-worker",
@@ -693,7 +706,7 @@ export function WorkerRef<
693
706
  * entrypoint: "./src/data.ts",
694
707
  * bindings: {
695
708
  * // Bind to its own durable object
696
- * STORAGE: new DurableObjectNamespace("storage", {
709
+ * STORAGE: DurableObjectNamespace("storage", {
697
710
  * className: "DataStorage"
698
711
  * })
699
712
  * }
@@ -834,7 +847,13 @@ export function Worker<const B extends Bindings>(
834
847
  ...(props as any),
835
848
  url: true,
836
849
  compatibilityFlags: Array.from(
837
- new Set(["nodejs_compat", ...(props.compatibilityFlags ?? [])]),
850
+ new Set([
851
+ "nodejs_compat",
852
+ ...unionCompatibilityFlags(
853
+ props.compatibility,
854
+ props.compatibilityFlags,
855
+ ),
856
+ ]),
838
857
  ),
839
858
  entrypoint: meta!.filename,
840
859
  name: workerName,
@@ -987,7 +1006,10 @@ export const _Worker = Resource(
987
1006
  const workerName = props.name ?? id;
988
1007
  const compatibilityDate =
989
1008
  props.compatibilityDate ?? DEFAULT_COMPATIBILITY_DATE;
990
- const compatibilityFlags = props.compatibilityFlags ?? [];
1009
+ const compatibilityFlags = unionCompatibilityFlags(
1010
+ props.compatibility,
1011
+ props.compatibilityFlags,
1012
+ );
991
1013
  const dispatchNamespace =
992
1014
  typeof props.namespace === "string"
993
1015
  ? props.namespace
@@ -1085,6 +1107,26 @@ export const _Worker = Resource(
1085
1107
  throw error;
1086
1108
  }
1087
1109
 
1110
+ if (this.phase === "update") {
1111
+ const oldName = this.output.name ?? this.output.id;
1112
+ const newName = workerName;
1113
+
1114
+ if (oldName !== newName) {
1115
+ if (dispatchNamespace) {
1116
+ await this.replace(true);
1117
+ } else {
1118
+ const renameResponse = await api.patch(
1119
+ `/accounts/${api.accountId}/workers/services/${oldName}`,
1120
+ { id: newName },
1121
+ );
1122
+
1123
+ if (!renameResponse.ok) {
1124
+ await handleApiError(renameResponse, "rename", "worker", oldName);
1125
+ }
1126
+ }
1127
+ }
1128
+ }
1129
+
1088
1130
  let assetsBinding: Assets | undefined;
1089
1131
  const workflowsBindings: Workflow[] = [];
1090
1132
  const containersBindings: Container[] = [];
@@ -1219,8 +1261,13 @@ export const _Worker = Resource(
1219
1261
  }),
1220
1262
  );
1221
1263
  putWorkerResult = await promise.value;
1222
- const tail = await createTail(api, id, workerName);
1223
- cleanups.push(() => tail.close());
1264
+ await createTail(api, id, workerName)
1265
+ .then((tail) => {
1266
+ cleanups.push(() => tail.close());
1267
+ })
1268
+ .catch((error) => {
1269
+ logger.error(`Failed to create tail for ${workerName}`, error);
1270
+ });
1224
1271
  } else {
1225
1272
  putWorkerResult = await putWorkerWithAssets(props, await bundle.create());
1226
1273
  }
@@ -1424,13 +1471,13 @@ const normalizeExportBindings = (
1424
1471
  Object.entries(bindings).map(([bindingName, binding]) => [
1425
1472
  bindingName,
1426
1473
  isDurableObjectNamespace(binding) && binding.scriptName === undefined
1427
- ? new DurableObjectNamespace(binding.id, {
1474
+ ? DurableObjectNamespace(binding.id, {
1428
1475
  ...binding,
1429
1476
  // re-export this binding mapping to the host worker (this worker)
1430
1477
  scriptName,
1431
1478
  })
1432
1479
  : isWorkflow(binding) && binding.scriptName === undefined
1433
- ? new Workflow(binding.id, {
1480
+ ? Workflow(binding.id, {
1434
1481
  ...binding,
1435
1482
  // re-export this binding mapping to the host worker (this worker)
1436
1483
  scriptName,
@@ -1471,7 +1518,7 @@ async function provisionContainers(
1471
1518
  }
1472
1519
  return ContainerApplication(container.id, {
1473
1520
  image: container.image,
1474
- name: container.id,
1521
+ name: container.name,
1475
1522
  instanceType: container.instanceType,
1476
1523
  observability: container.observability,
1477
1524
  durableObjects: {
@@ -1824,21 +1871,20 @@ function createDevCommand(props: {
1824
1871
  }
1825
1872
  }
1826
1873
 
1827
- type PutWorkerOptions = WorkerProps & {
1874
+ type PutWorkerOptions = Omit<WorkerProps, "entrypoint"> & {
1828
1875
  dispatchNamespace?: string;
1829
1876
  migrationTag?: string;
1830
1877
  workerName: string;
1831
1878
  scriptBundle: WorkerBundle;
1832
- version: string | undefined;
1879
+ version?: string;
1833
1880
  compatibilityDate: string;
1834
1881
  compatibilityFlags: string[];
1835
- assetUploadResult:
1836
- | {
1837
- completionToken?: string;
1838
- keepAssets?: boolean;
1839
- assetConfig?: AssetsConfig;
1840
- }
1841
- | undefined;
1882
+ assetUploadResult?: {
1883
+ completionToken?: string;
1884
+ keepAssets?: boolean;
1885
+ assetConfig?: AssetsConfig;
1886
+ };
1887
+ tags?: string[];
1842
1888
  unstable_cacheWorkerSettings?: boolean;
1843
1889
  };
1844
1890
 
@@ -34,31 +34,50 @@ export interface WorkflowProps {
34
34
  };
35
35
  }
36
36
 
37
- export function isWorkflow(binding: Binding): binding is Workflow {
38
- return typeof binding === "object" && binding.type === "workflow";
39
- }
40
-
41
- export class Workflow<PARAMS = unknown> {
42
- public readonly type = "workflow";
37
+ export type Workflow<PARAMS = unknown> = {
38
+ type: "workflow";
43
39
  /**
44
40
  * Phantom property to preserve workflow params at the type level.
45
- *
46
41
  * No value exists.
47
42
  */
48
- public readonly _PARAMS: PARAMS = undefined!;
43
+ _PARAMS: PARAMS;
44
+ id: string;
45
+ workflowName: string;
46
+ className: string;
47
+ scriptName?: string;
48
+ };
49
49
 
50
- public readonly workflowName: string;
51
- public readonly className: string;
52
- public readonly scriptName?: string;
50
+ export function isWorkflow(binding: Binding): binding is Workflow {
51
+ return typeof binding === "object" && binding.type === "workflow";
52
+ }
53
53
 
54
- constructor(
55
- public readonly id: string,
56
- props: WorkflowProps = {},
57
- ) {
58
- this.workflowName = props.workflowName ?? props.className ?? id;
59
- this.className = props.className ?? this.workflowName;
60
- this.scriptName = props.scriptName;
61
- }
54
+ /**
55
+ * Creates a workflow binding for orchestrating and automating tasks.
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * // Create a basic workflow
60
+ * const workflow = Workflow("my-workflow", {
61
+ * workflowName: "my-workflow",
62
+ * className: "MyWorkflow"
63
+ * });
64
+ * ```
65
+ */
66
+ export function Workflow<PARAMS = unknown>(
67
+ id: string,
68
+ props: WorkflowProps = {},
69
+ ): Workflow<PARAMS> {
70
+ const workflowName = props.workflowName ?? props.className ?? id;
71
+ const className = props.className ?? workflowName;
72
+
73
+ return {
74
+ type: "workflow",
75
+ _PARAMS: undefined!,
76
+ id,
77
+ workflowName,
78
+ className,
79
+ scriptName: props.scriptName,
80
+ };
62
81
  }
63
82
 
64
83
  export interface WorkflowMetadata {
package/src/context.ts CHANGED
@@ -57,7 +57,7 @@ export interface BaseContext<Out extends Resource> {
57
57
  * Indicate that this resource is being replaced.
58
58
  * This will cause the resource to be deleted at the end of the stack's CREATE phase.
59
59
  */
60
- replace(): never;
60
+ replace(force?: boolean): Promise<never>;
61
61
  /**
62
62
  * Terminate the resource lifecycle handler and destroy the resource.
63
63
  *
@@ -102,7 +102,7 @@ export function context<
102
102
  seq: number;
103
103
  props: Props;
104
104
  state: State<Kind, Props, Out>;
105
- replace: () => never;
105
+ replace: (force?: boolean) => Promise<never>;
106
106
  isReplacement?: boolean;
107
107
  }): Context<Out> {
108
108
  type InternalSymbols =
package/src/docker/api.ts CHANGED
@@ -1,8 +1,8 @@
1
+ import { execa } from "execa";
1
2
  import { Buffer } from "node:buffer";
2
3
  import { spawn } from "node:child_process";
3
4
  import fs from "node:fs/promises";
4
5
  import path from "node:path";
5
- import { exec } from "../os/exec.ts";
6
6
 
7
7
  /**
8
8
  * Options for Docker API requests
@@ -66,14 +66,39 @@ export class DockerApi {
66
66
  ? { ...process.env, DOCKER_CONFIG: this.configDir }
67
67
  : process.env;
68
68
 
69
- const command = `${this.dockerPath} ${args.join(" ")}`;
70
- const result = (await exec(command, {
71
- captureOutput: true,
72
- shell: true,
73
- env,
74
- })) as { stdout: string; stderr: string };
69
+ // Buffers to capture output
70
+ let stdout = "";
71
+ let stderr = "";
75
72
 
76
- return result;
73
+ // Create the subprocess
74
+ const subprocess = execa(this.dockerPath, args, {
75
+ env: env,
76
+ // Don't buffer - we'll handle streams manually
77
+ buffer: false,
78
+ encoding: "utf8",
79
+ });
80
+
81
+ // Stream stdout in real-time
82
+ subprocess.stdout?.on("data", (chunk: string) => {
83
+ process.stdout.write(chunk);
84
+ stdout += chunk;
85
+ });
86
+
87
+ // Stream stderr in real-time
88
+ subprocess.stderr?.on("data", (chunk: string) => {
89
+ process.stderr.write(chunk);
90
+ stderr += chunk;
91
+ });
92
+
93
+ // Wait for the process to complete
94
+ try {
95
+ await subprocess;
96
+ } catch (error: any) {
97
+ // Process failed, but we still have the output
98
+ throw new Error(stderr || error.message || "Command failed");
99
+ }
100
+
101
+ return { stdout, stderr };
77
102
  }
78
103
 
79
104
  /**