alchemy 0.74.2 → 0.75.1

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 (351) hide show
  1. package/README.md +1 -1
  2. package/bin/alchemy.js +1781 -1746
  3. package/bin/alchemy.ts +1 -1
  4. package/bin/commands/create.ts +5 -4
  5. package/bin/commands/init.ts +109 -65
  6. package/bin/commands/util.ts +3 -1
  7. package/bin/constants.ts +2 -2
  8. package/bin/services/dependencies.ts +4 -4
  9. package/bin/services/execute-alchemy.ts +5 -3
  10. package/bin/services/get-package-version.ts +4 -4
  11. package/bin/services/github-workflow.ts +9 -10
  12. package/bin/services/package-manager.ts +1 -5
  13. package/bin/services/template-manager.ts +20 -13
  14. package/bin/services/vibe-rules.ts +6 -5
  15. package/bin/trpc.ts +7 -0
  16. package/bin/types.ts +1 -0
  17. package/lib/alchemy.d.ts +1 -1
  18. package/lib/alchemy.d.ts.map +1 -1
  19. package/lib/alchemy.js +30 -2
  20. package/lib/alchemy.js.map +1 -1
  21. package/lib/apply.js +10 -0
  22. package/lib/apply.js.map +1 -1
  23. package/lib/auth.js +1 -1
  24. package/lib/auth.js.map +1 -1
  25. package/lib/aws/control/types.d.ts.map +1 -1
  26. package/lib/aws/control/types.js.map +1 -1
  27. package/lib/clickhouse/api/sdk.gen.d.ts.map +1 -1
  28. package/lib/clickhouse/api/sdk.gen.js.map +1 -1
  29. package/lib/cloudflare/account-api-token.d.ts.map +1 -1
  30. package/lib/cloudflare/account-api-token.js.map +1 -1
  31. package/lib/cloudflare/astro/astro.js +1 -1
  32. package/lib/cloudflare/astro/astro.js.map +1 -1
  33. package/lib/cloudflare/bound.d.ts.map +1 -1
  34. package/lib/cloudflare/bucket.d.ts +1 -1
  35. package/lib/cloudflare/bucket.d.ts.map +1 -1
  36. package/lib/cloudflare/bucket.js +1 -1
  37. package/lib/cloudflare/bucket.js.map +1 -1
  38. package/lib/cloudflare/bun-spa/bun-spa.d.ts +1 -1
  39. package/lib/cloudflare/bun-spa/bun-spa.d.ts.map +1 -1
  40. package/lib/cloudflare/bun-spa/bun-spa.js +10 -11
  41. package/lib/cloudflare/bun-spa/bun-spa.js.map +1 -1
  42. package/lib/cloudflare/bun-spa/get-bun-spa-backend.d.ts +11 -0
  43. package/lib/cloudflare/bun-spa/get-bun-spa-backend.d.ts.map +1 -0
  44. package/lib/cloudflare/bun-spa/get-bun-spa-backend.js +26 -0
  45. package/lib/cloudflare/bun-spa/get-bun-spa-backend.js.map +1 -0
  46. package/lib/cloudflare/bun-spa/index.d.ts +2 -0
  47. package/lib/cloudflare/bun-spa/index.d.ts.map +1 -0
  48. package/lib/cloudflare/bun-spa/index.js +2 -0
  49. package/lib/cloudflare/bun-spa/index.js.map +1 -0
  50. package/lib/cloudflare/bundle/internal-worker-bundle.js +1 -1
  51. package/lib/cloudflare/bundle/internal-worker-bundle.js.map +1 -1
  52. package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js +1 -1
  53. package/lib/cloudflare/bundle/plugin-hybrid-node-compat.js.map +1 -1
  54. package/lib/cloudflare/bundle/plugin-node-compat.js +1 -1
  55. package/lib/cloudflare/bundle/plugin-node-compat.js.map +1 -1
  56. package/lib/cloudflare/bundle/plugin-wasm.js +1 -1
  57. package/lib/cloudflare/bundle/plugin-wasm.js.map +1 -1
  58. package/lib/cloudflare/cloudflare-env-proxy.d.ts.map +1 -1
  59. package/lib/cloudflare/cloudflare-env-proxy.js +3 -3
  60. package/lib/cloudflare/cloudflare-env-proxy.js.map +1 -1
  61. package/lib/cloudflare/d1-migrations.js +1 -1
  62. package/lib/cloudflare/d1-migrations.js.map +1 -1
  63. package/lib/cloudflare/dns-records.js.map +1 -1
  64. package/lib/cloudflare/kv-namespace.d.ts +5 -0
  65. package/lib/cloudflare/kv-namespace.d.ts.map +1 -1
  66. package/lib/cloudflare/kv-namespace.js +44 -19
  67. package/lib/cloudflare/kv-namespace.js.map +1 -1
  68. package/lib/cloudflare/miniflare/delete.d.ts.map +1 -1
  69. package/lib/cloudflare/miniflare/delete.js +3 -0
  70. package/lib/cloudflare/miniflare/delete.js.map +1 -1
  71. package/lib/cloudflare/miniflare/miniflare-controller.js +1 -1
  72. package/lib/cloudflare/miniflare/miniflare-controller.js.map +1 -1
  73. package/lib/cloudflare/miniflare/miniflare-worker-proxy.d.ts.map +1 -1
  74. package/lib/cloudflare/miniflare/miniflare-worker-proxy.js +34 -4
  75. package/lib/cloudflare/miniflare/miniflare-worker-proxy.js.map +1 -1
  76. package/lib/cloudflare/miniflare/paths.d.ts +0 -1
  77. package/lib/cloudflare/miniflare/paths.d.ts.map +1 -1
  78. package/lib/cloudflare/miniflare/paths.js +6 -18
  79. package/lib/cloudflare/miniflare/paths.js.map +1 -1
  80. package/lib/cloudflare/next.js +1 -1
  81. package/lib/cloudflare/next.js.map +1 -1
  82. package/lib/cloudflare/nuxt/nuxt.js +1 -1
  83. package/lib/cloudflare/nuxt/nuxt.js.map +1 -1
  84. package/lib/cloudflare/nuxt/plugin.d.ts.map +1 -1
  85. package/lib/cloudflare/nuxt/plugin.js +2 -2
  86. package/lib/cloudflare/nuxt/plugin.js.map +1 -1
  87. package/lib/cloudflare/react-router/plugin.js +1 -1
  88. package/lib/cloudflare/react-router/plugin.js.map +1 -1
  89. package/lib/cloudflare/react-router/react-router.js +1 -1
  90. package/lib/cloudflare/react-router/react-router.js.map +1 -1
  91. package/lib/cloudflare/redwood/redwood.js +1 -1
  92. package/lib/cloudflare/redwood/redwood.js.map +1 -1
  93. package/lib/cloudflare/sveltekit/sveltekit.js +1 -1
  94. package/lib/cloudflare/sveltekit/sveltekit.js.map +1 -1
  95. package/lib/cloudflare/tanstack-start/tanstack-start.js +1 -1
  96. package/lib/cloudflare/tanstack-start/tanstack-start.js.map +1 -1
  97. package/lib/cloudflare/tunnel.d.ts.map +1 -1
  98. package/lib/cloudflare/tunnel.js +25 -1
  99. package/lib/cloudflare/tunnel.js.map +1 -1
  100. package/lib/cloudflare/vite/plugin.d.ts.map +1 -1
  101. package/lib/cloudflare/vite/plugin.js +4 -4
  102. package/lib/cloudflare/vite/plugin.js.map +1 -1
  103. package/lib/cloudflare/website.d.ts.map +1 -1
  104. package/lib/cloudflare/website.js +1 -5
  105. package/lib/cloudflare/website.js.map +1 -1
  106. package/lib/cloudflare/worker-assets.d.ts +1 -1
  107. package/lib/cloudflare/worker-assets.d.ts.map +1 -1
  108. package/lib/cloudflare/worker-assets.js +1 -1
  109. package/lib/cloudflare/worker-assets.js.map +1 -1
  110. package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
  111. package/lib/cloudflare/worker-metadata.js.map +1 -1
  112. package/lib/cloudflare/worker-tail.d.ts.map +1 -1
  113. package/lib/cloudflare/worker-tail.js.map +1 -1
  114. package/lib/cloudflare/worker.d.ts.map +1 -1
  115. package/lib/cloudflare/worker.js +1 -1
  116. package/lib/cloudflare/worker.js.map +1 -1
  117. package/lib/cloudflare/wrangler.json.js +1 -2
  118. package/lib/cloudflare/wrangler.json.js.map +1 -1
  119. package/lib/coinbase/evm-account.d.ts.map +1 -1
  120. package/lib/coinbase/evm-account.js.map +1 -1
  121. package/lib/coinbase/evm-smart-account.d.ts.map +1 -1
  122. package/lib/coinbase/evm-smart-account.js.map +1 -1
  123. package/lib/coinbase/faucet.js +2 -2
  124. package/lib/coinbase/faucet.js.map +1 -1
  125. package/lib/docker/api.d.ts.map +1 -1
  126. package/lib/docker/api.js +1 -1
  127. package/lib/docker/api.js.map +1 -1
  128. package/lib/docker/image.js +1 -1
  129. package/lib/docker/image.js.map +1 -1
  130. package/lib/esbuild/bundle.js +1 -1
  131. package/lib/esbuild/bundle.js.map +1 -1
  132. package/lib/fs/file.js +1 -1
  133. package/lib/fs/file.js.map +1 -1
  134. package/lib/github/secret.d.ts.map +1 -1
  135. package/lib/github/secret.js.map +1 -1
  136. package/lib/llms.js +1 -1
  137. package/lib/llms.js.map +1 -1
  138. package/lib/neon/api/sdk.gen.d.ts.map +1 -1
  139. package/lib/neon/api/sdk.gen.js.map +1 -1
  140. package/lib/os/exec.d.ts.map +1 -1
  141. package/lib/os/exec.js +1 -1
  142. package/lib/os/exec.js.map +1 -1
  143. package/lib/planetscale/api/sdk.gen.d.ts.map +1 -1
  144. package/lib/planetscale/api/sdk.gen.js.map +1 -1
  145. package/lib/prisma-postgres/api/sdk.gen.d.ts.map +1 -1
  146. package/lib/prisma-postgres/api/sdk.gen.js.map +1 -1
  147. package/lib/scope.d.ts.map +1 -1
  148. package/lib/scope.js +3 -3
  149. package/lib/scope.js.map +1 -1
  150. package/lib/sentry/client-key.js +1 -1
  151. package/lib/sentry/client-key.js.map +1 -1
  152. package/lib/state/file-system-state-store.js +1 -1
  153. package/lib/state/file-system-state-store.js.map +1 -1
  154. package/lib/state/migrations.js +1 -1
  155. package/lib/state/migrations.js.map +1 -1
  156. package/lib/state/sqlite-state-store.js +1 -1
  157. package/lib/state/sqlite-state-store.js.map +1 -1
  158. package/lib/stripe/file.d.ts +3 -3
  159. package/lib/stripe/file.js +3 -3
  160. package/lib/test/bun.d.ts.map +1 -1
  161. package/lib/test/bun.js +1 -1
  162. package/lib/test/bun.js.map +1 -1
  163. package/lib/test/prune.js +1 -1
  164. package/lib/test/prune.js.map +1 -1
  165. package/lib/test/vitest.d.ts.map +1 -1
  166. package/lib/test/vitest.js +1 -1
  167. package/lib/test/vitest.js.map +1 -1
  168. package/lib/util/api/client/client.gen.d.ts +1 -1
  169. package/lib/util/api/client/client.gen.js +45 -45
  170. package/lib/util/api/client/types.gen.d.ts +22 -22
  171. package/lib/util/api/client/utils.gen.d.ts +3 -3
  172. package/lib/util/api/client/utils.gen.d.ts.map +1 -1
  173. package/lib/util/api/client/utils.gen.js +34 -34
  174. package/lib/util/api/client/utils.gen.js.map +1 -1
  175. package/lib/util/api/core/auth.gen.d.ts +3 -3
  176. package/lib/util/api/core/auth.gen.js +3 -3
  177. package/lib/util/api/core/bodySerializer.gen.d.ts +1 -1
  178. package/lib/util/api/core/bodySerializer.gen.js +3 -3
  179. package/lib/util/api/core/params.gen.d.ts +3 -3
  180. package/lib/util/api/core/params.gen.js +7 -7
  181. package/lib/util/api/core/pathSerializer.gen.d.ts +3 -3
  182. package/lib/util/api/core/pathSerializer.gen.js +36 -36
  183. package/lib/util/api/core/serverSentEvents.gen.d.ts +3 -3
  184. package/lib/util/api/core/serverSentEvents.gen.js +18 -18
  185. package/lib/util/api/core/types.gen.d.ts +4 -4
  186. package/lib/util/api/core/utils.gen.d.ts +1 -1
  187. package/lib/util/api/core/utils.gen.js +17 -17
  188. package/lib/util/camel-to-snake.d.ts.map +1 -1
  189. package/lib/util/content-type.js +1 -1
  190. package/lib/util/content-type.js.map +1 -1
  191. package/lib/util/find-workspace-root.d.ts +3 -0
  192. package/lib/util/find-workspace-root.d.ts.map +1 -0
  193. package/lib/util/find-workspace-root.js +64 -0
  194. package/lib/util/find-workspace-root.js.map +1 -0
  195. package/lib/util/idempotent-spawn.d.ts.map +1 -1
  196. package/lib/util/idempotent-spawn.js +2 -2
  197. package/lib/util/idempotent-spawn.js.map +1 -1
  198. package/lib/util/lock.js +1 -1
  199. package/lib/util/lock.js.map +1 -1
  200. package/lib/util/peer.d.ts.map +1 -1
  201. package/lib/util/peer.js.map +1 -1
  202. package/package.json +6 -1
  203. package/src/alchemy.ts +60 -4
  204. package/src/apply.ts +16 -1
  205. package/src/auth.ts +1 -1
  206. package/src/aws/control/types.ts +87107 -85281
  207. package/src/clickhouse/api/sdk.gen.ts +1 -3
  208. package/src/cloudflare/account-api-token.ts +3 -1
  209. package/src/cloudflare/astro/astro.ts +1 -1
  210. package/src/cloudflare/bound.ts +64 -65
  211. package/src/cloudflare/bucket.ts +4 -7
  212. package/src/cloudflare/bun-spa/bun-spa.ts +13 -13
  213. package/src/cloudflare/bun-spa/get-bun-spa-backend.ts +29 -0
  214. package/src/cloudflare/bun-spa/index.ts +1 -0
  215. package/src/cloudflare/bundle/internal-worker-bundle.ts +1 -1
  216. package/src/cloudflare/bundle/plugin-hybrid-node-compat.ts +1 -1
  217. package/src/cloudflare/bundle/plugin-node-compat.ts +1 -1
  218. package/src/cloudflare/bundle/plugin-wasm.ts +1 -1
  219. package/src/cloudflare/cloudflare-env-proxy.ts +2 -4
  220. package/src/cloudflare/d1-migrations.ts +1 -1
  221. package/src/cloudflare/dns-records.ts +3 -1
  222. package/src/cloudflare/kv-namespace.ts +52 -20
  223. package/src/cloudflare/miniflare/delete.ts +3 -0
  224. package/src/cloudflare/miniflare/miniflare-controller.ts +1 -1
  225. package/src/cloudflare/miniflare/miniflare-worker-proxy.ts +39 -4
  226. package/src/cloudflare/miniflare/paths.ts +6 -26
  227. package/src/cloudflare/next.ts +1 -1
  228. package/src/cloudflare/nuxt/nuxt.ts +1 -1
  229. package/src/cloudflare/nuxt/plugin.ts +1 -4
  230. package/src/cloudflare/react-router/plugin.ts +1 -1
  231. package/src/cloudflare/react-router/react-router.ts +1 -1
  232. package/src/cloudflare/redwood/redwood.ts +1 -1
  233. package/src/cloudflare/sveltekit/sveltekit.ts +1 -1
  234. package/src/cloudflare/tanstack-start/tanstack-start.ts +1 -1
  235. package/src/cloudflare/tunnel.ts +36 -1
  236. package/src/cloudflare/vite/plugin.ts +2 -4
  237. package/src/cloudflare/website.ts +1 -6
  238. package/src/cloudflare/worker-assets.ts +1 -6
  239. package/src/cloudflare/worker-metadata.ts +5 -3
  240. package/src/cloudflare/worker-tail.ts +3 -1
  241. package/src/cloudflare/worker.ts +1 -3
  242. package/src/cloudflare/wrangler.json.ts +1 -2
  243. package/src/coinbase/evm-account.ts +3 -1
  244. package/src/coinbase/evm-smart-account.ts +3 -1
  245. package/src/coinbase/faucet.ts +2 -2
  246. package/src/docker/api.ts +4 -2
  247. package/src/docker/image.ts +1 -1
  248. package/src/esbuild/bundle.ts +1 -1
  249. package/src/fs/file.ts +1 -1
  250. package/src/github/secret.ts +5 -1
  251. package/src/llms.ts +1 -1
  252. package/src/neon/api/sdk.gen.ts +1 -3
  253. package/src/os/exec.ts +4 -2
  254. package/src/planetscale/api/sdk.gen.ts +1 -3
  255. package/src/prisma-postgres/api/sdk.gen.ts +1 -3
  256. package/src/scope.ts +3 -3
  257. package/src/sentry/client-key.ts +1 -5
  258. package/src/state/file-system-state-store.ts +1 -1
  259. package/src/state/migrations.ts +1 -1
  260. package/src/state/sqlite-state-store.ts +1 -1
  261. package/src/stripe/file.ts +3 -3
  262. package/src/test/bun.ts +4 -2
  263. package/src/test/prune.ts +1 -1
  264. package/src/test/vitest.ts +4 -2
  265. package/src/util/api/client/client.gen.ts +49 -49
  266. package/src/util/api/client/types.gen.ts +43 -43
  267. package/src/util/api/client/utils.gen.ts +47 -42
  268. package/src/util/api/core/auth.gen.ts +6 -6
  269. package/src/util/api/core/bodySerializer.gen.ts +4 -4
  270. package/src/util/api/core/params.gen.ts +10 -10
  271. package/src/util/api/core/pathSerializer.gen.ts +39 -39
  272. package/src/util/api/core/serverSentEvents.gen.ts +22 -22
  273. package/src/util/api/core/types.gen.ts +12 -12
  274. package/src/util/api/core/utils.gen.ts +18 -18
  275. package/src/util/camel-to-snake.ts +12 -10
  276. package/src/util/content-type.ts +1 -1
  277. package/{bin/services → src/util}/find-workspace-root.ts +27 -5
  278. package/src/util/idempotent-spawn.ts +2 -6
  279. package/src/util/lock.ts +1 -1
  280. package/src/util/peer.ts +3 -1
  281. package/templates/astro/alchemy.run.ts +0 -2
  282. package/templates/astro/astro.config.mjs +3 -3
  283. package/templates/astro/src/pages/api/hello.ts +16 -13
  284. package/templates/bun-spa/README.md +94 -0
  285. package/templates/bun-spa/_env +1 -0
  286. package/templates/bun-spa/_env.example +1 -0
  287. package/templates/bun-spa/_gitignore +29 -0
  288. package/templates/bun-spa/alchemy.run.ts +21 -0
  289. package/templates/bun-spa/bun-env.d.ts +25 -0
  290. package/templates/bun-spa/eslint.config.js +26 -0
  291. package/templates/bun-spa/package.json +30 -0
  292. package/templates/bun-spa/src/App.css +46 -0
  293. package/templates/bun-spa/src/App.tsx +53 -0
  294. package/templates/bun-spa/src/assets/logo.svg +1 -0
  295. package/templates/bun-spa/src/assets/react.svg +1 -0
  296. package/templates/bun-spa/src/frontend.tsx +14 -0
  297. package/templates/bun-spa/src/index.css +69 -0
  298. package/templates/bun-spa/src/index.html +14 -0
  299. package/templates/bun-spa/src/worker.ts +51 -0
  300. package/templates/bun-spa/tsconfig.json +24 -0
  301. package/templates/hono/alchemy.run.ts +0 -2
  302. package/templates/hono/src/index.ts +13 -13
  303. package/templates/nextjs/alchemy.run.ts +1 -3
  304. package/templates/nextjs/eslint.config.mjs +1 -1
  305. package/templates/nextjs/next-env.d.ts +1 -1
  306. package/templates/nextjs/next.config.ts +1 -1
  307. package/templates/nextjs/open-next.config.ts +1 -1
  308. package/templates/nextjs/src/app/api/hello/route.ts +2 -2
  309. package/templates/nextjs/src/app/layout.tsx +1 -1
  310. package/templates/nextjs/src/app/page.tsx +14 -15
  311. package/templates/nextjs/types/env.d.ts +4 -4
  312. package/templates/nuxt/alchemy.run.ts +0 -2
  313. package/templates/nuxt/server/middleware/auth.ts +1 -1
  314. package/templates/nuxt/server/middleware/hello.ts +2 -2
  315. package/templates/react-router/alchemy.run.ts +0 -2
  316. package/templates/react-router/app/entry.server.tsx +2 -2
  317. package/templates/react-router/package.json +1 -1
  318. package/templates/react-router/vite.config.ts +1 -1
  319. package/templates/react-router/workers/app.ts +2 -2
  320. package/templates/rwsdk/alchemy.run.ts +6 -4
  321. package/templates/rwsdk/package.json +1 -1
  322. package/templates/sveltekit/alchemy.run.ts +0 -2
  323. package/templates/sveltekit/package.json +1 -1
  324. package/templates/sveltekit/src/app.d.ts +7 -7
  325. package/templates/sveltekit/svelte.config.js +4 -4
  326. package/templates/sveltekit/vite.config.ts +3 -3
  327. package/templates/tanstack-start/alchemy.run.ts +0 -2
  328. package/templates/tanstack-start/package.json +1 -1
  329. package/templates/tanstack-start/src/components/Header.tsx +2 -2
  330. package/templates/tanstack-start/src/router.tsx +4 -4
  331. package/templates/tanstack-start/src/routes/__root.tsx +10 -10
  332. package/templates/tanstack-start/src/routes/api.demo-names.ts +6 -6
  333. package/templates/tanstack-start/src/routes/demo.start.api-request.tsx +11 -11
  334. package/templates/tanstack-start/src/routes/demo.start.server-funcs.tsx +30 -30
  335. package/templates/tanstack-start/src/routes/index.tsx +5 -5
  336. package/templates/tanstack-start/vite.config.ts +9 -9
  337. package/templates/typescript/alchemy.run.ts +0 -2
  338. package/templates/typescript/src/worker.ts +5 -1
  339. package/templates/vite/alchemy.run.ts +0 -2
  340. package/templates/vite/eslint.config.js +12 -12
  341. package/templates/vite/package.json +1 -1
  342. package/templates/vite/src/App.tsx +7 -7
  343. package/templates/vite/src/main.tsx +6 -6
  344. package/templates/vite/src/worker.ts +11 -12
  345. package/templates/vite/vite.config.ts +2 -2
  346. package/workers/tunnel-proxy.js +1 -1
  347. package/lib/cloudflare/miniflare/symlink-miniflare-state.d.ts +0 -2
  348. package/lib/cloudflare/miniflare/symlink-miniflare-state.d.ts.map +0 -1
  349. package/lib/cloudflare/miniflare/symlink-miniflare-state.js +0 -18
  350. package/lib/cloudflare/miniflare/symlink-miniflare-state.js.map +0 -1
  351. package/src/cloudflare/miniflare/symlink-miniflare-state.ts +0 -18
package/bin/alchemy.ts CHANGED
@@ -32,7 +32,7 @@ export type AppRouter = typeof router;
32
32
  const cli = createCli({
33
33
  router,
34
34
  name: "alchemy",
35
- version: getPackageVersion(),
35
+ version: await getPackageVersion(),
36
36
  description:
37
37
  "🧪 Welcome to Alchemy! Creating infrastructure as code with JavaScript and TypeScript.",
38
38
  });
@@ -10,11 +10,12 @@ import {
10
10
  spinner,
11
11
  text,
12
12
  } from "@clack/prompts";
13
- import * as fs from "fs-extra";
14
- import { resolve } from "node:path";
13
+ import { rm } from "fs-extra";
14
+ import { resolve } from "pathe";
15
15
  import pc from "picocolors";
16
16
  import z from "zod";
17
17
  import { detectPackageManager } from "../../src/util/detect-package-manager.ts";
18
+ import { exists } from "../../src/util/exists.ts";
18
19
  import { throwWithContext } from "../errors.ts";
19
20
  import { initializeGitRepo, isGitInstalled } from "../services/git.ts";
20
21
  import { addGitHubWorkflowToAlchemy } from "../services/github-workflow.ts";
@@ -209,7 +210,7 @@ async function getInstallPreference(
209
210
  async function handleDirectoryOverwrite(
210
211
  context: ProjectContext,
211
212
  ): Promise<void> {
212
- if (!fs.existsSync(context.path)) {
213
+ if (!(await exists(context.path))) {
213
214
  return;
214
215
  }
215
216
 
@@ -249,7 +250,7 @@ async function removeExistingDirectory(context: ProjectContext): Promise<void> {
249
250
  s.start(`Removing existing directory: ${pc.yellow(context.path)}`);
250
251
 
251
252
  try {
252
- await fs.rm(context.path, { recursive: true, force: true });
253
+ await rm(context.path, { recursive: true, force: true });
253
254
  s.stop(`Directory ${pc.yellow(context.path)} removed.`);
254
255
  } catch (error) {
255
256
  s.stop(pc.red(`Failed to remove directory ${pc.yellow(context.path)}.`));
@@ -8,9 +8,15 @@ import {
8
8
  outro,
9
9
  select,
10
10
  } from "@clack/prompts";
11
- import * as fs from "fs-extra";
11
+ import {
12
+ ensureDir,
13
+ ensureFile,
14
+ readFile,
15
+ writeFile,
16
+ writeJson,
17
+ } from "fs-extra";
12
18
  import { parse as parseJsonc } from "jsonc-parse";
13
- import { dirname, relative, resolve } from "node:path";
19
+ import { dirname, relative, resolve } from "pathe";
14
20
  import pc from "picocolors";
15
21
  import {
16
22
  IndentationText,
@@ -21,6 +27,7 @@ import {
21
27
  } from "ts-morph";
22
28
  import z from "zod";
23
29
  import { detectPackageManager } from "../../src/util/detect-package-manager.ts";
30
+ import { exists } from "../../src/util/exists.ts";
24
31
  import type { DependencyVersionMap } from "../constants.ts";
25
32
  import { throwWithContext } from "../errors.ts";
26
33
  import { addPackageDependencies } from "../services/dependencies.ts";
@@ -89,7 +96,7 @@ function sanitizeProjectName(name: string): string {
89
96
 
90
97
  async function readJsonc(filePath: string): Promise<any> {
91
98
  try {
92
- const content = await fs.readFile(filePath, "utf-8");
99
+ const content = await readFile(filePath, "utf-8");
93
100
  return parseJsonc(content);
94
101
  } catch (error) {
95
102
  throw new Error(`Failed to read or parse ${filePath}: ${error}`);
@@ -97,7 +104,7 @@ async function readJsonc(filePath: string): Promise<any> {
97
104
  }
98
105
 
99
106
  async function writeJsonWithSpaces(filePath: string, data: any): Promise<void> {
100
- await fs.writeJson(filePath, data, { spaces: 2 });
107
+ await writeJson(filePath, data, { spaces: 2 });
101
108
  }
102
109
 
103
110
  async function safelyUpdateJson(
@@ -107,7 +114,7 @@ async function safelyUpdateJson(
107
114
  ): Promise<void> {
108
115
  try {
109
116
  let data = fallbackData;
110
- if (await fs.pathExists(filePath)) {
117
+ if (await exists(filePath)) {
111
118
  data = await readJsonc(filePath);
112
119
  }
113
120
  updater(data);
@@ -123,7 +130,7 @@ async function createInitContext(options: {
123
130
  }): Promise<InitContext> {
124
131
  const cwd = resolve(process.cwd());
125
132
  const packageJsonPath = resolve(cwd, "package.json");
126
- const hasPackageJson = await fs.pathExists(packageJsonPath);
133
+ const hasPackageJson = await exists(packageJsonPath);
127
134
 
128
135
  let projectName = "my-alchemy-app";
129
136
  if (hasPackageJson) {
@@ -135,7 +142,7 @@ async function createInitContext(options: {
135
142
  } catch (_error) {}
136
143
  }
137
144
 
138
- const useTypeScript = await fs.pathExists(resolve(cwd, "tsconfig.json"));
145
+ const useTypeScript = await exists(resolve(cwd, "tsconfig.json"));
139
146
  const framework =
140
147
  options.framework ||
141
148
  (await detectFramework(cwd, hasPackageJson, options.yes));
@@ -160,6 +167,7 @@ const FRAMEWORK_DETECTION_MAP: Record<string, TemplateType> = {
160
167
  "@sveltejs/kit": "sveltekit",
161
168
  "@tanstack/react-start": "tanstack-start",
162
169
  vite: "vite",
170
+ "@types/bun": "bun-spa",
163
171
  };
164
172
 
165
173
  async function detectFramework(
@@ -182,6 +190,7 @@ async function detectFramework(
182
190
  options: [
183
191
  { label: "TypeScript Worker", value: "typescript" },
184
192
  { label: "Vite", value: "vite" },
193
+ { label: "Bun SPA", value: "bun-spa" },
185
194
  { label: "Astro", value: "astro" },
186
195
  { label: "React Router", value: "react-router" },
187
196
  { label: "SvelteKit", value: "sveltekit" },
@@ -226,9 +235,13 @@ async function detectFrameworkFromPackageJson(
226
235
 
227
236
  async function checkExistingAlchemyFiles(context: InitContext): Promise<void> {
228
237
  const alchemyFiles = ["alchemy.run.ts", "alchemy.run.js"];
229
- const existingFile = alchemyFiles.find((file) =>
230
- fs.pathExistsSync(resolve(context.cwd, file)),
231
- );
238
+ let existingFile: string | undefined;
239
+ for (const file of alchemyFiles) {
240
+ if (await exists(resolve(context.cwd, file))) {
241
+ existingFile = file;
242
+ break;
243
+ }
244
+ }
232
245
 
233
246
  if (existingFile) {
234
247
  const overwriteResult = await confirm({
@@ -247,9 +260,7 @@ const ALCHEMY_RUN_TEMPLATES: Record<
247
260
  Exclude<TemplateType, "hono">,
248
261
  (context: InitContext) => string
249
262
  > = {
250
- typescript: (context) => `/// <reference types="@types/node" />
251
-
252
- import alchemy from "alchemy";
263
+ typescript: (context) => `import alchemy from "alchemy";
253
264
  import { Worker } from "alchemy/cloudflare";
254
265
 
255
266
  const app = await alchemy("${context.projectName}");
@@ -283,9 +294,25 @@ console.log({
283
294
  await app.finalize();
284
295
  `,
285
296
 
286
- astro: (context) => `/// <reference types="@types/node" />
297
+ "bun-spa": (context) => `import alchemy from "alchemy";
298
+ import { BunSPA } from "alchemy/cloudflare";
299
+
300
+ const app = await alchemy("${context.projectName}");
301
+
302
+ export const bunsite = await BunSPA("website", {
303
+ frontend: "src/index.html", // adjust to match your HTML entrypoint(s)
304
+ entrypoint: "src/server.ts", // your backend API entrypoint
305
+ });
306
+
307
+ console.log({
308
+ url: bunsite.url,
309
+ apiUrl: bunsite.apiUrl,
310
+ });
311
+
312
+ await app.finalize();
313
+ `,
287
314
 
288
- import alchemy from "alchemy";
315
+ astro: (context) => `import alchemy from "alchemy";
289
316
  import { Astro } from "alchemy/cloudflare";
290
317
 
291
318
  const app = await alchemy("${context.projectName}");
@@ -305,9 +332,7 @@ console.log({
305
332
  await app.finalize();
306
333
  `,
307
334
 
308
- "react-router": (context) => `/// <reference types="@types/node" />
309
-
310
- import alchemy from "alchemy";
335
+ "react-router": (context) => `import alchemy from "alchemy";
311
336
  import { ReactRouter } from "alchemy/cloudflare";
312
337
 
313
338
  const app = await alchemy("${context.projectName}");
@@ -328,9 +353,7 @@ console.log({
328
353
  await app.finalize();
329
354
  `,
330
355
 
331
- sveltekit: (context) => `/// <reference types="@types/node" />
332
-
333
- import alchemy from "alchemy";
356
+ sveltekit: (context) => `import alchemy from "alchemy";
334
357
  import { SvelteKit } from "alchemy/cloudflare";
335
358
 
336
359
  const app = await alchemy("${context.projectName}");
@@ -350,9 +373,7 @@ console.log({
350
373
  await app.finalize();
351
374
  `,
352
375
 
353
- "tanstack-start": (context) => `/// <reference types="@types/node" />
354
-
355
- import alchemy from "alchemy";
376
+ "tanstack-start": (context) => `import alchemy from "alchemy";
356
377
  import { TanStackStart } from "alchemy/cloudflare";
357
378
 
358
379
  const app = await alchemy("${context.projectName}");
@@ -372,9 +393,7 @@ console.log({
372
393
  await app.finalize();
373
394
  `,
374
395
 
375
- rwsdk: (context) => `/// <reference types="@types/node" />
376
-
377
- import alchemy from "alchemy";
396
+ rwsdk: (context) => `import alchemy from "alchemy";
378
397
  import { D1Database, DurableObjectNamespace, Redwood } from "alchemy/cloudflare";
379
398
 
380
399
  const app = await alchemy("${context.projectName}");
@@ -405,9 +424,7 @@ console.log({
405
424
  await app.finalize();
406
425
  `,
407
426
 
408
- nextjs: (context) => `/// <reference types="@types/node" />
409
-
410
- import alchemy from "alchemy";
427
+ nextjs: (context) => `import alchemy from "alchemy";
411
428
  import { Nextjs } from "alchemy/cloudflare";
412
429
 
413
430
  const app = await alchemy("${context.projectName}");
@@ -422,9 +439,7 @@ console.log({
422
439
  await app.finalize();
423
440
  `,
424
441
 
425
- nuxt: (context) => `/// <reference types="@types/node" />
426
-
427
- import alchemy from "alchemy";
442
+ nuxt: (context) => `import alchemy from "alchemy";
428
443
  import { Nuxt } from "alchemy/cloudflare";
429
444
 
430
445
  const app = await alchemy("${context.projectName}");
@@ -452,7 +467,7 @@ async function createAlchemyRunFile(context: InitContext): Promise<void> {
452
467
  ? "alchemy.run.ts"
453
468
  : "alchemy.run.js";
454
469
  const outputPath = resolve(context.cwd, outputFileName);
455
- await fs.writeFile(outputPath, content, "utf-8");
470
+ await writeFile(outputPath, content, "utf-8");
456
471
  } catch (error) {
457
472
  throwWithContext(error, "Failed to create alchemy.run file");
458
473
  }
@@ -465,6 +480,7 @@ const FRAMEWORK_DEPENDENCIES: Record<TemplateType, DependencyVersionMap[]> = {
465
480
  sveltekit: ["alchemy", "@sveltejs/adapter-cloudflare"],
466
481
  typescript: ["alchemy"],
467
482
  vite: ["alchemy"],
483
+ "bun-spa": ["alchemy"],
468
484
  astro: ["alchemy", "@astrojs/cloudflare"],
469
485
  "react-router": ["alchemy", "@cloudflare/vite-plugin"],
470
486
  "tanstack-start": ["alchemy"],
@@ -507,11 +523,11 @@ async function updateGitignore(context: InitContext) {
507
523
  try {
508
524
  const gitignorePath = resolve(context.cwd, ".gitignore");
509
525
 
510
- await fs.ensureFile(gitignorePath);
526
+ await ensureFile(gitignorePath);
511
527
 
512
528
  let gitignoreContent = "";
513
- if (await fs.pathExists(gitignorePath)) {
514
- gitignoreContent = await fs.readFile(gitignorePath, "utf-8");
529
+ if (await exists(gitignorePath)) {
530
+ gitignoreContent = await readFile(gitignorePath, "utf-8");
515
531
  }
516
532
 
517
533
  const lines = gitignoreContent.split("\n").map((line) => line.trim());
@@ -534,7 +550,7 @@ async function updateGitignore(context: InitContext) {
534
550
  }
535
551
  }
536
552
 
537
- await fs.writeFile(gitignorePath, lines.join("\n"), "utf-8");
553
+ await writeFile(gitignorePath, lines.join("\n"), "utf-8");
538
554
  } catch (error) {
539
555
  throwWithContext(error, "Failed to update .gitignore");
540
556
  }
@@ -589,6 +605,7 @@ async function updateProjectConfiguration(context: InitContext): Promise<{
589
605
  return {
590
606
  typescript: () => updateTypescriptProject(context),
591
607
  vite: () => updateViteProject(context),
608
+ "bun-spa": () => updateBunSpaProject(context),
592
609
  astro: () => updateAstroProject(context),
593
610
  "react-router": () => updateReactRouterProject(context),
594
611
  sveltekit: () => updateSvelteKitProject(context),
@@ -601,7 +618,7 @@ async function updateProjectConfiguration(context: InitContext): Promise<{
601
618
 
602
619
  async function updateTypescriptProject(context: InitContext): Promise<void> {
603
620
  const tsConfigPath = resolve(context.cwd, "tsconfig.json");
604
- if (await fs.pathExists(tsConfigPath)) {
621
+ if (await exists(tsConfigPath)) {
605
622
  await updateTsConfig(tsConfigPath, {
606
623
  include: ["alchemy.run.ts"],
607
624
  });
@@ -611,18 +628,43 @@ async function updateTypescriptProject(context: InitContext): Promise<void> {
611
628
  async function updateViteProject(_context: InitContext): Promise<void> {
612
629
  // const tsConfigPath = resolve(context.cwd, "tsconfig.json");
613
630
  // const tsConfigNodePath = resolve(context.cwd, "tsconfig.node.json");
614
- // if (await fs.pathExists(tsConfigPath)) {
631
+ // if (await exists(tsConfigPath)) {
615
632
  // await updateTsConfig(tsConfigPath, {
616
633
  // exclude: ["alchemy.run.ts", "./types/env.d.ts"],
617
634
  // });
618
635
  // }
619
- // if ((await fs.pathExists(tsConfigNodePath)) || context.framework === "vite") {
636
+ // if ((await exists(tsConfigNodePath)) || context.framework === "vite") {
620
637
  // await updateTsConfig(tsConfigNodePath, {
621
638
  // include: ["alchemy.run.ts"],
622
639
  // });
623
640
  // }
624
641
  }
625
642
 
643
+ async function updateBunSpaProject(context: InitContext): Promise<void> {
644
+ // Validate bunfig.toml exists or create it
645
+ const bunfigPath = resolve(context.cwd, "bunfig.toml");
646
+ if (!(await exists(bunfigPath))) {
647
+ // Create bunfig.toml with required config
648
+ await writeFile(bunfigPath, `[serve.static]\nenv='BUN_PUBLIC_*'\n`);
649
+ } else {
650
+ // Validate bunfig.toml has required config
651
+ const bunfigContent = await readFile(bunfigPath, "utf8");
652
+ const hasBunPublicEnv =
653
+ bunfigContent.includes("env") &&
654
+ (bunfigContent.includes("BUN_PUBLIC_*") ||
655
+ bunfigContent.includes("PUBLIC_*"));
656
+
657
+ if (!hasBunPublicEnv) {
658
+ throw new Error(
659
+ "bunfig.toml must contain the following configuration:\n\n" +
660
+ "[serve.static]\n" +
661
+ "env='BUN_PUBLIC_*'\n\n" +
662
+ "This is required for Alchemy to work with Bun SPA.",
663
+ );
664
+ }
665
+ }
666
+ }
667
+
626
668
  async function updateSvelteKitProject(context: InitContext): Promise<void> {
627
669
  await updateSvelteConfig(context);
628
670
 
@@ -667,10 +709,12 @@ async function updateNextjsProject(context: InitContext): Promise<void> {
667
709
  const candidates = ["ts", "js", "cjs", "mjs"].map((ext) =>
668
710
  resolve(context.cwd, `${name}.${ext}`),
669
711
  );
670
- for (const candidate of candidates) {
671
- if (await fs.pathExists(candidate)) {
672
- return { path: candidate, exists: true };
673
- }
712
+ const existenceChecks = await Promise.all(
713
+ candidates.map((candidate) => exists(candidate)),
714
+ );
715
+ const foundIdx = existenceChecks.findIndex((exists) => exists);
716
+ if (foundIdx !== -1) {
717
+ return { path: candidates[foundIdx], exists: true };
674
718
  }
675
719
  return { path: candidates[0], exists: false };
676
720
  };
@@ -679,7 +723,7 @@ async function updateNextjsProject(context: InitContext): Promise<void> {
679
723
  const openNextConfig = await resolveFile("open-next.config");
680
724
 
681
725
  if (nextConfig.exists) {
682
- const fileContent = await fs.readFile(nextConfig.path, "utf-8");
726
+ const fileContent = await readFile(nextConfig.path, "utf-8");
683
727
  let updated = fileContent;
684
728
  if (
685
729
  !fileContent.includes(
@@ -691,9 +735,9 @@ async function updateNextjsProject(context: InitContext): Promise<void> {
691
735
  if (!fileContent.includes("initOpenNextCloudflareForDev()")) {
692
736
  updated += "\ninitOpenNextCloudflareForDev();\n";
693
737
  }
694
- await fs.writeFile(nextConfig.path, updated);
738
+ await writeFile(nextConfig.path, updated);
695
739
  } else {
696
- await fs.writeFile(
740
+ await writeFile(
697
741
  nextConfig.path,
698
742
  `import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare";
699
743
  import type { NextConfig } from "next";
@@ -710,7 +754,7 @@ initOpenNextCloudflareForDev();
710
754
  }
711
755
 
712
756
  if (!openNextConfig.exists) {
713
- await fs.writeFile(
757
+ await writeFile(
714
758
  openNextConfig.path,
715
759
  `import { defineCloudflareConfig } from "@opennextjs/cloudflare";
716
760
 
@@ -724,7 +768,7 @@ export default defineCloudflareConfig({
724
768
  `,
725
769
  );
726
770
  }
727
- await fs.writeFile(
771
+ await writeFile(
728
772
  resolve(context.cwd, "./env.d.ts"),
729
773
  `// Auto-generated Cloudflare binding types.
730
774
  // @see https://alchemy.run/concepts/bindings/#type-safe-bindings
@@ -759,17 +803,17 @@ async function updateReactRouterProject(context: InitContext): Promise<{
759
803
  const wranglerJsonPath = resolve(context.cwd, "wrangler.json");
760
804
  const envTsPath = resolve(workersDir, "env.ts");
761
805
 
762
- await fs.ensureDir(workersDir);
806
+ await ensureDir(workersDir);
763
807
 
764
808
  let main: string | undefined;
765
- if (await fs.pathExists(wranglerJsonCPath)) {
809
+ if (await exists(wranglerJsonCPath)) {
766
810
  const wranglerJsonC = await readJsonc(wranglerJsonCPath);
767
811
  main = wranglerJsonC.main;
768
- } else if (await fs.pathExists(wranglerJsonPath)) {
812
+ } else if (await exists(wranglerJsonPath)) {
769
813
  const wranglerJson = await readJsonc(wranglerJsonPath);
770
814
  main = wranglerJson.main;
771
815
  } else {
772
- await fs.writeFile(
816
+ await writeFile(
773
817
  resolve(workersDir, "app.ts"),
774
818
  `
775
819
  import { createRequestHandler } from "react-router";
@@ -799,7 +843,7 @@ export default {
799
843
  );
800
844
  }
801
845
 
802
- await fs.writeFile(
846
+ await writeFile(
803
847
  envTsPath,
804
848
  `
805
849
  import type { website } from "../alchemy.run.ts";
@@ -837,7 +881,7 @@ declare module "cloudflare:workers" {
837
881
 
838
882
  async function updateViteConfig(context: InitContext): Promise<void> {
839
883
  const viteConfigPath = resolve(context.cwd, "vite.config.ts");
840
- if (!(await fs.pathExists(viteConfigPath))) return;
884
+ if (!(await exists(viteConfigPath))) return;
841
885
 
842
886
  try {
843
887
  const project = new Project({
@@ -922,7 +966,7 @@ async function updateViteConfig(context: InitContext): Promise<void> {
922
966
 
923
967
  async function updateReactRouterConfigTS(context: InitContext): Promise<void> {
924
968
  const configPath = resolve(context.cwd, "react-router.config.ts");
925
- if (!(await fs.pathExists(configPath))) return;
969
+ if (!(await exists(configPath))) return;
926
970
 
927
971
  try {
928
972
  const project = new Project({
@@ -1005,7 +1049,7 @@ async function updateTanStackStartProject(context: InitContext): Promise<void> {
1005
1049
 
1006
1050
  async function updateSvelteConfig(context: InitContext): Promise<void> {
1007
1051
  const svelteConfigPath = resolve(context.cwd, "svelte.config.js");
1008
- if (!(await fs.pathExists(svelteConfigPath))) return;
1052
+ if (!(await exists(svelteConfigPath))) return;
1009
1053
 
1010
1054
  try {
1011
1055
  const project = new Project({
@@ -1079,7 +1123,7 @@ function updateAdapterInConfig(configObject: Node): void {
1079
1123
 
1080
1124
  async function updateEnvFile(context: InitContext): Promise<void> {
1081
1125
  const envPath = resolve(context.cwd, ".env");
1082
- await fs.ensureFile(envPath);
1126
+ await ensureFile(envPath);
1083
1127
 
1084
1128
  const envVars = ["ALCHEMY_PASSWORD=change-me"];
1085
1129
  if (context.framework === "rwsdk") {
@@ -1087,9 +1131,9 @@ async function updateEnvFile(context: InitContext): Promise<void> {
1087
1131
  }
1088
1132
 
1089
1133
  let envContent = "";
1090
- if (await fs.pathExists(envPath)) {
1134
+ if (await exists(envPath)) {
1091
1135
  try {
1092
- envContent = await fs.readFile(envPath, "utf-8");
1136
+ envContent = await readFile(envPath, "utf-8");
1093
1137
  } catch (error) {
1094
1138
  console.warn("Failed to read .env:", error);
1095
1139
  }
@@ -1109,7 +1153,7 @@ async function updateEnvFile(context: InitContext): Promise<void> {
1109
1153
 
1110
1154
  if (needsUpdate) {
1111
1155
  try {
1112
- await fs.writeFile(envPath, envContent, "utf-8");
1156
+ await writeFile(envPath, envContent, "utf-8");
1113
1157
  } catch (error) {
1114
1158
  console.warn("Failed to update .env:", error);
1115
1159
  }
@@ -1118,7 +1162,7 @@ async function updateEnvFile(context: InitContext): Promise<void> {
1118
1162
 
1119
1163
  async function updateNuxtConfig(context: InitContext): Promise<void> {
1120
1164
  const nuxtConfigPath = resolve(context.cwd, "nuxt.config.ts");
1121
- if (!(await fs.pathExists(nuxtConfigPath))) return;
1165
+ if (!(await exists(nuxtConfigPath))) return;
1122
1166
 
1123
1167
  try {
1124
1168
  const project = new Project({
@@ -1193,7 +1237,7 @@ async function updateNuxtConfig(context: InitContext): Promise<void> {
1193
1237
 
1194
1238
  async function updateAstroConfig(context: InitContext): Promise<void> {
1195
1239
  const astroConfigPath = resolve(context.cwd, "astro.config.mjs");
1196
- if (!(await fs.pathExists(astroConfigPath))) return;
1240
+ if (!(await exists(astroConfigPath))) return;
1197
1241
 
1198
1242
  try {
1199
1243
  const project = new Project({
@@ -1251,7 +1295,7 @@ async function updateAstroConfig(context: InitContext): Promise<void> {
1251
1295
 
1252
1296
  async function updateTanStackViteConfig(context: InitContext): Promise<void> {
1253
1297
  const viteConfigPath = resolve(context.cwd, "vite.config.ts");
1254
- if (!(await fs.pathExists(viteConfigPath))) return;
1298
+ if (!(await exists(viteConfigPath))) return;
1255
1299
 
1256
1300
  try {
1257
1301
  const project = new Project({
@@ -162,7 +162,9 @@ async function createCloudflareGodToken() {
162
162
 
163
163
  while (true) {
164
164
  const accountId = await text({
165
- message: `Enter account ID ${accountIds.length > 0 ? "(or press enter to finish)" : ""}`,
165
+ message: `Enter account ID ${
166
+ accountIds.length > 0 ? "(or press enter to finish)" : ""
167
+ }`,
166
168
  placeholder: accountIds.length === 0 ? "account-id" : "",
167
169
  defaultValue: "",
168
170
  validate: (value) => {
package/bin/constants.ts CHANGED
@@ -1,4 +1,4 @@
1
- import path from "node:path";
1
+ import path from "pathe";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { getPackageVersion } from "./services/get-package-version.ts";
4
4
 
@@ -10,7 +10,7 @@ export const dependencyVersionMap = {
10
10
  alchemy:
11
11
  process.env.NODE_ENV === "test"
12
12
  ? `file:${path.resolve(PKG_ROOT)}`
13
- : getPackageVersion(),
13
+ : await getPackageVersion(),
14
14
 
15
15
  miniflare: "^4.20250617.3",
16
16
 
@@ -1,6 +1,6 @@
1
- import fs from "fs-extra";
2
- import path from "node:path";
1
+ import path from "pathe";
3
2
 
3
+ import { readJson, writeJson } from "fs-extra";
4
4
  import {
5
5
  type DependencyVersionMap,
6
6
  dependencyVersionMap,
@@ -15,7 +15,7 @@ export const addPackageDependencies = async (opts: {
15
15
 
16
16
  const pkgJsonPath = path.join(projectDir, "package.json");
17
17
 
18
- const pkgJson = await fs.readJson(pkgJsonPath);
18
+ const pkgJson = await readJson(pkgJsonPath);
19
19
 
20
20
  if (!pkgJson.dependencies) pkgJson.dependencies = {};
21
21
  if (!pkgJson.devDependencies) pkgJson.devDependencies = {};
@@ -34,7 +34,7 @@ export const addPackageDependencies = async (opts: {
34
34
  }
35
35
  }
36
36
 
37
- await fs.writeJson(pkgJsonPath, pkgJson, {
37
+ await writeJson(pkgJsonPath, pkgJson, {
38
38
  spaces: 2,
39
39
  });
40
40
  };
@@ -1,18 +1,18 @@
1
1
  import { log } from "@clack/prompts";
2
2
  import { spawn } from "node:child_process";
3
3
  import { once } from "node:events";
4
- import { resolve } from "node:path";
4
+ import { resolve } from "pathe";
5
5
  import pc from "picocolors";
6
6
  import z from "zod";
7
7
  import { detectRuntime } from "../../src/util/detect-node-runtime.ts";
8
8
  import { detectPackageManager } from "../../src/util/detect-package-manager.ts";
9
9
  import { exists } from "../../src/util/exists.ts";
10
+ import { findWorkspaceRoot } from "../../src/util/find-workspace-root.ts";
10
11
  import { promiseWithResolvers } from "../../src/util/promise-with-resolvers.ts";
11
12
  import { collectData } from "../../src/util/telemetry.ts";
12
13
  import { ExitSignal } from "../trpc.ts";
13
14
  import { CDPProxy } from "./cdp-manager/cdp-proxy.ts";
14
15
  import { CDPManager } from "./cdp-manager/server.ts";
15
- import { findWorkspaceRoot } from "./find-workspace-root.ts";
16
16
 
17
17
  export const entrypoint = z
18
18
  .string()
@@ -126,7 +126,9 @@ export async function execAlchemy(
126
126
 
127
127
  args.push(`--telemetry-session-id ${telemetryData.sessionId}`);
128
128
  args.push(
129
- `--telemetry-ref ${telemetryData.referrer ? `${telemetryData.referrer}+cli` : "cli"}`,
129
+ `--telemetry-ref ${
130
+ telemetryData.referrer ? `${telemetryData.referrer}+cli` : "cli"
131
+ }`,
130
132
  );
131
133
 
132
134
  if (quiet) args.push("--quiet");
@@ -1,11 +1,11 @@
1
- import fs from "fs-extra";
2
- import path from "node:path";
1
+ import { readJSON } from "fs-extra";
2
+ import path from "pathe";
3
3
  import { PKG_ROOT } from "../constants.ts";
4
4
 
5
- export const getPackageVersion = () => {
5
+ export const getPackageVersion = async () => {
6
6
  const packageJsonPath = path.join(PKG_ROOT, "package.json");
7
7
 
8
- const packageJsonContent = fs.readJSONSync(packageJsonPath);
8
+ const packageJsonContent = await readJSON(packageJsonPath);
9
9
 
10
10
  return packageJsonContent.version ?? "1.0.0";
11
11
  };