alchemy 0.62.3 → 0.63.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 (594) hide show
  1. package/bin/alchemy.js +1516 -1202
  2. package/bin/commands/deploy.ts +2 -0
  3. package/bin/commands/dev.ts +2 -0
  4. package/bin/services/execute-alchemy.ts +11 -0
  5. package/bin/services/template-manager.ts +2 -0
  6. package/bin/types.ts +2 -1
  7. package/lib/alchemy.d.ts +6 -22
  8. package/lib/alchemy.d.ts.map +1 -1
  9. package/lib/alchemy.js +65 -169
  10. package/lib/alchemy.js.map +1 -1
  11. package/lib/apply.d.ts +0 -2
  12. package/lib/apply.d.ts.map +1 -1
  13. package/lib/apply.js +2 -16
  14. package/lib/apply.js.map +1 -1
  15. package/lib/aws/account-id.d.ts.map +1 -1
  16. package/lib/aws/account-id.js +3 -2
  17. package/lib/aws/account-id.js.map +1 -1
  18. package/lib/aws/bucket.d.ts +8 -2
  19. package/lib/aws/bucket.d.ts.map +1 -1
  20. package/lib/aws/bucket.js +21 -14
  21. package/lib/aws/bucket.js.map +1 -1
  22. package/lib/aws/ec2/security-group.d.ts +8 -2
  23. package/lib/aws/ec2/security-group.d.ts.map +1 -1
  24. package/lib/aws/ec2/security-group.js +7 -2
  25. package/lib/aws/ec2/security-group.js.map +1 -1
  26. package/lib/aws/function.d.ts +9 -3
  27. package/lib/aws/function.d.ts.map +1 -1
  28. package/lib/aws/function.js +35 -26
  29. package/lib/aws/function.js.map +1 -1
  30. package/lib/aws/policy-attachment.d.ts.map +1 -1
  31. package/lib/aws/policy-attachment.js +2 -1
  32. package/lib/aws/policy-attachment.js.map +1 -1
  33. package/lib/aws/policy.d.ts +8 -2
  34. package/lib/aws/policy.d.ts.map +1 -1
  35. package/lib/aws/policy.js +13 -4
  36. package/lib/aws/policy.js.map +1 -1
  37. package/lib/aws/queue.d.ts +8 -2
  38. package/lib/aws/queue.d.ts.map +1 -1
  39. package/lib/aws/queue.js +22 -14
  40. package/lib/aws/queue.js.map +1 -1
  41. package/lib/aws/role.d.ts +8 -2
  42. package/lib/aws/role.d.ts.map +1 -1
  43. package/lib/aws/role.js +10 -3
  44. package/lib/aws/role.js.map +1 -1
  45. package/lib/aws/ses.d.ts +1 -1
  46. package/lib/aws/ses.d.ts.map +1 -1
  47. package/lib/aws/ses.js +2 -1
  48. package/lib/aws/ses.js.map +1 -1
  49. package/lib/aws/ssm-parameter.d.ts +8 -2
  50. package/lib/aws/ssm-parameter.d.ts.map +1 -1
  51. package/lib/aws/ssm-parameter.js +15 -10
  52. package/lib/aws/ssm-parameter.js.map +1 -1
  53. package/lib/aws/table.d.ts +8 -2
  54. package/lib/aws/table.d.ts.map +1 -1
  55. package/lib/aws/table.js +17 -9
  56. package/lib/aws/table.js.map +1 -1
  57. package/lib/cloudflare/account-api-token.d.ts +2 -2
  58. package/lib/cloudflare/account-api-token.d.ts.map +1 -1
  59. package/lib/cloudflare/account-api-token.js +7 -6
  60. package/lib/cloudflare/account-api-token.js.map +1 -1
  61. package/lib/cloudflare/ai-gateway.d.ts +9 -4
  62. package/lib/cloudflare/ai-gateway.d.ts.map +1 -1
  63. package/lib/cloudflare/ai-gateway.js +20 -24
  64. package/lib/cloudflare/ai-gateway.js.map +1 -1
  65. package/lib/cloudflare/api-schema.d.ts +2 -2
  66. package/lib/cloudflare/api-schema.d.ts.map +1 -1
  67. package/lib/cloudflare/api-schema.js +6 -2
  68. package/lib/cloudflare/api-schema.js.map +1 -1
  69. package/lib/cloudflare/api-shield.d.ts +5 -1
  70. package/lib/cloudflare/api-shield.d.ts.map +1 -1
  71. package/lib/cloudflare/api-shield.js +6 -1
  72. package/lib/cloudflare/api-shield.js.map +1 -1
  73. package/lib/cloudflare/assets.d.ts +1 -1
  74. package/lib/cloudflare/assets.d.ts.map +1 -1
  75. package/lib/cloudflare/astro/astro.d.ts.map +1 -1
  76. package/lib/cloudflare/astro/astro.js +3 -1
  77. package/lib/cloudflare/astro/astro.js.map +1 -1
  78. package/lib/cloudflare/astro/plugin.d.ts +2 -1
  79. package/lib/cloudflare/astro/plugin.d.ts.map +1 -1
  80. package/lib/cloudflare/astro/plugin.js.map +1 -1
  81. package/lib/cloudflare/bindings.d.ts +2 -2
  82. package/lib/cloudflare/bindings.d.ts.map +1 -1
  83. package/lib/cloudflare/bound.d.ts +1 -1
  84. package/lib/cloudflare/bound.d.ts.map +1 -1
  85. package/lib/cloudflare/bucket.d.ts +120 -1
  86. package/lib/cloudflare/bucket.d.ts.map +1 -1
  87. package/lib/cloudflare/bucket.js +80 -2
  88. package/lib/cloudflare/bucket.js.map +1 -1
  89. package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
  90. package/lib/cloudflare/compatibility-date.gen.js +1 -1
  91. package/lib/cloudflare/container.d.ts +10 -4
  92. package/lib/cloudflare/container.d.ts.map +1 -1
  93. package/lib/cloudflare/container.js +12 -9
  94. package/lib/cloudflare/container.js.map +1 -1
  95. package/lib/cloudflare/custom-domain.js +2 -1
  96. package/lib/cloudflare/custom-domain.js.map +1 -1
  97. package/lib/cloudflare/d1-database.d.ts +1 -1
  98. package/lib/cloudflare/d1-database.d.ts.map +1 -1
  99. package/lib/cloudflare/d1-database.js +6 -2
  100. package/lib/cloudflare/d1-database.js.map +1 -1
  101. package/lib/cloudflare/dispatch-namespace.d.ts +2 -0
  102. package/lib/cloudflare/dispatch-namespace.d.ts.map +1 -1
  103. package/lib/cloudflare/dispatch-namespace.js +7 -5
  104. package/lib/cloudflare/dispatch-namespace.js.map +1 -1
  105. package/lib/cloudflare/hyperdrive.d.ts +7 -1
  106. package/lib/cloudflare/hyperdrive.d.ts.map +1 -1
  107. package/lib/cloudflare/hyperdrive.js +2 -1
  108. package/lib/cloudflare/hyperdrive.js.map +1 -1
  109. package/lib/cloudflare/kv-namespace.d.ts +3 -0
  110. package/lib/cloudflare/kv-namespace.d.ts.map +1 -1
  111. package/lib/cloudflare/kv-namespace.js +11 -2
  112. package/lib/cloudflare/kv-namespace.js.map +1 -1
  113. package/lib/cloudflare/miniflare/miniflare-worker-proxy.js +3 -1
  114. package/lib/cloudflare/miniflare/miniflare-worker-proxy.js.map +1 -1
  115. package/lib/cloudflare/miniflare/paths.d.ts +4 -0
  116. package/lib/cloudflare/miniflare/paths.d.ts.map +1 -1
  117. package/lib/cloudflare/miniflare/paths.js +11 -0
  118. package/lib/cloudflare/miniflare/paths.js.map +1 -1
  119. package/lib/cloudflare/pipeline.d.ts +14 -3
  120. package/lib/cloudflare/pipeline.d.ts.map +1 -1
  121. package/lib/cloudflare/pipeline.js +31 -2
  122. package/lib/cloudflare/pipeline.js.map +1 -1
  123. package/lib/cloudflare/queue-consumer.js +1 -1
  124. package/lib/cloudflare/queue-consumer.js.map +1 -1
  125. package/lib/cloudflare/queue.d.ts +4 -2
  126. package/lib/cloudflare/queue.d.ts.map +1 -1
  127. package/lib/cloudflare/queue.js +13 -9
  128. package/lib/cloudflare/queue.js.map +1 -1
  129. package/lib/cloudflare/react-router/plugin.d.ts +1 -1
  130. package/lib/cloudflare/react-router/plugin.d.ts.map +1 -1
  131. package/lib/cloudflare/react-router/react-router.d.ts.map +1 -1
  132. package/lib/cloudflare/react-router/react-router.js +32 -2
  133. package/lib/cloudflare/react-router/react-router.js.map +1 -1
  134. package/lib/cloudflare/redwood/plugin.d.ts +2 -1
  135. package/lib/cloudflare/redwood/plugin.d.ts.map +1 -1
  136. package/lib/cloudflare/redwood/plugin.js.map +1 -1
  137. package/lib/cloudflare/route.js +1 -1
  138. package/lib/cloudflare/route.js.map +1 -1
  139. package/lib/cloudflare/ruleset.d.ts +3 -1
  140. package/lib/cloudflare/ruleset.d.ts.map +1 -1
  141. package/lib/cloudflare/ruleset.js +3 -2
  142. package/lib/cloudflare/ruleset.js.map +1 -1
  143. package/lib/cloudflare/secret.d.ts +6 -23
  144. package/lib/cloudflare/secret.d.ts.map +1 -1
  145. package/lib/cloudflare/secret.js +8 -4
  146. package/lib/cloudflare/secret.js.map +1 -1
  147. package/lib/cloudflare/secrets-store.d.ts +1 -1
  148. package/lib/cloudflare/secrets-store.d.ts.map +1 -1
  149. package/lib/cloudflare/secrets-store.js +5 -2
  150. package/lib/cloudflare/secrets-store.js.map +1 -1
  151. package/lib/cloudflare/tunnel.d.ts +5 -1
  152. package/lib/cloudflare/tunnel.d.ts.map +1 -1
  153. package/lib/cloudflare/tunnel.js +5 -1
  154. package/lib/cloudflare/tunnel.js.map +1 -1
  155. package/lib/cloudflare/vectorize-index.d.ts +7 -1
  156. package/lib/cloudflare/vectorize-index.d.ts.map +1 -1
  157. package/lib/cloudflare/vectorize-index.js +5 -2
  158. package/lib/cloudflare/vectorize-index.js.map +1 -1
  159. package/lib/cloudflare/vite/plugin.d.ts +2 -1
  160. package/lib/cloudflare/vite/plugin.d.ts.map +1 -1
  161. package/lib/cloudflare/vite/plugin.js.map +1 -1
  162. package/lib/cloudflare/website.js +1 -1
  163. package/lib/cloudflare/website.js.map +1 -1
  164. package/lib/cloudflare/worker.d.ts +1 -1
  165. package/lib/cloudflare/worker.d.ts.map +1 -1
  166. package/lib/cloudflare/worker.js +12 -7
  167. package/lib/cloudflare/worker.js.map +1 -1
  168. package/lib/cloudflare/wrangler.json.d.ts +1 -1
  169. package/lib/cloudflare/wrangler.json.d.ts.map +1 -1
  170. package/lib/cloudflare/wrangler.json.js +5 -3
  171. package/lib/cloudflare/wrangler.json.js.map +1 -1
  172. package/lib/docker/container.d.ts +6 -0
  173. package/lib/docker/container.d.ts.map +1 -1
  174. package/lib/docker/container.js +5 -1
  175. package/lib/docker/container.js.map +1 -1
  176. package/lib/docker/network.d.ts +8 -2
  177. package/lib/docker/network.d.ts.map +1 -1
  178. package/lib/docker/network.js +7 -2
  179. package/lib/docker/network.js.map +1 -1
  180. package/lib/docker/volume.d.ts +8 -2
  181. package/lib/docker/volume.d.ts.map +1 -1
  182. package/lib/docker/volume.js +6 -4
  183. package/lib/docker/volume.js.map +1 -1
  184. package/lib/esbuild/bundle.d.ts +1 -1
  185. package/lib/fs/index.d.ts +0 -8
  186. package/lib/fs/index.d.ts.map +1 -1
  187. package/lib/fs/index.js +0 -8
  188. package/lib/fs/index.js.map +1 -1
  189. package/lib/github/client.d.ts +1 -1
  190. package/lib/github/client.d.ts.map +1 -1
  191. package/lib/github/client.js +2 -1
  192. package/lib/github/client.js.map +1 -1
  193. package/lib/github/repository-environment.d.ts +8 -2
  194. package/lib/github/repository-environment.d.ts.map +1 -1
  195. package/lib/github/repository-environment.js +16 -12
  196. package/lib/github/repository-environment.js.map +1 -1
  197. package/lib/neon/project.d.ts +7 -1
  198. package/lib/neon/project.d.ts.map +1 -1
  199. package/lib/neon/project.js +10 -6
  200. package/lib/neon/project.js.map +1 -1
  201. package/lib/planetscale/branch.d.ts +4 -2
  202. package/lib/planetscale/branch.d.ts.map +1 -1
  203. package/lib/planetscale/branch.js +18 -12
  204. package/lib/planetscale/branch.js.map +1 -1
  205. package/lib/planetscale/database.d.ts +8 -2
  206. package/lib/planetscale/database.d.ts.map +1 -1
  207. package/lib/planetscale/database.js +24 -16
  208. package/lib/planetscale/database.js.map +1 -1
  209. package/lib/planetscale/password.d.ts +8 -2
  210. package/lib/planetscale/password.d.ts.map +1 -1
  211. package/lib/planetscale/password.js +2 -2
  212. package/lib/planetscale/password.js.map +1 -1
  213. package/lib/resource.d.ts +0 -2
  214. package/lib/resource.d.ts.map +1 -1
  215. package/lib/resource.js +1 -9
  216. package/lib/resource.js.map +1 -1
  217. package/lib/scope.d.ts +9 -3
  218. package/lib/scope.d.ts.map +1 -1
  219. package/lib/scope.js +21 -34
  220. package/lib/scope.js.map +1 -1
  221. package/lib/sentry/client-key.d.ts +7 -1
  222. package/lib/sentry/client-key.d.ts.map +1 -1
  223. package/lib/sentry/client-key.js +45 -6
  224. package/lib/sentry/client-key.js.map +1 -1
  225. package/lib/sentry/project.d.ts +8 -2
  226. package/lib/sentry/project.d.ts.map +1 -1
  227. package/lib/sentry/project.js +35 -5
  228. package/lib/sentry/project.js.map +1 -1
  229. package/lib/sentry/team.d.ts +8 -2
  230. package/lib/sentry/team.d.ts.map +1 -1
  231. package/lib/sentry/team.js +36 -6
  232. package/lib/sentry/team.js.map +1 -1
  233. package/lib/serde.d.ts +0 -5
  234. package/lib/serde.d.ts.map +1 -1
  235. package/lib/serde.js +0 -28
  236. package/lib/serde.js.map +1 -1
  237. package/lib/state/d1-state-store.d.ts +1 -1
  238. package/lib/state/d1-state-store.d.ts.map +1 -1
  239. package/lib/state/d1-state-store.js +5 -5
  240. package/lib/state/d1-state-store.js.map +1 -1
  241. package/lib/state/sqlite-state-store.d.ts.map +1 -1
  242. package/lib/state/sqlite-state-store.js +7 -11
  243. package/lib/state/sqlite-state-store.js.map +1 -1
  244. package/lib/stripe/card.d.ts.map +1 -1
  245. package/lib/stripe/card.js +3 -2
  246. package/lib/stripe/card.js.map +1 -1
  247. package/lib/stripe/client.d.ts +2 -2
  248. package/lib/stripe/client.d.ts.map +1 -1
  249. package/lib/stripe/client.js +4 -3
  250. package/lib/stripe/client.js.map +1 -1
  251. package/lib/stripe/coupon.d.ts.map +1 -1
  252. package/lib/stripe/coupon.js +4 -3
  253. package/lib/stripe/coupon.js.map +1 -1
  254. package/lib/stripe/customer.js +2 -2
  255. package/lib/stripe/customer.js.map +1 -1
  256. package/lib/stripe/entitlements-feature.d.ts.map +1 -1
  257. package/lib/stripe/entitlements-feature.js +3 -2
  258. package/lib/stripe/entitlements-feature.js.map +1 -1
  259. package/lib/stripe/file.d.ts.map +1 -1
  260. package/lib/stripe/file.js +3 -2
  261. package/lib/stripe/file.js.map +1 -1
  262. package/lib/stripe/meter.js +2 -2
  263. package/lib/stripe/meter.js.map +1 -1
  264. package/lib/stripe/portal-configuration.d.ts.map +1 -1
  265. package/lib/stripe/portal-configuration.js +3 -2
  266. package/lib/stripe/portal-configuration.js.map +1 -1
  267. package/lib/stripe/price.d.ts.map +1 -1
  268. package/lib/stripe/price.js +3 -2
  269. package/lib/stripe/price.js.map +1 -1
  270. package/lib/stripe/product-feature.d.ts.map +1 -1
  271. package/lib/stripe/product-feature.js +3 -2
  272. package/lib/stripe/product-feature.js.map +1 -1
  273. package/lib/stripe/product.d.ts.map +1 -1
  274. package/lib/stripe/product.js +3 -2
  275. package/lib/stripe/product.js.map +1 -1
  276. package/lib/stripe/promotion-code.d.ts.map +1 -1
  277. package/lib/stripe/promotion-code.js +3 -2
  278. package/lib/stripe/promotion-code.js.map +1 -1
  279. package/lib/stripe/shipping-rate.d.ts.map +1 -1
  280. package/lib/stripe/shipping-rate.js +4 -3
  281. package/lib/stripe/shipping-rate.js.map +1 -1
  282. package/lib/stripe/tax-rate.d.ts.map +1 -1
  283. package/lib/stripe/tax-rate.js +3 -2
  284. package/lib/stripe/tax-rate.js.map +1 -1
  285. package/lib/stripe/webhook.d.ts.map +1 -1
  286. package/lib/stripe/webhook.js +4 -3
  287. package/lib/stripe/webhook.js.map +1 -1
  288. package/lib/test/vitest.d.ts.map +1 -1
  289. package/lib/test/vitest.js +1 -0
  290. package/lib/test/vitest.js.map +1 -1
  291. package/lib/upstash/redis.d.ts +8 -2
  292. package/lib/upstash/redis.d.ts.map +1 -1
  293. package/lib/upstash/redis.js +5 -4
  294. package/lib/upstash/redis.js.map +1 -1
  295. package/lib/util/ignore-matcher.d.ts.map +1 -1
  296. package/lib/util/ignore-matcher.js +3 -1
  297. package/lib/util/ignore-matcher.js.map +1 -1
  298. package/lib/util/peer.d.ts +10 -0
  299. package/lib/util/peer.d.ts.map +1 -0
  300. package/lib/util/peer.js +42 -0
  301. package/lib/util/peer.js.map +1 -0
  302. package/lib/vercel/project.d.ts +7 -1
  303. package/lib/vercel/project.d.ts.map +1 -1
  304. package/lib/vercel/project.js +28 -0
  305. package/lib/vercel/project.js.map +1 -1
  306. package/package.json +88 -74
  307. package/src/alchemy.ts +76 -222
  308. package/src/apply.ts +6 -19
  309. package/src/aws/account-id.ts +6 -3
  310. package/src/aws/bucket.ts +43 -32
  311. package/src/aws/ec2/security-group.ts +15 -3
  312. package/src/aws/function.ts +65 -39
  313. package/src/aws/policy-attachment.ts +10 -6
  314. package/src/aws/policy.ts +33 -15
  315. package/src/aws/queue.ts +50 -29
  316. package/src/aws/role.ts +37 -20
  317. package/src/aws/ses.ts +24 -20
  318. package/src/aws/ssm-parameter.ts +40 -20
  319. package/src/aws/table.ts +35 -17
  320. package/src/cloudflare/account-api-token.ts +9 -7
  321. package/src/cloudflare/ai-gateway.ts +37 -34
  322. package/src/cloudflare/api-schema.ts +33 -26
  323. package/src/cloudflare/api-shield.ts +15 -2
  324. package/src/cloudflare/astro/astro.ts +5 -1
  325. package/src/cloudflare/astro/plugin.ts +2 -1
  326. package/src/cloudflare/bindings.ts +2 -2
  327. package/src/cloudflare/bound.ts +1 -1
  328. package/src/cloudflare/bucket.ts +242 -3
  329. package/src/cloudflare/compatibility-date.gen.ts +1 -1
  330. package/src/cloudflare/container.ts +23 -12
  331. package/src/cloudflare/custom-domain.ts +2 -2
  332. package/src/cloudflare/d1-database.ts +10 -3
  333. package/src/cloudflare/dispatch-namespace.ts +10 -7
  334. package/src/cloudflare/hyperdrive.ts +13 -3
  335. package/src/cloudflare/kv-namespace.ts +25 -2
  336. package/src/cloudflare/miniflare/miniflare-worker-proxy.ts +3 -1
  337. package/src/cloudflare/miniflare/paths.ts +13 -0
  338. package/src/cloudflare/pipeline.ts +76 -28
  339. package/src/cloudflare/queue-consumer.ts +1 -1
  340. package/src/cloudflare/queue.ts +26 -14
  341. package/src/cloudflare/react-router/react-router.ts +28 -2
  342. package/src/cloudflare/redwood/plugin.ts +3 -2
  343. package/src/cloudflare/route.ts +1 -1
  344. package/src/cloudflare/ruleset.ts +7 -2
  345. package/src/cloudflare/secret.ts +20 -31
  346. package/src/cloudflare/secrets-store.ts +7 -3
  347. package/src/cloudflare/tunnel.ts +13 -2
  348. package/src/cloudflare/vectorize-index.ts +14 -3
  349. package/src/cloudflare/vite/plugin.ts +3 -2
  350. package/src/cloudflare/website.ts +1 -1
  351. package/src/cloudflare/worker.ts +35 -23
  352. package/src/cloudflare/wrangler.json.ts +7 -4
  353. package/src/docker/container.ts +13 -1
  354. package/src/docker/network.ts +18 -3
  355. package/src/docker/volume.ts +17 -6
  356. package/src/fs/index.ts +0 -8
  357. package/src/github/client.ts +6 -2
  358. package/src/github/repository-environment.ts +27 -13
  359. package/src/neon/project.ts +20 -6
  360. package/src/planetscale/branch.ts +24 -13
  361. package/src/planetscale/database.ts +38 -17
  362. package/src/planetscale/password.ts +10 -3
  363. package/src/resource.ts +1 -10
  364. package/src/scope.ts +29 -38
  365. package/src/sentry/client-key.ts +74 -6
  366. package/src/sentry/project.ts +59 -6
  367. package/src/sentry/team.ts +55 -7
  368. package/src/serde.ts +0 -44
  369. package/src/state/d1-state-store.ts +13 -6
  370. package/src/state/sqlite-state-store.ts +16 -17
  371. package/src/stripe/card.ts +5 -2
  372. package/src/stripe/client.ts +10 -3
  373. package/src/stripe/coupon.ts +4 -3
  374. package/src/stripe/customer.ts +2 -2
  375. package/src/stripe/entitlements-feature.ts +5 -2
  376. package/src/stripe/file.ts +3 -2
  377. package/src/stripe/meter.ts +2 -2
  378. package/src/stripe/portal-configuration.ts +5 -2
  379. package/src/stripe/price.ts +3 -2
  380. package/src/stripe/product-feature.ts +5 -2
  381. package/src/stripe/product.ts +3 -2
  382. package/src/stripe/promotion-code.ts +3 -2
  383. package/src/stripe/shipping-rate.ts +4 -3
  384. package/src/stripe/tax-rate.ts +3 -2
  385. package/src/stripe/webhook.ts +4 -3
  386. package/src/test/vitest.ts +1 -0
  387. package/src/upstash/redis.ts +15 -5
  388. package/src/util/ignore-matcher.ts +3 -1
  389. package/src/util/peer.ts +53 -0
  390. package/src/vercel/project.ts +46 -1
  391. package/templates/hono/README.md +19 -0
  392. package/templates/hono/_env +1 -0
  393. package/templates/hono/_env.example +1 -0
  394. package/templates/hono/_gitignore +34 -0
  395. package/templates/hono/alchemy.run.ts +22 -0
  396. package/templates/hono/package.json +18 -0
  397. package/templates/hono/src/index.ts +17 -0
  398. package/templates/hono/tsconfig.json +13 -0
  399. package/templates/hono/types/env.d.ts +16 -0
  400. package/templates/react-router/vite.config.ts +5 -3
  401. package/workers/cloudflare-state-store.js +69 -74
  402. package/workers/dofs-state-store.js +1 -1
  403. package/bin/bootstrap-s3.ts +0 -255
  404. package/lib/ai/ark.d.ts +0 -12
  405. package/lib/ai/ark.d.ts.map +0 -1
  406. package/lib/ai/ark.js +0 -87
  407. package/lib/ai/ark.js.map +0 -1
  408. package/lib/ai/astro-file.d.ts +0 -138
  409. package/lib/ai/astro-file.d.ts.map +0 -1
  410. package/lib/ai/astro-file.js +0 -158
  411. package/lib/ai/astro-file.js.map +0 -1
  412. package/lib/ai/client.d.ts +0 -51
  413. package/lib/ai/client.d.ts.map +0 -1
  414. package/lib/ai/client.js +0 -58
  415. package/lib/ai/client.js.map +0 -1
  416. package/lib/ai/css-file.d.ts +0 -132
  417. package/lib/ai/css-file.d.ts.map +0 -1
  418. package/lib/ai/css-file.js +0 -142
  419. package/lib/ai/css-file.js.map +0 -1
  420. package/lib/ai/data.d.ts +0 -152
  421. package/lib/ai/data.d.ts.map +0 -1
  422. package/lib/ai/data.js +0 -120
  423. package/lib/ai/data.js.map +0 -1
  424. package/lib/ai/document.d.ts +0 -208
  425. package/lib/ai/document.d.ts.map +0 -1
  426. package/lib/ai/document.js +0 -206
  427. package/lib/ai/document.js.map +0 -1
  428. package/lib/ai/html-file.d.ts +0 -129
  429. package/lib/ai/html-file.d.ts.map +0 -1
  430. package/lib/ai/html-file.js +0 -139
  431. package/lib/ai/html-file.js.map +0 -1
  432. package/lib/ai/index.d.ts +0 -11
  433. package/lib/ai/index.d.ts.map +0 -1
  434. package/lib/ai/index.js +0 -11
  435. package/lib/ai/index.js.map +0 -1
  436. package/lib/ai/json-file.d.ts +0 -161
  437. package/lib/ai/json-file.d.ts.map +0 -1
  438. package/lib/ai/json-file.js +0 -188
  439. package/lib/ai/json-file.js.map +0 -1
  440. package/lib/ai/typescript-file.d.ts +0 -140
  441. package/lib/ai/typescript-file.d.ts.map +0 -1
  442. package/lib/ai/typescript-file.js +0 -146
  443. package/lib/ai/typescript-file.js.map +0 -1
  444. package/lib/ai/vue-file.d.ts +0 -127
  445. package/lib/ai/vue-file.d.ts.map +0 -1
  446. package/lib/ai/vue-file.js +0 -137
  447. package/lib/ai/vue-file.js.map +0 -1
  448. package/lib/ai/yaml-file.d.ts +0 -170
  449. package/lib/ai/yaml-file.d.ts.map +0 -1
  450. package/lib/ai/yaml-file.js +0 -201
  451. package/lib/ai/yaml-file.js.map +0 -1
  452. package/lib/fs/static-astro-file.d.ts +0 -35
  453. package/lib/fs/static-astro-file.d.ts.map +0 -1
  454. package/lib/fs/static-astro-file.js +0 -40
  455. package/lib/fs/static-astro-file.js.map +0 -1
  456. package/lib/fs/static-css-file.d.ts +0 -25
  457. package/lib/fs/static-css-file.d.ts.map +0 -1
  458. package/lib/fs/static-css-file.js +0 -30
  459. package/lib/fs/static-css-file.js.map +0 -1
  460. package/lib/fs/static-html-file.d.ts +0 -32
  461. package/lib/fs/static-html-file.d.ts.map +0 -1
  462. package/lib/fs/static-html-file.js +0 -37
  463. package/lib/fs/static-html-file.js.map +0 -1
  464. package/lib/fs/static-json-file.d.ts +0 -18
  465. package/lib/fs/static-json-file.d.ts.map +0 -1
  466. package/lib/fs/static-json-file.js +0 -19
  467. package/lib/fs/static-json-file.js.map +0 -1
  468. package/lib/fs/static-text-file.d.ts +0 -13
  469. package/lib/fs/static-text-file.d.ts.map +0 -1
  470. package/lib/fs/static-text-file.js +0 -9
  471. package/lib/fs/static-text-file.js.map +0 -1
  472. package/lib/fs/static-typescript-file.d.ts +0 -20
  473. package/lib/fs/static-typescript-file.d.ts.map +0 -1
  474. package/lib/fs/static-typescript-file.js +0 -16
  475. package/lib/fs/static-typescript-file.js.map +0 -1
  476. package/lib/fs/static-vue-file.d.ts +0 -29
  477. package/lib/fs/static-vue-file.d.ts.map +0 -1
  478. package/lib/fs/static-vue-file.js +0 -34
  479. package/lib/fs/static-vue-file.js.map +0 -1
  480. package/lib/fs/static-yaml-file.d.ts +0 -23
  481. package/lib/fs/static-yaml-file.d.ts.map +0 -1
  482. package/lib/fs/static-yaml-file.js +0 -10
  483. package/lib/fs/static-yaml-file.js.map +0 -1
  484. package/lib/internal/docs/providers.d.ts +0 -34
  485. package/lib/internal/docs/providers.d.ts.map +0 -1
  486. package/lib/internal/docs/providers.js +0 -200
  487. package/lib/internal/docs/providers.js.map +0 -1
  488. package/lib/runtime/bind.d.ts +0 -25
  489. package/lib/runtime/bind.d.ts.map +0 -1
  490. package/lib/runtime/bind.js +0 -76
  491. package/lib/runtime/bind.js.map +0 -1
  492. package/lib/runtime/global.d.ts +0 -8
  493. package/lib/runtime/global.d.ts.map +0 -1
  494. package/lib/runtime/global.js +0 -3
  495. package/lib/runtime/global.js.map +0 -1
  496. package/lib/runtime/plugin.d.ts +0 -35
  497. package/lib/runtime/plugin.d.ts.map +0 -1
  498. package/lib/runtime/plugin.js +0 -134
  499. package/lib/runtime/plugin.js.map +0 -1
  500. package/lib/runtime/shims.d.ts +0 -6
  501. package/lib/runtime/shims.d.ts.map +0 -1
  502. package/lib/runtime/shims.js +0 -27
  503. package/lib/runtime/shims.js.map +0 -1
  504. package/lib/runtime/state.d.ts +0 -5
  505. package/lib/runtime/state.d.ts.map +0 -1
  506. package/lib/runtime/state.js +0 -4
  507. package/lib/runtime/state.js.map +0 -1
  508. package/lib/web/astro.d.ts +0 -148
  509. package/lib/web/astro.d.ts.map +0 -1
  510. package/lib/web/astro.js +0 -419
  511. package/lib/web/astro.js.map +0 -1
  512. package/lib/web/shadcn-component.d.ts +0 -30
  513. package/lib/web/shadcn-component.d.ts.map +0 -1
  514. package/lib/web/shadcn-component.js +0 -25
  515. package/lib/web/shadcn-component.js.map +0 -1
  516. package/lib/web/shadcn.d.ts +0 -98
  517. package/lib/web/shadcn.d.ts.map +0 -1
  518. package/lib/web/shadcn.js +0 -102
  519. package/lib/web/shadcn.js.map +0 -1
  520. package/lib/web/tailwind.d.ts +0 -65
  521. package/lib/web/tailwind.d.ts.map +0 -1
  522. package/lib/web/tailwind.js +0 -98
  523. package/lib/web/tailwind.js.map +0 -1
  524. package/lib/web/vite.d.ts +0 -96
  525. package/lib/web/vite.d.ts.map +0 -1
  526. package/lib/web/vite.js +0 -232
  527. package/lib/web/vite.js.map +0 -1
  528. package/lib/web/vitepress/config.d.ts +0 -12
  529. package/lib/web/vitepress/config.d.ts.map +0 -1
  530. package/lib/web/vitepress/config.js +0 -33
  531. package/lib/web/vitepress/config.js.map +0 -1
  532. package/lib/web/vitepress/custom-theme.d.ts +0 -174
  533. package/lib/web/vitepress/custom-theme.d.ts.map +0 -1
  534. package/lib/web/vitepress/custom-theme.js +0 -337
  535. package/lib/web/vitepress/custom-theme.js.map +0 -1
  536. package/lib/web/vitepress/dependencies.d.ts +0 -13
  537. package/lib/web/vitepress/dependencies.d.ts.map +0 -1
  538. package/lib/web/vitepress/dependencies.js +0 -37
  539. package/lib/web/vitepress/dependencies.js.map +0 -1
  540. package/lib/web/vitepress/home-page.d.ts +0 -247
  541. package/lib/web/vitepress/home-page.d.ts.map +0 -1
  542. package/lib/web/vitepress/home-page.js +0 -146
  543. package/lib/web/vitepress/home-page.js.map +0 -1
  544. package/lib/web/vitepress/index.d.ts +0 -6
  545. package/lib/web/vitepress/index.d.ts.map +0 -1
  546. package/lib/web/vitepress/index.js +0 -6
  547. package/lib/web/vitepress/index.js.map +0 -1
  548. package/lib/web/vitepress/process-front-matter-files.d.ts +0 -19
  549. package/lib/web/vitepress/process-front-matter-files.d.ts.map +0 -1
  550. package/lib/web/vitepress/process-front-matter-files.js +0 -73
  551. package/lib/web/vitepress/process-front-matter-files.js.map +0 -1
  552. package/lib/web/vitepress/vitepress.d.ts +0 -75
  553. package/lib/web/vitepress/vitepress.d.ts.map +0 -1
  554. package/lib/web/vitepress/vitepress.js +0 -254
  555. package/lib/web/vitepress/vitepress.js.map +0 -1
  556. package/src/ai/ark.ts +0 -118
  557. package/src/ai/astro-file.ts +0 -270
  558. package/src/ai/client.ts +0 -117
  559. package/src/ai/css-file.ts +0 -247
  560. package/src/ai/data.ts +0 -221
  561. package/src/ai/document.ts +0 -367
  562. package/src/ai/html-file.ts +0 -244
  563. package/src/ai/index.ts +0 -10
  564. package/src/ai/json-file.ts +0 -325
  565. package/src/ai/typescript-file.ts +0 -259
  566. package/src/ai/vue-file.ts +0 -242
  567. package/src/ai/yaml-file.ts +0 -328
  568. package/src/fs/static-astro-file.ts +0 -45
  569. package/src/fs/static-css-file.ts +0 -35
  570. package/src/fs/static-html-file.ts +0 -42
  571. package/src/fs/static-json-file.ts +0 -38
  572. package/src/fs/static-text-file.ts +0 -23
  573. package/src/fs/static-typescript-file.ts +0 -37
  574. package/src/fs/static-vue-file.ts +0 -39
  575. package/src/fs/static-yaml-file.ts +0 -33
  576. package/src/internal/docs/providers.ts +0 -286
  577. package/src/runtime/bind.ts +0 -95
  578. package/src/runtime/global.ts +0 -10
  579. package/src/runtime/plugin.ts +0 -163
  580. package/src/runtime/shims.js +0 -34
  581. package/src/runtime/state.ts +0 -9
  582. package/src/web/astro.ts +0 -643
  583. package/src/web/shadcn-component.ts +0 -72
  584. package/src/web/shadcn.ts +0 -221
  585. package/src/web/tailwind.ts +0 -167
  586. package/src/web/vite.ts +0 -407
  587. package/src/web/vitepress/config.ts +0 -50
  588. package/src/web/vitepress/custom-theme.ts +0 -514
  589. package/src/web/vitepress/dependencies.ts +0 -69
  590. package/src/web/vitepress/home-page.ts +0 -378
  591. package/src/web/vitepress/index.ts +0 -5
  592. package/src/web/vitepress/process-front-matter-files.ts +0 -107
  593. package/src/web/vitepress/vitepress.ts +0 -372
  594. package/templates/sveltekit/bun.lock +0 -1099
@@ -14,8 +14,10 @@ import {
14
14
  export interface DatabaseProps {
15
15
  /**
16
16
  * The name of the database
17
+ *
18
+ * @default ${app}-${stage}-${id}
17
19
  */
18
- name: string;
20
+ name?: string;
19
21
 
20
22
  /**
21
23
  * The organization ID where the database will be created
@@ -104,6 +106,11 @@ export interface Database
104
106
  */
105
107
  id: string;
106
108
 
109
+ /**
110
+ * The name of the database
111
+ */
112
+ name: string;
113
+
107
114
  /**
108
115
  * The current state of the database
109
116
  */
@@ -173,9 +180,10 @@ export const Database = Resource(
173
180
  "planetscale::Database",
174
181
  async function (
175
182
  this: Context<Database>,
176
- _id: string,
183
+ id: string,
177
184
  props: DatabaseProps,
178
185
  ): Promise<Database> {
186
+ const adopt = props.adopt ?? this.scope.adopt;
179
187
  const apiKey =
180
188
  props.apiKey?.unencrypted || process.env.PLANETSCALE_API_TOKEN;
181
189
  if (!apiKey) {
@@ -184,6 +192,16 @@ export const Database = Resource(
184
192
 
185
193
  const api = new PlanetScaleApi({ apiKey });
186
194
 
195
+ const databaseName =
196
+ props.name ?? this.output?.name ?? this.scope.createPhysicalName(id);
197
+
198
+ if (this.phase === "update" && this.output.name !== databaseName) {
199
+ await api.patch(
200
+ `/organizations/${props.organizationId}/databases/${this.output.name}`,
201
+ { new_name: databaseName },
202
+ );
203
+ }
204
+
187
205
  if (this.phase === "delete") {
188
206
  try {
189
207
  if (this.output?.name) {
@@ -207,26 +225,26 @@ export const Database = Resource(
207
225
  try {
208
226
  // Check if database exists
209
227
  const getResponse = await api.get(
210
- `/organizations/${props.organizationId}/databases/${props.name}`,
228
+ `/organizations/${props.organizationId}/databases/${databaseName}`,
211
229
  );
212
230
  const getData = await getResponse.json<any>();
213
- if (this.phase === "update" || (props.adopt && getResponse.ok)) {
231
+ if (this.phase === "update" || (adopt && getResponse.ok)) {
214
232
  if (!getResponse.ok) {
215
- throw new Error(`Database ${props.name} not found`);
233
+ throw new Error(`Database ${databaseName} not found`);
216
234
  }
217
235
  // Update database settings
218
236
  // If updating to a non-'main' default branch, create it first
219
237
  if (props.defaultBranch && props.defaultBranch !== "main") {
220
238
  const branchResponse = await api.get(
221
- `/organizations/${props.organizationId}/databases/${props.name}/branches/${props.defaultBranch}`,
239
+ `/organizations/${props.organizationId}/databases/${databaseName}/branches/${props.defaultBranch}`,
222
240
  );
223
241
  if (!getData.ready) {
224
- await waitForDatabaseReady(api, props.organizationId, props.name);
242
+ await waitForDatabaseReady(api, props.organizationId, databaseName);
225
243
  }
226
244
  if (!branchResponse.ok && branchResponse.status === 404) {
227
245
  // Create the branch
228
246
  const createBranchResponse = await api.post(
229
- `/organizations/${props.organizationId}/databases/${props.name}/branches`,
247
+ `/organizations/${props.organizationId}/databases/${databaseName}/branches`,
230
248
  {
231
249
  name: props.defaultBranch,
232
250
  parent_branch: "main",
@@ -242,7 +260,7 @@ export const Database = Resource(
242
260
  }
243
261
 
244
262
  const updateResponse = await api.patch(
245
- `/organizations/${props.organizationId}/databases/${props.name}`,
263
+ `/organizations/${props.organizationId}/databases/${databaseName}`,
246
264
  {
247
265
  automatic_migrations: props.automaticMigrations,
248
266
  migration_framework: props.migrationFramework,
@@ -265,7 +283,7 @@ export const Database = Resource(
265
283
  await fixClusterSize(
266
284
  api,
267
285
  props.organizationId,
268
- props.name,
286
+ databaseName,
269
287
  props.defaultBranch || "main",
270
288
  props.clusterSize,
271
289
  getData.ready,
@@ -275,6 +293,7 @@ export const Database = Resource(
275
293
  return this({
276
294
  ...props,
277
295
  id: data.id,
296
+ name: databaseName,
278
297
  state: data.state,
279
298
  defaultBranch: data.default_branch,
280
299
  plan: data.plan,
@@ -285,14 +304,14 @@ export const Database = Resource(
285
304
  }
286
305
 
287
306
  if (getResponse.ok) {
288
- throw new Error(`Database with name ${props.name} already exists`);
307
+ throw new Error(`Database with name ${databaseName} already exists`);
289
308
  }
290
309
 
291
310
  // Create new database
292
311
  const createResponse = await api.post(
293
312
  `/organizations/${props.organizationId}/databases`,
294
313
  {
295
- name: props.name,
314
+ name: databaseName,
296
315
  region_slug: props.region?.slug,
297
316
  require_approval_for_deploy: props.requireApprovalForDeploy,
298
317
  allow_data_branching: props.allowDataBranching,
@@ -316,17 +335,17 @@ export const Database = Resource(
316
335
 
317
336
  // If a non-'main' default branch is specified, create it
318
337
  if (props.defaultBranch && props.defaultBranch !== "main") {
319
- await waitForDatabaseReady(api, props.organizationId, props.name);
338
+ await waitForDatabaseReady(api, props.organizationId, databaseName);
320
339
 
321
340
  // Check if branch exists
322
341
  const branchResponse = await api.get(
323
- `/organizations/${props.organizationId}/databases/${props.name}/branches/${props.defaultBranch}`,
342
+ `/organizations/${props.organizationId}/databases/${databaseName}/branches/${props.defaultBranch}`,
324
343
  );
325
344
 
326
345
  if (!branchResponse.ok && branchResponse.status === 404) {
327
346
  // Create the branch
328
347
  const createBranchResponse = await api.post(
329
- `/organizations/${props.organizationId}/databases/${props.name}/branches`,
348
+ `/organizations/${props.organizationId}/databases/${databaseName}/branches`,
330
349
  {
331
350
  name: props.defaultBranch,
332
351
  parent_branch: "main",
@@ -342,7 +361,7 @@ export const Database = Resource(
342
361
  await fixClusterSize(
343
362
  api,
344
363
  props.organizationId,
345
- props.name,
364
+ databaseName,
346
365
  props.defaultBranch || "main",
347
366
  props.clusterSize,
348
367
  false,
@@ -350,7 +369,7 @@ export const Database = Resource(
350
369
 
351
370
  // Update database to use new branch as default
352
371
  const updateResponse = await api.patch(
353
- `/organizations/${props.organizationId}/databases/${props.name}`,
372
+ `/organizations/${props.organizationId}/databases/${databaseName}`,
354
373
  {
355
374
  default_branch: props.defaultBranch,
356
375
  },
@@ -366,6 +385,7 @@ export const Database = Resource(
366
385
  return this({
367
386
  ...props,
368
387
  id: data.id,
388
+ name: databaseName,
369
389
  state: updatedData.state,
370
390
  defaultBranch: updatedData.default_branch,
371
391
  plan: updatedData.plan,
@@ -379,6 +399,7 @@ export const Database = Resource(
379
399
  return this({
380
400
  ...props,
381
401
  id: data.id,
402
+ name: databaseName,
382
403
  state: data.state,
383
404
  defaultBranch: data.default_branch || "main",
384
405
  plan: data.plan,
@@ -14,8 +14,10 @@ import type { Database } from "./database.ts";
14
14
  export interface PasswordProps {
15
15
  /**
16
16
  * The name of the password
17
+ *
18
+ * @default ${app}-${stage}-${id}
17
19
  */
18
- name: string;
20
+ name?: string;
19
21
 
20
22
  /**
21
23
  * The organization ID where the password will be created
@@ -73,6 +75,11 @@ export interface Password
73
75
  */
74
76
  id: string;
75
77
 
78
+ /**
79
+ * Name of the Password.
80
+ */
81
+ name: string;
82
+
76
83
  /**
77
84
  * The timestamp when the password expires (ISO 8601 format)
78
85
  */
@@ -255,7 +262,7 @@ export const Password = Resource(
255
262
  "planetscale::Password",
256
263
  async function (
257
264
  this: Context<Password>,
258
- _id: string,
265
+ id: string,
259
266
  props: PasswordProps,
260
267
  ): Promise<Password> {
261
268
  const apiKey =
@@ -266,7 +273,7 @@ export const Password = Resource(
266
273
  const nameSlug = this.isReplacement
267
274
  ? lowercaseId()
268
275
  : (this.output?.nameSlug ?? lowercaseId());
269
- const name = `${props.name.toLowerCase()}-${nameSlug}`;
276
+ const name = `${(props.name ?? this.output?.name ?? this.scope.createPhysicalName(id)).toLowerCase()}-${nameSlug}`;
270
277
 
271
278
  const api = new PlanetScaleApi({ apiKey });
272
279
  const branchName =
package/src/resource.ts CHANGED
@@ -59,7 +59,6 @@ export const ResourceFQN = Symbol.for("alchemy::ResourceFQN");
59
59
  export type ResourceKind = string;
60
60
  export const ResourceKind = Symbol.for("alchemy::ResourceKind");
61
61
  export const ResourceScope = Symbol.for("alchemy::ResourceScope");
62
- export const InnerResourceScope = Symbol.for("alchemy::InnerResourceScope");
63
62
  export const ResourceSeq = Symbol.for("alchemy::ResourceSeq");
64
63
 
65
64
  export interface ProviderOptions {
@@ -97,7 +96,6 @@ export interface PendingResource<Out = unknown> extends Promise<Out> {
97
96
  [ResourceScope]: Scope;
98
97
  [ResourceSeq]: number;
99
98
  [DestroyStrategy]: DestroyStrategy;
100
- [InnerResourceScope]: Promise<Scope>;
101
99
  }
102
100
 
103
101
  export interface Resource<Kind extends ResourceKind = ResourceKind> {
@@ -187,7 +185,6 @@ export function Resource<
187
185
 
188
186
  // get a sequence number (unique within the scope) for the resource
189
187
  const seq = scope.seq();
190
- let resolveInnerScope: ((scope: Scope) => void) | undefined;
191
188
  const meta = {
192
189
  [ResourceKind]: type,
193
190
  [ResourceID]: resourceID,
@@ -195,14 +192,8 @@ export function Resource<
195
192
  [ResourceSeq]: seq,
196
193
  [ResourceScope]: scope,
197
194
  [DestroyStrategy]: options?.destroyStrategy ?? "sequential",
198
- [InnerResourceScope]: new Promise<Scope>((resolve) => {
199
- resolveInnerScope = resolve;
200
- }),
201
195
  } as any as PendingResource<Out>;
202
- const promise = apply(meta, props, {
203
- ...options,
204
- resolveInnerScope,
205
- });
196
+ const promise = apply(meta, props, options);
206
197
  const resource = Object.assign(promise, meta);
207
198
  scope.resources.set(resourceID, resource);
208
199
  return resource;
package/src/scope.ts CHANGED
@@ -15,7 +15,6 @@ import {
15
15
  type ResourceProps,
16
16
  } from "./resource.ts";
17
17
  import type { State, StateStore, StateStoreType } from "./state.ts";
18
- import { D1StateStore } from "./state/d1-state-store.ts";
19
18
  import { FileSystemStateStore } from "./state/file-system-state-store.ts";
20
19
  import { InstrumentedStateStore } from "./state/instrumented-state-store.ts";
21
20
  import {
@@ -84,6 +83,12 @@ export interface ScopeOptions extends ProviderCredentials {
84
83
  * @default "./.alchemy"
85
84
  */
86
85
  dotAlchemy?: string;
86
+ /**
87
+ * Whether to adopt resources if they already exist but are not yet managed by your Alchemy app.
88
+ *
89
+ * @default false
90
+ */
91
+ adopt?: boolean;
87
92
  }
88
93
 
89
94
  /**
@@ -123,7 +128,6 @@ export const DEFAULT_STAGE =
123
128
 
124
129
  declare global {
125
130
  var __ALCHEMY_STORAGE__: AsyncLocalStorage<Scope>;
126
- var __ALCHEMY_GLOBALS__: Scope[];
127
131
  }
128
132
 
129
133
  const ScopeSymbol = Symbol.for("alchemy::Scope");
@@ -139,17 +143,9 @@ export class Scope {
139
143
 
140
144
  public static storage = (globalThis.__ALCHEMY_STORAGE__ ??=
141
145
  new AsyncLocalStorage<Scope>());
142
- public static globals: Scope[] = (globalThis.__ALCHEMY_GLOBALS__ ??= []);
143
146
 
144
147
  public static getScope(): Scope | undefined {
145
- const scope = Scope.storage.getStore();
146
- if (!scope) {
147
- if (Scope.globals.length > 0) {
148
- return Scope.globals[Scope.globals.length - 1];
149
- }
150
- return undefined;
151
- }
152
- return scope;
148
+ return Scope.storage.getStore();
153
149
  }
154
150
 
155
151
  public static get root(): Scope {
@@ -176,10 +172,12 @@ export class Scope {
176
172
  public readonly local: boolean;
177
173
  public readonly watch: boolean;
178
174
  public readonly force: boolean;
175
+ public readonly adopt: boolean;
179
176
  public readonly destroyStrategy: DestroyStrategy;
180
177
  public readonly logger: LoggerApi;
181
178
  public readonly telemetryClient: ITelemetryClient;
182
179
  public readonly dataMutex: AsyncMutex;
180
+ public readonly dotAlchemy: string;
183
181
 
184
182
  // Provider credentials for scope-level credential overrides
185
183
  public readonly providerCredentials: ProviderCredentials;
@@ -198,8 +196,6 @@ export class Scope {
198
196
  return this.scopeName;
199
197
  }
200
198
 
201
- public readonly dotAlchemy: string;
202
-
203
199
  constructor(options: ScopeOptions) {
204
200
  // Extract core scope options first
205
201
  const {
@@ -216,10 +212,16 @@ export class Scope {
216
212
  destroyStrategy,
217
213
  telemetryClient,
218
214
  logger,
215
+ adopt,
219
216
  dotAlchemy,
220
217
  ...providerCredentials
221
218
  } = options;
222
219
 
220
+ this.dotAlchemy =
221
+ dotAlchemy ??
222
+ this.parent?.dotAlchemy ??
223
+ path.join(process.cwd(), ".alchemy");
224
+
223
225
  this.scopeName = scopeName;
224
226
  this.name = this.scopeName;
225
227
  this.parent = parent ?? Scope.getScope();
@@ -234,10 +236,6 @@ export class Scope {
234
236
  `Scope name "${this.scopeName}" cannot contain double colons`,
235
237
  );
236
238
  }
237
- this.dotAlchemy =
238
- options.dotAlchemy ??
239
- this.parent?.dotAlchemy ??
240
- path.join(process.cwd(), ".alchemy");
241
239
 
242
240
  this.stage = stage ?? this.parent?.stage ?? DEFAULT_STAGE;
243
241
  this.parent?.children.set(this.scopeName!, this);
@@ -266,6 +264,7 @@ export class Scope {
266
264
  this.local = local ?? this.parent?.local ?? false;
267
265
  this.watch = watch ?? this.parent?.watch ?? false;
268
266
  this.force = force ?? this.parent?.force ?? false;
267
+ this.adopt = adopt ?? this.parent?.adopt ?? false;
269
268
  this.destroyStrategy =
270
269
  destroyStrategy ?? this.parent?.destroyStrategy ?? "sequential";
271
270
  if (this.local) {
@@ -275,7 +274,9 @@ export class Scope {
275
274
  }
276
275
 
277
276
  this.stateStore =
278
- stateStore ?? this.parent?.stateStore ?? defaultStateStore;
277
+ stateStore ??
278
+ this.parent?.stateStore ??
279
+ ((scope) => new FileSystemStateStore(scope));
279
280
  this.telemetryClient = telemetryClient ?? this.parent?.telemetryClient!;
280
281
  this.state = new InstrumentedStateStore(
281
282
  this.stateStore(this),
@@ -287,6 +288,14 @@ export class Scope {
287
288
  this.dataMutex = new AsyncMutex();
288
289
  }
289
290
 
291
+ public createPhysicalName(id: string, delimiter = "-"): string {
292
+ const app = this.appName;
293
+ const stage = this.stage;
294
+ return [app, ...this.chain.slice(2), id, stage]
295
+ .map((s) => s.replaceAll(/[^a-z0-9_-]/gi, delimiter))
296
+ .join(delimiter);
297
+ }
298
+
290
299
  public async spawn<
291
300
  E extends ((line: string) => string | undefined) | undefined,
292
301
  >(
@@ -294,9 +303,8 @@ export class Scope {
294
303
  id: string,
295
304
  options: Omit<IdempotentSpawnOptions, "log" | "stateFile">,
296
305
  ): Promise<E extends undefined ? undefined : string> {
297
- const dotAlchemy = path.join(process.cwd(), ".alchemy");
298
- const logsDir = path.join(dotAlchemy, "logs");
299
- const pidsDir = path.join(dotAlchemy, "pids");
306
+ const logsDir = path.join(this.dotAlchemy, "logs");
307
+ const pidsDir = path.join(this.dotAlchemy, "pids");
300
308
 
301
309
  const result = await idempotentSpawn({
302
310
  log: path.join(logsDir, `${id}.log`),
@@ -496,14 +504,6 @@ export class Scope {
496
504
  if (this.finalized && !shouldForce) {
497
505
  return;
498
506
  }
499
- if (this.parent === undefined && Scope.globals.length > 0) {
500
- const last = Scope.globals.pop();
501
- if (last !== this) {
502
- throw new Error(
503
- "Running in AsyncLocaStorage.enterWith emulation mode and attempted to finalize a global Scope that wasn't top of the stack",
504
- );
505
- }
506
- }
507
507
  this.finalized = true;
508
508
  // trigger and await all deferred promises
509
509
  await Promise.all(this.deferred.map((fn) => fn()));
@@ -667,15 +667,6 @@ export class Scope {
667
667
  }
668
668
  }
669
669
 
670
- const defaultStateStore: StateStoreType = (scope: Scope) => {
671
- switch (process.env.ALCHEMY_STATE_STORE) {
672
- case "d1":
673
- return new D1StateStore(scope);
674
- default:
675
- return new FileSystemStateStore(scope);
676
- }
677
- };
678
-
679
670
  declare global {
680
671
  // for runtime
681
672
  // TODO(sam): maybe inject is a better way to achieve this
@@ -10,6 +10,8 @@ import { SentryApi } from "./api.ts";
10
10
  export interface ClientKeyProps {
11
11
  /**
12
12
  * The name of the key
13
+ *
14
+ * @default ${app}-${stage}-${id}
13
15
  */
14
16
  name?: string;
15
17
 
@@ -68,6 +70,11 @@ export interface ClientKey
68
70
  */
69
71
  id: string;
70
72
 
73
+ /**
74
+ * Name of the Client Key.
75
+ */
76
+ name: string;
77
+
71
78
  /**
72
79
  * The label of the key
73
80
  */
@@ -180,11 +187,45 @@ export const ClientKey = Resource(
180
187
  "sentry::ClientKey",
181
188
  async function (
182
189
  this: Context<ClientKey>,
183
- _id: string,
190
+ id: string,
184
191
  props: ClientKeyProps,
185
192
  ): Promise<ClientKey> {
186
193
  const api = new SentryApi({ authToken: props.authToken });
187
194
 
195
+ // it's possible that `this.output.name` is undefined because a previous version
196
+ // of alchemy had a bug where it didn't set the name on the output
197
+ // so, we try to find the key by ID and use the name from the API response
198
+ const lookupName = async () => {
199
+ if (!this.output?.id) {
200
+ // not running in the update phase
201
+ return undefined;
202
+ } else if (this.output.name) {
203
+ return this.output.name;
204
+ }
205
+ const name = (
206
+ await getClientKeyName(api, {
207
+ organization: props.organization,
208
+ project: props.project,
209
+ keyId: this.output.id,
210
+ })
211
+ )?.name;
212
+
213
+ if (name) {
214
+ this.output.name = name;
215
+ }
216
+
217
+ return name;
218
+ };
219
+
220
+ const clientKeyName =
221
+ props.name ?? (await lookupName()) ?? this.scope.createPhysicalName(id);
222
+
223
+ if (this.phase === "update") {
224
+ if (this.output.name !== clientKeyName) {
225
+ this.replace();
226
+ }
227
+ }
228
+
188
229
  if (this.phase === "delete") {
189
230
  try {
190
231
  if (this.output?.id) {
@@ -217,24 +258,24 @@ export const ClientKey = Resource(
217
258
  } catch (error) {
218
259
  // Check if this is a "key already exists" error and adopt is enabled
219
260
  if (
220
- props.adopt &&
261
+ (props.adopt ?? this.scope.adopt) &&
221
262
  error instanceof Error &&
222
263
  error.message.includes("already exists") &&
223
- props.name
264
+ clientKeyName
224
265
  ) {
225
266
  logger.log(
226
- `Client key '${props.name}' already exists, adopting it`,
267
+ `Client key '${clientKeyName}' already exists, adopting it`,
227
268
  );
228
269
  // Find the existing key by name
229
270
  const existingKey = await findClientKeyByName(
230
271
  api,
231
272
  props.organization,
232
273
  props.project,
233
- props.name,
274
+ clientKeyName,
234
275
  );
235
276
  if (!existingKey) {
236
277
  throw new Error(
237
- `Failed to find existing client key '${props.name}' for adoption`,
278
+ `Failed to find existing client key '${clientKeyName}' for adoption`,
238
279
  );
239
280
  }
240
281
  response = await api.get(
@@ -257,6 +298,7 @@ export const ClientKey = Resource(
257
298
  return this({
258
299
  ...props,
259
300
  id: data.id,
301
+ name: clientKeyName,
260
302
  label: data.label,
261
303
  public: data.public,
262
304
  secret: data.secret,
@@ -294,3 +336,29 @@ async function findClientKeyByName(
294
336
  const key = keys.find((k) => k.name === name);
295
337
  return key ? { id: key.id } : null;
296
338
  }
339
+
340
+ /**
341
+ * Find a client key by ID
342
+ */
343
+ async function getClientKeyName(
344
+ api: SentryApi,
345
+ {
346
+ organization,
347
+ project,
348
+ keyId,
349
+ }: {
350
+ organization: string;
351
+ project: string;
352
+ keyId: string;
353
+ },
354
+ ): Promise<{ id: string; name: string } | null> {
355
+ const response = await api.get(
356
+ `/projects/${organization}/${project}/keys/${keyId}`,
357
+ );
358
+ if (!response.ok) {
359
+ throw new Error(`API error: ${response.statusText}`);
360
+ }
361
+
362
+ const key = (await response.json()) as { id: string; name: string };
363
+ return key ? { id: key.id, name: key.name } : null;
364
+ }
@@ -10,8 +10,10 @@ import { SentryApi } from "./api.ts";
10
10
  export interface ProjectProps {
11
11
  /**
12
12
  * The name for the project
13
+ *
14
+ * @default ${app}-${stage}-${id}
13
15
  */
14
- name: string;
16
+ name?: string;
15
17
 
16
18
  /**
17
19
  * Uniquely identifies a project and is used for the interface
@@ -63,6 +65,11 @@ export interface Project
63
65
  */
64
66
  id: string;
65
67
 
68
+ /**
69
+ * The name for the project
70
+ */
71
+ name: string;
72
+
66
73
  /**
67
74
  * The team that owns the project
68
75
  */
@@ -282,11 +289,43 @@ export const Project = Resource(
282
289
  "sentry::Project",
283
290
  async function (
284
291
  this: Context<Project>,
285
- _id: string,
292
+ id: string,
286
293
  props: ProjectProps,
287
294
  ): Promise<Project> {
288
295
  const api = new SentryApi({ authToken: props.authToken });
289
296
 
297
+ // it's possible that `this.output.name` is undefined because a previous version
298
+ // of alchemy had a bug where it didn't set the name on the output
299
+ // so, we try to find the key by ID and use the name from the API response
300
+ const lookupName = async () => {
301
+ if (!this.output) {
302
+ return undefined;
303
+ } else if (this.output.name) {
304
+ return this.output.name;
305
+ }
306
+ const name = await getProjectName(
307
+ api,
308
+ props.organization,
309
+ this.output.id,
310
+ );
311
+ if (name) {
312
+ this.output.name = name;
313
+ }
314
+ return name;
315
+ };
316
+
317
+ const projectName =
318
+ props.name ?? (await lookupName()) ?? this.scope.createPhysicalName(id);
319
+
320
+ if (this.phase === "update" && this.output.name !== projectName) {
321
+ await api.put(
322
+ `/projects/${props.organization}/${this.output.slug || this.output.id}/`,
323
+ {
324
+ name: projectName,
325
+ },
326
+ );
327
+ }
328
+
290
329
  if (this.phase === "delete") {
291
330
  try {
292
331
  if (this.output?.id) {
@@ -319,22 +358,22 @@ export const Project = Resource(
319
358
  } catch (error) {
320
359
  // Check if this is a "project already exists" error and adopt is enabled
321
360
  if (
322
- props.adopt &&
361
+ (props.adopt ?? this.scope.adopt) &&
323
362
  error instanceof Error &&
324
363
  error.message.includes("already exists")
325
364
  ) {
326
365
  logger.log(
327
- `Project '${props.slug || props.name}' already exists, adopting it`,
366
+ `Project '${props.slug || projectName}' already exists, adopting it`,
328
367
  );
329
368
  // Find the existing project by slug
330
369
  const existingProject = await findProjectBySlug(
331
370
  api,
332
371
  props.organization,
333
- props.slug || props.name,
372
+ props.slug || projectName,
334
373
  );
335
374
  if (!existingProject) {
336
375
  throw new Error(
337
- `Failed to find existing project '${props.slug || props.name}' for adoption`,
376
+ `Failed to find existing project '${props.slug || projectName}' for adoption`,
338
377
  );
339
378
  }
340
379
  response = await api.get(
@@ -357,6 +396,7 @@ export const Project = Resource(
357
396
  return this({
358
397
  ...props,
359
398
  id: data.id,
399
+ name: projectName,
360
400
  team: data.team,
361
401
  teams: data.teams,
362
402
  isBookmarked: data.isBookmarked,
@@ -419,3 +459,16 @@ async function findProjectBySlug(
419
459
  const project = projects.find((p) => p.slug === slug);
420
460
  return project ? { id: project.id, slug: project.slug } : null;
421
461
  }
462
+
463
+ async function getProjectName(
464
+ api: SentryApi,
465
+ organization: string,
466
+ slug: string,
467
+ ): Promise<string | undefined> {
468
+ const response = await api.get(`/projects/${organization}/${slug}/`);
469
+ if (!response.ok) {
470
+ throw new Error(`API error: ${response.statusText}`);
471
+ }
472
+
473
+ return ((await response.json()) as { name: string }).name;
474
+ }