alchemy 0.45.6 → 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 +5 -1
  59. package/lib/cloudflare/container.d.ts.map +1 -1
  60. package/lib/cloudflare/container.js +42 -2
  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 +31 -7
  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 +18 -16
  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 +70 -3
  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 +65 -19
  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,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,
@@ -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
  /**
@@ -1,149 +1,6 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { ResourceScope } from "../resource.ts";
4
- import type { Scope } from "../scope.ts";
5
- import { deserialize, serialize } from "../serde.ts";
6
- import type { State, StateStore } from "../state.ts";
7
- import { ignore } from "../util/ignore.ts";
1
+ import * as state from "../state/file-system-state-store.ts";
8
2
 
9
- const stateRootDir = path.join(process.cwd(), ".alchemy");
10
- const ALCHEMY_SEPERATOR_CHAR = process.platform === "win32" ? "-" : ":";
11
-
12
- export class FileSystemStateStore implements StateStore {
13
- public readonly dir: string;
14
- private initialized = false;
15
- constructor(
16
- public readonly scope: Scope,
17
- options?: {
18
- rootDir?: string;
19
- },
20
- ) {
21
- this.dir = path.join(options?.rootDir ?? stateRootDir, ...scope.chain);
22
- }
23
-
24
- async init(): Promise<void> {
25
- if (this.initialized) {
26
- return;
27
- }
28
- this.initialized = true;
29
- await fs.promises.mkdir(this.dir, { recursive: true });
30
- }
31
-
32
- async deinit(): Promise<void> {
33
- await ignore("ENOENT", async () => {
34
- const entries = await fs.promises.readdir(this.dir, {
35
- withFileTypes: true,
36
- });
37
- const files = entries.filter((entry) => entry.isFile());
38
- if (files.length > 0) {
39
- throw new Error(
40
- `Cannot deinit: directory "${this.dir}" contains files and cannot be deleted.`,
41
- );
42
- }
43
- // Only folders (or empty), delete recursively
44
- await fs.promises.rm(this.dir, { recursive: true, force: true });
45
- });
46
- }
47
-
48
- async count(): Promise<number> {
49
- return Object.keys(await this.list()).length;
50
- }
51
-
52
- async list(): Promise<string[]> {
53
- try {
54
- const files = await fs.promises.readdir(this.dir, {
55
- withFileTypes: true,
56
- });
57
- return files
58
- .filter((dirent) => dirent.isFile() && dirent.name.endsWith(".json"))
59
- .map((dirent) => dirent.name.replace(/\.json$/, ""))
60
- .map((key) => key.replaceAll(":", "/"));
61
- } catch (error: any) {
62
- if (error.code === "ENOENT") {
63
- return [];
64
- }
65
- throw error;
66
- }
67
- }
68
-
69
- async get(key: string): Promise<State | undefined> {
70
- try {
71
- const content = await fs.promises.readFile(this.getPath(key), "utf8");
72
- const state = (await deserialize(
73
- this.scope,
74
- JSON.parse(content),
75
- )) as State;
76
- if (state.output === undefined) {
77
- state.output = {} as any;
78
- }
79
- state.output[ResourceScope] = this.scope;
80
- return state;
81
- } catch (error: any) {
82
- if (error.code === "ENOENT") {
83
- return undefined;
84
- }
85
- throw error;
86
- }
87
- }
88
-
89
- async set(key: string, value: State): Promise<void> {
90
- await this.init();
91
- const file = this.getPath(key);
92
- await fs.promises.mkdir(path.dirname(file), { recursive: true });
93
- await fs.promises.writeFile(
94
- file,
95
- JSON.stringify(await serialize(this.scope, value), null, 2),
96
- );
97
- }
98
-
99
- async delete(key: string): Promise<void> {
100
- try {
101
- return await fs.promises.unlink(this.getPath(key));
102
- } catch (error: any) {
103
- if (error.code === "ENOENT") {
104
- return;
105
- }
106
- throw error;
107
- }
108
- }
109
-
110
- async all(): Promise<Record<string, State>> {
111
- return this.getBatch(await this.list());
112
- }
113
-
114
- async getBatch(ids: string[]): Promise<Record<string, State>> {
115
- return Object.fromEntries(
116
- (
117
- await Promise.all(
118
- Array.from(ids).flatMap(async (id) => {
119
- const s = await this.get(id);
120
- if (s === undefined) {
121
- return [] as const;
122
- }
123
- return [[id, s]] as const;
124
- }),
125
- )
126
- ).flat(),
127
- );
128
- }
129
-
130
- private getPath(key: string): string {
131
- if (key.includes(":")) {
132
- throw new Error(`ID cannot include colons: ${key}`);
133
- }
134
- if (key.includes("/")) {
135
- //todo(michael): remove this next time we do a breaking change
136
- //* windows doesn't support ":" in file paths, but we already use ":"
137
- //* so now we use both to prevent breaking changes
138
- key = key.replaceAll("/", ALCHEMY_SEPERATOR_CHAR);
139
- }
140
- //todo(michael): remove this next time we do a breaking change
141
- //* windows doesn't support "*" in file paths, but we already use "*"
142
- //* when making cloudflare routes containing "*"
143
- //* so now we use "+" on windows but "*" on mac/linux to prevent breaking changes
144
- if (process.platform === "win32") {
145
- key = key.replaceAll("*", "+");
146
- }
147
- return path.join(this.dir, `${key}.json`);
148
- }
149
- }
3
+ /**
4
+ * @deprecated Use `FileSystemStateStore` from `alchemy/state` instead.
5
+ */
6
+ export const FileSystemStateStore = state.FileSystemStateStore;
package/src/fs/index.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  export * from "./copy-file.ts";
2
2
  export * from "./file-collection.ts";
3
3
  export * from "./file-ref.ts";
4
- export * from "./file-system-state-store.ts";
5
4
  export * from "./file.ts";
6
5
  export * from "./folder.ts";
7
6
  export * from "./static-astro-file.ts";
@@ -41,8 +41,9 @@ ALCHEMY_STATE_STORE=cloudflare
41
41
 
42
42
  ### Commands
43
43
  ```bash
44
- bun ./alchemy.run.ts # Deploy
45
- bun ./alchemy.run.ts --destroy # Destroy all resources
44
+ bun alchemy deploy # Deploy
45
+ bun alchemy dev # Local development
46
+ bun alchemy destroy # Destroy all resources
46
47
  ```
47
48
 
48
49
  ## Workers
@@ -107,7 +108,7 @@ declare module "cloudflare:workers" {
107
108
  ### Creating Durable Object Namespace
108
109
  ```typescript
109
110
  // Use 'new' instead of 'await' for DurableObjectNamespace
110
- const counter = new DurableObjectNamespace("counter", {
111
+ const counter = DurableObjectNamespace("counter", {
111
112
  className: "Counter",
112
113
  sqlite: true, // Enable SQLite storage
113
114
  });
@@ -161,7 +162,7 @@ export default {
161
162
  const sharedCounter = host.bindings.SHARED_COUNTER;
162
163
 
163
164
  // Method 2: Reference by worker script name
164
- const counter = new DurableObjectNamespace("counter", {
165
+ const counter = DurableObjectNamespace("counter", {
165
166
  className: "Counter",
166
167
  scriptName: "provider-worker"
167
168
  });
@@ -353,7 +354,7 @@ describe("Worker Tests", () => {
353
354
  ## Common Issues
354
355
 
355
356
  - **Missing finalize()**: Resources won't be cleaned up properly
356
- - **Wrong DurableObject syntax**: Use `new DurableObjectNamespace()` not `await`
357
+ - **Wrong DurableObject syntax**: Use `DurableObjectNamespace()` not `await`
357
358
  - **Type errors**: Set up env.d.ts file for binding types
358
359
  - **State conflicts**: Use different stages/prefixes for different environments
359
360
  - **Resource adoption**: Use `adopt: true` when migrating existing resources