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,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
@@ -306,7 +306,7 @@ export const Password = Resource(
306
306
  this.output.cidrs.length === props.cidrs.length &&
307
307
  this.output.cidrs.every((cidr, i) => cidr === props.cidrs![i])))
308
308
  ) {
309
- return this.replace();
309
+ return await this.replace();
310
310
  }
311
311
  const updateResponse = await api.patch(
312
312
  `/organizations/${props.organizationId}/databases/${databaseName}/branches/${branchName}/passwords/${this.output.id}`,
package/src/scope.ts CHANGED
@@ -1,10 +1,7 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
2
  import util from "node:util";
3
3
  import type { Phase } from "./alchemy.ts";
4
- import { D1StateStore } from "./cloudflare/d1-state-store.ts";
5
- import { DOStateStore } from "./cloudflare/do-state-store/index.ts";
6
4
  import { destroy, destroyAll } from "./destroy.ts";
7
- import { FileSystemStateStore } from "./fs/file-system-state-store.ts";
8
5
  import {
9
6
  ResourceFQN,
10
7
  ResourceID,
@@ -16,6 +13,8 @@ import {
16
13
  type ResourceProps,
17
14
  } from "./resource.ts";
18
15
  import type { State, StateStore, StateStoreType } from "./state.ts";
16
+ import { D1StateStore } from "./state/d1-state-store.ts";
17
+ import { FileSystemStateStore } from "./state/file-system-state-store.ts";
19
18
  import {
20
19
  createDummyLogger,
21
20
  createLoggerInstance,
@@ -499,10 +498,8 @@ export class Scope {
499
498
 
500
499
  const defaultStateStore: StateStoreType = (scope: Scope) => {
501
500
  switch (process.env.ALCHEMY_STATE_STORE) {
502
- case "cloudflare-d1":
501
+ case "d1":
503
502
  return new D1StateStore(scope);
504
- case "cloudflare":
505
- return new DOStateStore(scope);
506
503
  default:
507
504
  return new FileSystemStateStore(scope);
508
505
  }
@@ -0,0 +1,170 @@
1
+ import { alchemy } from "../alchemy.ts";
2
+ import { BUILD_DATE } from "../build-date.ts";
3
+ import type { CloudflareApiOptions } from "../cloudflare/api.ts";
4
+ import { createCloudflareApi } from "../cloudflare/api.ts";
5
+ import { getInternalWorkerBundle } from "../cloudflare/bundle/internal-worker-bundle.ts";
6
+ import { DurableObjectNamespace } from "../cloudflare/durable-object-namespace.ts";
7
+ import { getWorkerSettings } from "../cloudflare/worker-metadata.ts";
8
+ import {
9
+ enableWorkerSubdomain,
10
+ getAccountSubdomain,
11
+ getWorkerSubdomain,
12
+ } from "../cloudflare/worker-subdomain.ts";
13
+ import { putWorker } from "../cloudflare/worker.ts";
14
+ import type { Scope } from "../scope.ts";
15
+ import type { Secret } from "../secret.ts";
16
+ import { logger } from "../util/logger.ts";
17
+ import { memoize } from "../util/memoize.ts";
18
+ import { StateStoreProxy } from "./proxy.ts";
19
+
20
+ export interface CloudflareStateStoreOptions extends CloudflareApiOptions {
21
+ /**
22
+ * The name of the script to use for the state store.
23
+ * @default "alchemy-state-service"
24
+ */
25
+ scriptName?: string;
26
+ /**
27
+ * Whether to force the worker to be updated.
28
+ * This may be useful if you've lost the token for the state store and need to overwrite it.
29
+ * @default false
30
+ */
31
+ forceUpdate?: boolean;
32
+ /**
33
+ * The token to use for the state store.
34
+ * @default process.env.ALCHEMY_STATE_TOKEN
35
+ * @note You must use the same token for all deployments on your Cloudflare account.
36
+ */
37
+ stateToken?: Secret<string>;
38
+ }
39
+
40
+ /**
41
+ * A state store backed by a SQLite database in a Cloudflare Durable Object.
42
+ *
43
+ * @see {@link https://alchemy.run/guides/do-state-store DOStateStore}
44
+ */
45
+ export class CloudflareStateStore extends StateStoreProxy {
46
+ constructor(
47
+ scope: Scope,
48
+ private readonly options: CloudflareStateStoreOptions = {},
49
+ ) {
50
+ super(scope);
51
+ }
52
+
53
+ async provision(): Promise<StateStoreProxy.Dispatch> {
54
+ const { url, token } = await provision(this.options);
55
+ return async (method, params) => {
56
+ const request: StateStoreProxy.Request<
57
+ typeof method,
58
+ { chain: string[] }
59
+ > = {
60
+ method,
61
+ params,
62
+ context: { chain: this.scope.chain },
63
+ };
64
+ const response = await fetch(url, {
65
+ method: "POST",
66
+ headers: {
67
+ Authorization: `Bearer ${token}`,
68
+ "Content-Type": "application/json",
69
+ },
70
+ body: JSON.stringify(request),
71
+ });
72
+ if (!response.headers.get("Content-Type")?.includes("application/json")) {
73
+ throw new Error(
74
+ `[CloudflareStateStore] "${method}" request failed with status ${response.status}: Expected JSON response, but got ${response.headers.get("Content-Type")}`,
75
+ );
76
+ }
77
+ const json = (await response.json()) as StateStoreProxy.Response<
78
+ typeof method
79
+ >;
80
+ if (!json.success) {
81
+ throw new Error(
82
+ `[CloudflareStateStore] "${method}" request failed with status ${response.status}: ${json.error}`,
83
+ );
84
+ }
85
+ return json.result;
86
+ };
87
+ }
88
+ }
89
+
90
+ const provision = memoize(async (options: CloudflareStateStoreOptions) => {
91
+ const scriptName = options.scriptName ?? "alchemy-state-service";
92
+ const token =
93
+ options.stateToken ??
94
+ (await alchemy.secret.env(
95
+ "ALCHEMY_STATE_TOKEN",
96
+ undefined,
97
+ "Missing token for DOStateStore. Please set ALCHEMY_STATE_TOKEN in the environment or set the `stateToken` option in the DOStateStore constructor.",
98
+ ));
99
+
100
+ const api = await createCloudflareApi(options);
101
+ const [bundle, settings, subdomain] = await Promise.all([
102
+ getInternalWorkerBundle("cloudflare-state-store"),
103
+ getWorkerSettings(api, scriptName),
104
+ getWorkerSubdomain(api, scriptName),
105
+ ]);
106
+ if (!settings || !settings.tags.includes(bundle.tag) || options.forceUpdate) {
107
+ logger.log(
108
+ `[CloudflareStateStore] ${settings ? "Updating" : "Creating"}...`,
109
+ );
110
+ await putWorker(api, {
111
+ workerName: scriptName,
112
+ compatibilityDate: BUILD_DATE,
113
+ format: "esm",
114
+ scriptBundle: {
115
+ entrypoint: bundle.file.name,
116
+ files: [bundle.file],
117
+ hash: bundle.tag,
118
+ },
119
+ compatibilityFlags: [],
120
+ bindings: {
121
+ STORE: DurableObjectNamespace(scriptName, {
122
+ className: "Store",
123
+ sqlite: true,
124
+ }),
125
+ STATE_TOKEN: token,
126
+ },
127
+ tags: [bundle.tag],
128
+ });
129
+ }
130
+ if (!subdomain.enabled) {
131
+ await enableWorkerSubdomain(api, scriptName);
132
+ }
133
+ const url = `https://${scriptName}.${await getAccountSubdomain(api)}.workers.dev`;
134
+ await pollUntilReady(() =>
135
+ fetch(url, {
136
+ method: "HEAD",
137
+ headers: { Authorization: `Bearer ${token.unencrypted}` },
138
+ }),
139
+ );
140
+ return { url, token: token.unencrypted };
141
+ });
142
+
143
+ async function pollUntilReady(fn: () => Promise<Response>) {
144
+ // This ensures the token is correct and the worker is ready to use.
145
+ let last: Response | undefined;
146
+ let delay = 1000;
147
+ for (let i = 0; i < 20; i++) {
148
+ const res = await fn();
149
+ if (res.ok) {
150
+ return;
151
+ }
152
+ if (res.status === 401) {
153
+ throw new Error(
154
+ "[CloudflareStateStore] The token is invalid. Please check your ALCHEMY_STATE_TOKEN environment variable, or set `forceUpdate: true` in the CloudflareStateStore constructor to overwrite the current token.",
155
+ );
156
+ }
157
+ if (!last) {
158
+ logger.log("[CloudflareStateStore] Waiting for deployment...");
159
+ }
160
+ last = res;
161
+ // Exponential backoff with jitter
162
+ const jitter = Math.random() * 0.1 * delay;
163
+ await new Promise((resolve) => setTimeout(resolve, delay + jitter));
164
+ delay *= 1.5; // Increase the delay for next attempt
165
+ delay = Math.min(delay, 10000); // Cap at 10 seconds
166
+ }
167
+ throw new Error(
168
+ `[CloudflareStateStore] Failed to reach state store: ${last?.status} ${last?.statusText}`,
169
+ );
170
+ }
@@ -0,0 +1,102 @@
1
+ import { drizzle, type RemoteCallback } from "drizzle-orm/sqlite-proxy";
2
+ import assert from "node:assert";
3
+ import { extractCloudflareResult } from "../cloudflare/api-response.ts";
4
+ import type { CloudflareApi, CloudflareApiOptions } from "../cloudflare/api.ts";
5
+ import type { Scope } from "../scope.ts";
6
+ import { memoize } from "../util/memoize.ts";
7
+ import { MIGRATIONS_DIRECTORY } from "./migrations.ts";
8
+ import { SQLiteStateStoreOperations } from "./operations.ts";
9
+ import { StateStoreProxy } from "./proxy.ts";
10
+ import * as schema from "./schema.ts";
11
+
12
+ export interface D1StateStoreOptions extends CloudflareApiOptions {
13
+ databaseName?: string;
14
+ }
15
+
16
+ /**
17
+ * @deprecated Use `CloudflareStateStore` from `alchemy/state` instead.
18
+ */
19
+ export class D1StateStore extends StateStoreProxy {
20
+ constructor(
21
+ scope: Scope,
22
+ private options: D1StateStoreOptions = {},
23
+ ) {
24
+ super(scope);
25
+ }
26
+
27
+ async provision(): Promise<StateStoreProxy.Dispatch> {
28
+ const db = await createDatabaseClient(this.options);
29
+ const operations = new SQLiteStateStoreOperations(db, {
30
+ chain: this.scope.chain,
31
+ });
32
+ return operations.dispatch.bind(operations);
33
+ }
34
+ }
35
+
36
+ const createDatabaseClient = memoize(async (options: D1StateStoreOptions) => {
37
+ const { createCloudflareApi } = await import("../cloudflare/api.ts");
38
+ const api = await createCloudflareApi(options);
39
+ const database = await upsertDatabase(
40
+ api,
41
+ options.databaseName ?? "alchemy-state",
42
+ );
43
+ const remoteCallback: RemoteCallback = async (sql, params) => {
44
+ const [result] = await extractCloudflareResult<
45
+ {
46
+ results: { columns: string[]; rows: any[][] };
47
+ }[]
48
+ >(
49
+ "execute D1 query",
50
+ api.post(
51
+ `/accounts/${api.accountId}/d1/database/${database.id}/raw`,
52
+ { sql, params },
53
+ {
54
+ headers: {
55
+ "Content-Type": "application/json",
56
+ },
57
+ },
58
+ ),
59
+ );
60
+ assert(result, "Missing result");
61
+ return {
62
+ rows: Object.values(result.results.rows),
63
+ };
64
+ };
65
+ return drizzle(remoteCallback, {
66
+ schema,
67
+ });
68
+ });
69
+
70
+ const upsertDatabase = async (api: CloudflareApi, databaseName: string) => {
71
+ const { listDatabases, createDatabase } = await import(
72
+ "../cloudflare/d1-database.ts"
73
+ );
74
+ const { applyMigrations, listMigrationsFiles } = await import(
75
+ "../cloudflare/d1-migrations.ts"
76
+ );
77
+ const migrate = async (databaseId: string) => {
78
+ await applyMigrations({
79
+ migrationsFiles: await listMigrationsFiles(MIGRATIONS_DIRECTORY),
80
+ migrationsTable: "migrations",
81
+ accountId: api.accountId,
82
+ databaseId,
83
+ api,
84
+ quiet: true,
85
+ });
86
+ };
87
+ const databases = await listDatabases(api, databaseName);
88
+ if (databases[0]) {
89
+ await migrate(databases[0].id);
90
+ return {
91
+ id: databases[0].id,
92
+ };
93
+ }
94
+ const res = await createDatabase(api, databaseName, {
95
+ readReplication: { mode: "disabled" },
96
+ });
97
+ assert(res.result.uuid, "Missing UUID for database");
98
+ await migrate(res.result.uuid);
99
+ return {
100
+ id: res.result.uuid,
101
+ };
102
+ };
@@ -1,14 +1,16 @@
1
1
  import { alchemy } from "../../alchemy.ts";
2
+ import {
3
+ createCloudflareApi,
4
+ type CloudflareApiOptions,
5
+ } from "../../cloudflare/api.ts";
6
+ import { getAccountSubdomain } from "../../cloudflare/worker-subdomain.ts";
2
7
  import { ResourceScope } from "../../resource.ts";
3
8
  import type { Scope } from "../../scope.ts";
4
- import { serialize } from "../../serde.ts";
9
+ import { deserialize, serialize } from "../../serde.ts";
5
10
  import type { State, StateStore } from "../../state.ts";
6
- import { deserialize } from "../../serde.ts";
7
- import { createCloudflareApi, type CloudflareApiOptions } from "../api.ts";
8
- import { getAccountSubdomain } from "../worker/shared.ts";
9
- import { DOStateStoreClient, upsertStateStoreWorker } from "./internal.ts";
11
+ import { DOFSStateStoreClient, upsertStateStoreWorker } from "./store.ts";
10
12
 
11
- export interface DOStateStoreOptions extends CloudflareApiOptions {
13
+ export interface DOFSStateStoreOptions extends CloudflareApiOptions {
12
14
  /**
13
15
  * The prefix to use for state keys.
14
16
  * Each app and stage has its own state store, so this is primarily for testing.
@@ -45,13 +47,18 @@ export interface DOStateStoreOptions extends CloudflareApiOptions {
45
47
  };
46
48
  }
47
49
 
48
- export class DOStateStore implements StateStore {
50
+ /**
51
+ * A state store backed by a {@link https://www.npmjs.com/package/dofs Durable Object File System (DOFS)}.
52
+ *
53
+ * @deprecated This state store is no longer recommended for production use. Please use {@link https://alchemy.run/guides/cloudflare-state-store/ CloudflareStateStore} from `alchemy/state` instead, which offers better reliability and performance.
54
+ */
55
+ export class DOFSStateStore implements StateStore {
49
56
  private prefix: string;
50
- private client?: Promise<DOStateStoreClient>;
57
+ private client?: Promise<DOFSStateStoreClient>;
51
58
 
52
59
  constructor(
53
60
  private readonly scope: Scope,
54
- private readonly options: DOStateStoreOptions = {},
61
+ private readonly options: DOFSStateStoreOptions = {},
55
62
  ) {
56
63
  this.prefix = [options.prefix ?? "alchemy", ...scope.chain, ""].join("/");
57
64
  }
@@ -61,7 +68,7 @@ export class DOStateStore implements StateStore {
61
68
  this.options.worker?.token ??
62
69
  (await alchemy.secret.env.ALCHEMY_STATE_TOKEN).unencrypted;
63
70
  if (this.options.worker && "url" in this.options.worker) {
64
- const client = new DOStateStoreClient({
71
+ const client = new DOFSStateStoreClient({
65
72
  app: this.scope.appName ?? "alchemy",
66
73
  stage: this.scope.stage,
67
74
  url: this.options.worker.url,
@@ -75,11 +82,11 @@ export class DOStateStore implements StateStore {
75
82
  }
76
83
  if (res.status === 401) {
77
84
  throw new Error(
78
- "A worker URL was provided to DOStateStore, but the token is incorrect. Correct the token or remove the worker URL to create a new worker.",
85
+ "A worker URL was provided to DOFSStateStore, but the token is incorrect. Correct the token or remove the worker URL to create a new worker.",
79
86
  );
80
87
  }
81
88
  throw new Error(
82
- `A worker URL was provided to DOStateStore, but the worker status is ${res.status} ${res.statusText}.`,
89
+ `A worker URL was provided to DOFSStateStore, but the worker status is ${res.status} ${res.statusText}.`,
83
90
  );
84
91
  }
85
92
  const workerName = this.options.worker?.name ?? "alchemy-state";
@@ -98,7 +105,7 @@ export class DOStateStore implements StateStore {
98
105
  "Failed to access state store worker because the workers.dev subdomain is not available.",
99
106
  );
100
107
  }
101
- const client = new DOStateStoreClient({
108
+ const client = new DOFSStateStoreClient({
102
109
  app: this.scope.appName ?? "alchemy",
103
110
  stage: this.scope.stage,
104
111
  url: `https://${workerName}.${subdomain}.workers.dev`,
@@ -1,10 +1,10 @@
1
+ import { handleApiError } from "../../cloudflare/api-error.ts";
2
+ import type { CloudflareApi } from "../../cloudflare/api.ts";
3
+ import { getInternalWorkerBundle } from "../../cloudflare/bundle/internal-worker-bundle.ts";
4
+ import type { WorkerMetadata } from "../../cloudflare/worker-metadata.ts";
1
5
  import { logger } from "../../util/logger.ts";
2
6
  import { withExponentialBackoff } from "../../util/retry.ts";
3
- import { handleApiError } from "../api-error.ts";
4
- import type { CloudflareApi } from "../api.ts";
5
- import type { WorkerMetadata } from "../worker-metadata.ts";
6
- import { getWorkerTemplate } from "../worker/shared.ts";
7
- import type { DOStateStoreAPI } from "./types.ts";
7
+ import type { DOStateStoreAPI } from "./api.ts";
8
8
 
9
9
  interface DOStateStoreClientOptions {
10
10
  app: string;
@@ -22,7 +22,7 @@ class StateStoreError extends Error {
22
22
  }
23
23
  }
24
24
 
25
- export class DOStateStoreClient {
25
+ export class DOFSStateStoreClient {
26
26
  constructor(private readonly options: DOStateStoreClientOptions) {}
27
27
 
28
28
  async rpc<T extends keyof DOStateStoreAPI.API>(
@@ -141,13 +141,13 @@ export async function upsertStateStoreWorker(
141
141
  return;
142
142
  }
143
143
  const formData = new FormData();
144
- const worker = await getWorkerTemplate("do-state-store");
145
- formData.append(worker.name, worker);
144
+ const { file } = await getInternalWorkerBundle("dofs-state-store");
145
+ formData.append(file.name, file);
146
146
  formData.append(
147
147
  "metadata",
148
148
  new Blob([
149
149
  JSON.stringify({
150
- main_module: worker.name,
150
+ main_module: file.name,
151
151
  compatibility_date: "2025-06-01",
152
152
  compatibility_flags: ["nodejs_compat"],
153
153
  bindings: [
@@ -222,21 +222,3 @@ async function getWorkerStatus(api: CloudflareApi, workerName: string) {
222
222
  tag: json.result.tags.find((tag) => tag.startsWith("alchemy-state-store:")),
223
223
  };
224
224
  }
225
-
226
- export async function getAccountSubdomain(api: CloudflareApi) {
227
- const key = `subdomain:${api.accountId}`;
228
- const cached = cache.get(key);
229
- if (cached) {
230
- return cached;
231
- }
232
- const res = await api.get(`/accounts/${api.accountId}/workers/subdomain`);
233
- if (!res.ok) {
234
- throw new Error(
235
- `Failed to get account subdomain: ${res.status} ${res.statusText}: ${await res.text().catch(() => "unknown error")}`,
236
- );
237
- }
238
- const json: { result: { subdomain: string } } = await res.json();
239
- const subdomain = json.result.subdomain;
240
- cache.set(key, subdomain);
241
- return subdomain;
242
- }