alchemy 2.0.0-beta.10 → 2.0.0-beta.13

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 (420) hide show
  1. package/bin/alchemy.js +1122 -450
  2. package/bin/alchemy.js.map +1 -1
  3. package/bin/alchemy.sh +15 -0
  4. package/bin/alchemy.ts +22 -727
  5. package/bin/commands/_shared.ts +237 -0
  6. package/bin/commands/bootstrap.ts +117 -0
  7. package/bin/commands/deploy.ts +144 -0
  8. package/bin/commands/login.ts +93 -0
  9. package/bin/commands/logs.ts +157 -0
  10. package/bin/commands/tail.ts +138 -0
  11. package/lib/AWS/AuthProvider.d.ts +7 -71
  12. package/lib/AWS/AuthProvider.d.ts.map +1 -1
  13. package/lib/AWS/AuthProvider.js +27 -22
  14. package/lib/AWS/AuthProvider.js.map +1 -1
  15. package/lib/AWS/AutoScaling/LaunchTemplate.d.ts +3 -3
  16. package/lib/AWS/AutoScaling/LaunchTemplate.d.ts.map +1 -1
  17. package/lib/AWS/AutoScaling/LaunchTemplate.js +2 -2
  18. package/lib/AWS/AutoScaling/LaunchTemplate.js.map +1 -1
  19. package/lib/AWS/Bootstrap.d.ts +2 -1
  20. package/lib/AWS/Bootstrap.d.ts.map +1 -1
  21. package/lib/AWS/Bootstrap.js +27 -29
  22. package/lib/AWS/Bootstrap.js.map +1 -1
  23. package/lib/AWS/CloudWatch/Alarm.d.ts +2 -2
  24. package/lib/AWS/CloudWatch/Alarm.d.ts.map +1 -1
  25. package/lib/AWS/CloudWatch/Alarm.js +2 -2
  26. package/lib/AWS/CloudWatch/Alarm.js.map +1 -1
  27. package/lib/AWS/CloudWatch/AlarmMuteRule.d.ts +2 -2
  28. package/lib/AWS/CloudWatch/AlarmMuteRule.d.ts.map +1 -1
  29. package/lib/AWS/CloudWatch/AlarmMuteRule.js +2 -2
  30. package/lib/AWS/CloudWatch/AlarmMuteRule.js.map +1 -1
  31. package/lib/AWS/CloudWatch/CompositeAlarm.d.ts +2 -2
  32. package/lib/AWS/CloudWatch/CompositeAlarm.d.ts.map +1 -1
  33. package/lib/AWS/CloudWatch/CompositeAlarm.js +2 -2
  34. package/lib/AWS/CloudWatch/CompositeAlarm.js.map +1 -1
  35. package/lib/AWS/CloudWatch/Dashboard.d.ts +2 -2
  36. package/lib/AWS/CloudWatch/Dashboard.d.ts.map +1 -1
  37. package/lib/AWS/CloudWatch/Dashboard.js +2 -2
  38. package/lib/AWS/CloudWatch/Dashboard.js.map +1 -1
  39. package/lib/AWS/CloudWatch/InsightRule.d.ts +2 -2
  40. package/lib/AWS/CloudWatch/InsightRule.d.ts.map +1 -1
  41. package/lib/AWS/CloudWatch/InsightRule.js +2 -2
  42. package/lib/AWS/CloudWatch/InsightRule.js.map +1 -1
  43. package/lib/AWS/CloudWatch/MetricStream.d.ts +2 -2
  44. package/lib/AWS/CloudWatch/MetricStream.d.ts.map +1 -1
  45. package/lib/AWS/CloudWatch/MetricStream.js +2 -2
  46. package/lib/AWS/CloudWatch/MetricStream.js.map +1 -1
  47. package/lib/AWS/Credentials.d.ts +5 -10
  48. package/lib/AWS/Credentials.d.ts.map +1 -1
  49. package/lib/AWS/Credentials.js +6 -30
  50. package/lib/AWS/Credentials.js.map +1 -1
  51. package/lib/AWS/DynamoDB/Table.d.ts +1 -1
  52. package/lib/AWS/DynamoDB/Table.d.ts.map +1 -1
  53. package/lib/AWS/EC2/EIP.d.ts +3 -3
  54. package/lib/AWS/EC2/EIP.d.ts.map +1 -1
  55. package/lib/AWS/EC2/EIP.js +2 -2
  56. package/lib/AWS/EC2/EIP.js.map +1 -1
  57. package/lib/AWS/EC2/EgressOnlyInternetGateway.d.ts +3 -3
  58. package/lib/AWS/EC2/EgressOnlyInternetGateway.d.ts.map +1 -1
  59. package/lib/AWS/EC2/EgressOnlyInternetGateway.js +2 -2
  60. package/lib/AWS/EC2/EgressOnlyInternetGateway.js.map +1 -1
  61. package/lib/AWS/EC2/Instance.d.ts +3 -3
  62. package/lib/AWS/EC2/Instance.d.ts.map +1 -1
  63. package/lib/AWS/EC2/Instance.js +2 -2
  64. package/lib/AWS/EC2/Instance.js.map +1 -1
  65. package/lib/AWS/EC2/InternetGateway.d.ts +3 -3
  66. package/lib/AWS/EC2/InternetGateway.d.ts.map +1 -1
  67. package/lib/AWS/EC2/InternetGateway.js +2 -2
  68. package/lib/AWS/EC2/InternetGateway.js.map +1 -1
  69. package/lib/AWS/EC2/NatGateway.d.ts +3 -3
  70. package/lib/AWS/EC2/NatGateway.d.ts.map +1 -1
  71. package/lib/AWS/EC2/NatGateway.js +2 -2
  72. package/lib/AWS/EC2/NatGateway.js.map +1 -1
  73. package/lib/AWS/EC2/Network.d.ts +1 -1
  74. package/lib/AWS/EC2/NetworkAcl.d.ts +3 -3
  75. package/lib/AWS/EC2/NetworkAcl.d.ts.map +1 -1
  76. package/lib/AWS/EC2/NetworkAcl.js +2 -2
  77. package/lib/AWS/EC2/NetworkAcl.js.map +1 -1
  78. package/lib/AWS/EC2/RouteTable.d.ts +3 -3
  79. package/lib/AWS/EC2/RouteTable.d.ts.map +1 -1
  80. package/lib/AWS/EC2/RouteTable.js +2 -2
  81. package/lib/AWS/EC2/RouteTable.js.map +1 -1
  82. package/lib/AWS/EC2/SecurityGroup.d.ts +3 -3
  83. package/lib/AWS/EC2/SecurityGroup.d.ts.map +1 -1
  84. package/lib/AWS/EC2/SecurityGroup.js +2 -2
  85. package/lib/AWS/EC2/SecurityGroup.js.map +1 -1
  86. package/lib/AWS/EC2/Subnet.d.ts +1 -1
  87. package/lib/AWS/EC2/Subnet.d.ts.map +1 -1
  88. package/lib/AWS/EC2/Vpc.d.ts +3 -3
  89. package/lib/AWS/EC2/Vpc.d.ts.map +1 -1
  90. package/lib/AWS/EC2/Vpc.js +2 -2
  91. package/lib/AWS/EC2/Vpc.js.map +1 -1
  92. package/lib/AWS/EC2/VpcEndpoint.d.ts +3 -3
  93. package/lib/AWS/EC2/VpcEndpoint.d.ts.map +1 -1
  94. package/lib/AWS/EC2/VpcEndpoint.js +2 -2
  95. package/lib/AWS/EC2/VpcEndpoint.js.map +1 -1
  96. package/lib/AWS/ECR/Repository.d.ts +1 -1
  97. package/lib/AWS/ECR/Repository.d.ts.map +1 -1
  98. package/lib/AWS/ECR/Repository.js +0 -1
  99. package/lib/AWS/ECR/Repository.js.map +1 -1
  100. package/lib/AWS/ECS/Cluster.d.ts +2 -2
  101. package/lib/AWS/ECS/Cluster.d.ts.map +1 -1
  102. package/lib/AWS/ECS/Cluster.js +2 -2
  103. package/lib/AWS/ECS/Cluster.js.map +1 -1
  104. package/lib/AWS/ECS/Service.d.ts +1 -1
  105. package/lib/AWS/ECS/Service.d.ts.map +1 -1
  106. package/lib/AWS/ECS/Task.d.ts +2 -2
  107. package/lib/AWS/ECS/Task.d.ts.map +1 -1
  108. package/lib/AWS/ECS/Task.js +2 -2
  109. package/lib/AWS/ECS/Task.js.map +1 -1
  110. package/lib/AWS/EKS/Cluster.d.ts +1 -1
  111. package/lib/AWS/EKS/Cluster.d.ts.map +1 -1
  112. package/lib/AWS/ELBv2/Listener.d.ts +1 -1
  113. package/lib/AWS/ELBv2/Listener.d.ts.map +1 -1
  114. package/lib/AWS/ELBv2/LoadBalancer.d.ts +1 -1
  115. package/lib/AWS/ELBv2/LoadBalancer.d.ts.map +1 -1
  116. package/lib/AWS/ELBv2/TargetGroup.d.ts +1 -1
  117. package/lib/AWS/ELBv2/TargetGroup.d.ts.map +1 -1
  118. package/lib/AWS/Endpoint.d.ts +7 -2
  119. package/lib/AWS/Endpoint.d.ts.map +1 -1
  120. package/lib/AWS/Endpoint.js +7 -2
  121. package/lib/AWS/Endpoint.js.map +1 -1
  122. package/lib/AWS/Environment.d.ts +68 -0
  123. package/lib/AWS/Environment.d.ts.map +1 -0
  124. package/lib/AWS/Environment.js +53 -0
  125. package/lib/AWS/Environment.js.map +1 -0
  126. package/lib/AWS/EventBridge/EventBus.d.ts +2 -2
  127. package/lib/AWS/EventBridge/EventBus.d.ts.map +1 -1
  128. package/lib/AWS/EventBridge/EventBus.js +2 -2
  129. package/lib/AWS/EventBridge/EventBus.js.map +1 -1
  130. package/lib/AWS/EventBridge/ListRules.d.ts +2 -2
  131. package/lib/AWS/EventBridge/ListRules.d.ts.map +1 -1
  132. package/lib/AWS/EventBridge/ListRules.js +2 -2
  133. package/lib/AWS/EventBridge/ListRules.js.map +1 -1
  134. package/lib/AWS/EventBridge/PutEvents.d.ts +2 -2
  135. package/lib/AWS/EventBridge/PutEvents.d.ts.map +1 -1
  136. package/lib/AWS/EventBridge/PutEvents.js +2 -2
  137. package/lib/AWS/EventBridge/PutEvents.js.map +1 -1
  138. package/lib/AWS/EventBridge/Rule.d.ts +2 -2
  139. package/lib/AWS/EventBridge/Rule.d.ts.map +1 -1
  140. package/lib/AWS/EventBridge/Rule.js +2 -2
  141. package/lib/AWS/EventBridge/Rule.js.map +1 -1
  142. package/lib/AWS/IAM/OpenIDConnectProvider.d.ts +2 -2
  143. package/lib/AWS/IAM/OpenIDConnectProvider.d.ts.map +1 -1
  144. package/lib/AWS/IAM/OpenIDConnectProvider.js +2 -2
  145. package/lib/AWS/IAM/OpenIDConnectProvider.js.map +1 -1
  146. package/lib/AWS/IAM/Policy.d.ts +3 -3
  147. package/lib/AWS/IAM/Policy.d.ts.map +1 -1
  148. package/lib/AWS/IAM/Policy.js +2 -2
  149. package/lib/AWS/IAM/Policy.js.map +1 -1
  150. package/lib/AWS/IAM/Role.d.ts +3 -3
  151. package/lib/AWS/IAM/Role.d.ts.map +1 -1
  152. package/lib/AWS/IAM/Role.js +3 -3
  153. package/lib/AWS/IAM/Role.js.map +1 -1
  154. package/lib/AWS/Kinesis/Stream.d.ts +2 -2
  155. package/lib/AWS/Kinesis/Stream.d.ts.map +1 -1
  156. package/lib/AWS/Kinesis/Stream.js +2 -2
  157. package/lib/AWS/Kinesis/Stream.js.map +1 -1
  158. package/lib/AWS/Lambda/BucketEventSource.d.ts +1 -1
  159. package/lib/AWS/Lambda/BucketEventSource.d.ts.map +1 -1
  160. package/lib/AWS/Lambda/EventBridgeEventSource.d.ts +1 -1
  161. package/lib/AWS/Lambda/EventBridgeEventSource.d.ts.map +1 -1
  162. package/lib/AWS/Lambda/EventSourceMapping.d.ts +2 -2
  163. package/lib/AWS/Lambda/EventSourceMapping.d.ts.map +1 -1
  164. package/lib/AWS/Lambda/EventSourceMapping.js +2 -2
  165. package/lib/AWS/Lambda/EventSourceMapping.js.map +1 -1
  166. package/lib/AWS/Lambda/Function.d.ts +2 -2
  167. package/lib/AWS/Lambda/Function.d.ts.map +1 -1
  168. package/lib/AWS/Lambda/Function.js +2 -2
  169. package/lib/AWS/Lambda/Function.js.map +1 -1
  170. package/lib/AWS/Lambda/Permission.d.ts +1 -1
  171. package/lib/AWS/Lambda/Permission.js +1 -1
  172. package/lib/AWS/Lambda/QueueEventSource.d.ts +1 -1
  173. package/lib/AWS/Lambda/QueueEventSource.d.ts.map +1 -1
  174. package/lib/AWS/Lambda/StreamEventSource.d.ts +1 -1
  175. package/lib/AWS/Lambda/StreamEventSource.d.ts.map +1 -1
  176. package/lib/AWS/Lambda/TableEventSource.d.ts +1 -1
  177. package/lib/AWS/Lambda/TableEventSource.d.ts.map +1 -1
  178. package/lib/AWS/Lambda/TopicEventSource.d.ts +1 -1
  179. package/lib/AWS/Lambda/TopicEventSource.d.ts.map +1 -1
  180. package/lib/AWS/Logs/LogGroup.d.ts +3 -3
  181. package/lib/AWS/Logs/LogGroup.d.ts.map +1 -1
  182. package/lib/AWS/Logs/LogGroup.js +2 -2
  183. package/lib/AWS/Logs/LogGroup.js.map +1 -1
  184. package/lib/AWS/Providers.d.ts +1 -2
  185. package/lib/AWS/Providers.d.ts.map +1 -1
  186. package/lib/AWS/Providers.js +3 -3
  187. package/lib/AWS/Providers.js.map +1 -1
  188. package/lib/AWS/Region.d.ts +6 -22
  189. package/lib/AWS/Region.d.ts.map +1 -1
  190. package/lib/AWS/Region.js +6 -39
  191. package/lib/AWS/Region.js.map +1 -1
  192. package/lib/AWS/S3/Bucket.d.ts +2 -2
  193. package/lib/AWS/S3/Bucket.d.ts.map +1 -1
  194. package/lib/AWS/S3/Bucket.js +2 -2
  195. package/lib/AWS/S3/Bucket.js.map +1 -1
  196. package/lib/AWS/SNS/Topic.d.ts +1 -1
  197. package/lib/AWS/SNS/Topic.d.ts.map +1 -1
  198. package/lib/AWS/SQS/Queue.d.ts +3 -3
  199. package/lib/AWS/SQS/Queue.d.ts.map +1 -1
  200. package/lib/AWS/SQS/Queue.js +2 -2
  201. package/lib/AWS/SQS/Queue.js.map +1 -1
  202. package/lib/AWS/index.d.ts +1 -3
  203. package/lib/AWS/index.d.ts.map +1 -1
  204. package/lib/AWS/index.js +1 -3
  205. package/lib/AWS/index.js.map +1 -1
  206. package/lib/Apply.d.ts.map +1 -1
  207. package/lib/Apply.js +2 -2
  208. package/lib/Apply.js.map +1 -1
  209. package/lib/Auth/AuthProvider.d.ts +51 -7
  210. package/lib/Auth/AuthProvider.d.ts.map +1 -1
  211. package/lib/Auth/AuthProvider.js +37 -0
  212. package/lib/Auth/AuthProvider.js.map +1 -1
  213. package/lib/Auth/Profile.d.ts +71 -10
  214. package/lib/Auth/Profile.d.ts.map +1 -1
  215. package/lib/Auth/Profile.js +47 -30
  216. package/lib/Auth/Profile.js.map +1 -1
  217. package/lib/Auth/index.d.ts +1 -1
  218. package/lib/Auth/index.d.ts.map +1 -1
  219. package/lib/Cloudflare/Auth/AuthProvider.d.ts +14 -31
  220. package/lib/Cloudflare/Auth/AuthProvider.d.ts.map +1 -1
  221. package/lib/Cloudflare/Auth/AuthProvider.js +59 -38
  222. package/lib/Cloudflare/Auth/AuthProvider.js.map +1 -1
  223. package/lib/Cloudflare/CloudflareEnvironment.d.ts +11 -0
  224. package/lib/Cloudflare/CloudflareEnvironment.d.ts.map +1 -0
  225. package/lib/Cloudflare/CloudflareEnvironment.js +26 -0
  226. package/lib/Cloudflare/CloudflareEnvironment.js.map +1 -0
  227. package/lib/Cloudflare/Container/ContainerApplication.d.ts +70 -42
  228. package/lib/Cloudflare/Container/ContainerApplication.d.ts.map +1 -1
  229. package/lib/Cloudflare/Container/ContainerApplication.js +49 -24
  230. package/lib/Cloudflare/Container/ContainerApplication.js.map +1 -1
  231. package/lib/Cloudflare/Credentials.d.ts +11 -0
  232. package/lib/Cloudflare/Credentials.d.ts.map +1 -0
  233. package/lib/Cloudflare/Credentials.js +34 -0
  234. package/lib/Cloudflare/Credentials.js.map +1 -0
  235. package/lib/Cloudflare/D1/D1Database.d.ts +2 -2
  236. package/lib/Cloudflare/D1/D1Database.d.ts.map +1 -1
  237. package/lib/Cloudflare/D1/D1Database.js +2 -2
  238. package/lib/Cloudflare/D1/D1Database.js.map +1 -1
  239. package/lib/Cloudflare/KV/KVNamespace.d.ts +2 -2
  240. package/lib/Cloudflare/KV/KVNamespace.d.ts.map +1 -1
  241. package/lib/Cloudflare/KV/KVNamespace.js +2 -2
  242. package/lib/Cloudflare/KV/KVNamespace.js.map +1 -1
  243. package/lib/Cloudflare/Providers.d.ts +2 -3
  244. package/lib/Cloudflare/Providers.d.ts.map +1 -1
  245. package/lib/Cloudflare/Providers.js +12 -4
  246. package/lib/Cloudflare/Providers.js.map +1 -1
  247. package/lib/Cloudflare/Queue/Queue.d.ts +52 -0
  248. package/lib/Cloudflare/Queue/Queue.d.ts.map +1 -0
  249. package/lib/Cloudflare/Queue/Queue.js +136 -0
  250. package/lib/Cloudflare/Queue/Queue.js.map +1 -0
  251. package/lib/Cloudflare/Queue/QueueBinding.d.ts +35 -0
  252. package/lib/Cloudflare/Queue/QueueBinding.d.ts.map +1 -0
  253. package/lib/Cloudflare/Queue/QueueBinding.js +51 -0
  254. package/lib/Cloudflare/Queue/QueueBinding.js.map +1 -0
  255. package/lib/Cloudflare/Queue/QueueConsumer.d.ts +86 -0
  256. package/lib/Cloudflare/Queue/QueueConsumer.d.ts.map +1 -0
  257. package/lib/Cloudflare/Queue/QueueConsumer.js +138 -0
  258. package/lib/Cloudflare/Queue/QueueConsumer.js.map +1 -0
  259. package/lib/Cloudflare/Queue/index.d.ts +4 -0
  260. package/lib/Cloudflare/Queue/index.d.ts.map +1 -0
  261. package/lib/Cloudflare/Queue/index.js +4 -0
  262. package/lib/Cloudflare/Queue/index.js.map +1 -0
  263. package/lib/Cloudflare/R2/R2Bucket.d.ts +2 -2
  264. package/lib/Cloudflare/R2/R2Bucket.d.ts.map +1 -1
  265. package/lib/Cloudflare/R2/R2Bucket.js +2 -2
  266. package/lib/Cloudflare/R2/R2Bucket.js.map +1 -1
  267. package/lib/Cloudflare/SecretsStore/Secret.d.ts +74 -0
  268. package/lib/Cloudflare/SecretsStore/Secret.d.ts.map +1 -0
  269. package/lib/Cloudflare/SecretsStore/Secret.js +161 -0
  270. package/lib/Cloudflare/SecretsStore/Secret.js.map +1 -0
  271. package/lib/Cloudflare/SecretsStore/SecretBinding.d.ts +42 -0
  272. package/lib/Cloudflare/SecretsStore/SecretBinding.d.ts.map +1 -0
  273. package/lib/Cloudflare/SecretsStore/SecretBinding.js +49 -0
  274. package/lib/Cloudflare/SecretsStore/SecretBinding.js.map +1 -0
  275. package/lib/Cloudflare/SecretsStore/SecretsStore.d.ts +37 -0
  276. package/lib/Cloudflare/SecretsStore/SecretsStore.d.ts.map +1 -0
  277. package/lib/Cloudflare/SecretsStore/SecretsStore.js +88 -0
  278. package/lib/Cloudflare/SecretsStore/SecretsStore.js.map +1 -0
  279. package/lib/Cloudflare/SecretsStore/index.d.ts +4 -0
  280. package/lib/Cloudflare/SecretsStore/index.d.ts.map +1 -0
  281. package/lib/Cloudflare/SecretsStore/index.js +4 -0
  282. package/lib/Cloudflare/SecretsStore/index.js.map +1 -0
  283. package/lib/Cloudflare/Workers/InferEnv.d.ts +1 -1
  284. package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
  285. package/lib/Cloudflare/Workers/Worker.d.ts +5 -3
  286. package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
  287. package/lib/Cloudflare/Workers/Worker.js +61 -7
  288. package/lib/Cloudflare/Workers/Worker.js.map +1 -1
  289. package/lib/Cloudflare/Workers/Workflow.d.ts +10 -4
  290. package/lib/Cloudflare/Workers/Workflow.d.ts.map +1 -1
  291. package/lib/Cloudflare/Workers/Workflow.js +3 -3
  292. package/lib/Cloudflare/Workers/Workflow.js.map +1 -1
  293. package/lib/Cloudflare/index.d.ts +3 -1
  294. package/lib/Cloudflare/index.d.ts.map +1 -1
  295. package/lib/Cloudflare/index.js +3 -1
  296. package/lib/Cloudflare/index.js.map +1 -1
  297. package/lib/Stack.d.ts +3 -2
  298. package/lib/Stack.d.ts.map +1 -1
  299. package/lib/Stack.js +10 -7
  300. package/lib/Stack.js.map +1 -1
  301. package/lib/State/LocalState.d.ts.map +1 -1
  302. package/lib/State/LocalState.js +40 -12
  303. package/lib/State/LocalState.js.map +1 -1
  304. package/lib/Test/Bun.d.ts.map +1 -1
  305. package/lib/Test/Bun.js +3 -2
  306. package/lib/Test/Bun.js.map +1 -1
  307. package/lib/Test/Vitest.d.ts +3 -1
  308. package/lib/Test/Vitest.d.ts.map +1 -1
  309. package/lib/Test/Vitest.js +19 -16
  310. package/lib/Test/Vitest.js.map +1 -1
  311. package/lib/Util/PlatformServices.d.ts +14 -3
  312. package/lib/Util/PlatformServices.d.ts.map +1 -1
  313. package/lib/Util/PlatformServices.js +21 -3
  314. package/lib/Util/PlatformServices.js.map +1 -1
  315. package/package.json +5 -5
  316. package/src/AWS/AuthProvider.ts +67 -67
  317. package/src/AWS/AutoScaling/LaunchTemplate.ts +3 -3
  318. package/src/AWS/Bootstrap.ts +32 -37
  319. package/src/AWS/CloudWatch/Alarm.ts +2 -2
  320. package/src/AWS/CloudWatch/AlarmMuteRule.ts +2 -2
  321. package/src/AWS/CloudWatch/CompositeAlarm.ts +2 -2
  322. package/src/AWS/CloudWatch/Dashboard.ts +2 -2
  323. package/src/AWS/CloudWatch/InsightRule.ts +2 -2
  324. package/src/AWS/CloudWatch/MetricStream.ts +2 -2
  325. package/src/AWS/Credentials.ts +9 -44
  326. package/src/AWS/DynamoDB/Table.ts +1 -1
  327. package/src/AWS/EC2/EIP.ts +3 -3
  328. package/src/AWS/EC2/EgressOnlyInternetGateway.ts +3 -3
  329. package/src/AWS/EC2/Instance.ts +3 -3
  330. package/src/AWS/EC2/InternetGateway.ts +3 -3
  331. package/src/AWS/EC2/NatGateway.ts +3 -3
  332. package/src/AWS/EC2/NetworkAcl.ts +3 -3
  333. package/src/AWS/EC2/RouteTable.ts +3 -3
  334. package/src/AWS/EC2/SecurityGroup.ts +3 -3
  335. package/src/AWS/EC2/Subnet.ts +1 -1
  336. package/src/AWS/EC2/Vpc.ts +3 -3
  337. package/src/AWS/EC2/VpcEndpoint.ts +3 -3
  338. package/src/AWS/ECR/Repository.ts +1 -1
  339. package/src/AWS/ECS/Cluster.ts +2 -2
  340. package/src/AWS/ECS/Service.ts +1 -1
  341. package/src/AWS/ECS/Task.ts +2 -2
  342. package/src/AWS/EKS/Cluster.ts +1 -1
  343. package/src/AWS/ELBv2/Listener.ts +1 -1
  344. package/src/AWS/ELBv2/LoadBalancer.ts +1 -1
  345. package/src/AWS/ELBv2/TargetGroup.ts +1 -1
  346. package/src/AWS/Endpoint.ts +12 -8
  347. package/src/AWS/Environment.ts +123 -0
  348. package/src/AWS/EventBridge/EventBus.ts +2 -2
  349. package/src/AWS/EventBridge/ListRules.ts +2 -2
  350. package/src/AWS/EventBridge/PutEvents.ts +2 -2
  351. package/src/AWS/EventBridge/Rule.ts +2 -2
  352. package/src/AWS/IAM/OpenIDConnectProvider.ts +2 -2
  353. package/src/AWS/IAM/Policy.ts +3 -3
  354. package/src/AWS/IAM/Role.ts +4 -4
  355. package/src/AWS/Kinesis/Stream.ts +2 -2
  356. package/src/AWS/Lambda/EventSourceMapping.ts +2 -2
  357. package/src/AWS/Lambda/Function.ts +2 -2
  358. package/src/AWS/Lambda/Permission.ts +1 -1
  359. package/src/AWS/Logs/LogGroup.ts +3 -3
  360. package/src/AWS/Providers.ts +7 -7
  361. package/src/AWS/Region.ts +9 -66
  362. package/src/AWS/S3/Bucket.ts +2 -2
  363. package/src/AWS/SNS/Topic.ts +1 -1
  364. package/src/AWS/SQS/Queue.ts +3 -3
  365. package/src/AWS/index.ts +1 -3
  366. package/src/Apply.ts +55 -57
  367. package/src/Auth/AuthProvider.ts +188 -8
  368. package/src/Auth/Profile.ts +117 -54
  369. package/src/Auth/index.ts +1 -1
  370. package/src/Cloudflare/Auth/AuthProvider.ts +127 -98
  371. package/src/Cloudflare/CloudflareEnvironment.ts +49 -0
  372. package/src/Cloudflare/Container/ContainerApplication.ts +172 -94
  373. package/src/Cloudflare/Credentials.ts +75 -0
  374. package/src/Cloudflare/D1/D1Database.ts +2 -2
  375. package/src/Cloudflare/KV/KVNamespace.ts +2 -2
  376. package/src/Cloudflare/Providers.ts +20 -10
  377. package/src/Cloudflare/Queue/Queue.ts +174 -0
  378. package/src/Cloudflare/Queue/QueueBinding.ts +110 -0
  379. package/src/Cloudflare/Queue/QueueConsumer.ts +219 -0
  380. package/src/Cloudflare/Queue/index.ts +3 -0
  381. package/src/Cloudflare/R2/R2Bucket.ts +2 -2
  382. package/src/Cloudflare/SecretsStore/Secret.ts +229 -0
  383. package/src/Cloudflare/SecretsStore/SecretBinding.ts +107 -0
  384. package/src/Cloudflare/SecretsStore/SecretsStore.ts +106 -0
  385. package/src/Cloudflare/SecretsStore/index.ts +3 -0
  386. package/src/Cloudflare/Workers/InferEnv.ts +5 -3
  387. package/src/Cloudflare/Workers/Worker.ts +63 -7
  388. package/src/Cloudflare/Workers/Workflow.ts +19 -9
  389. package/src/Cloudflare/index.ts +3 -1
  390. package/src/Stack.ts +40 -29
  391. package/src/State/LocalState.ts +43 -16
  392. package/src/Test/Bun.ts +3 -0
  393. package/src/Test/Vitest.ts +31 -23
  394. package/src/Util/PlatformServices.ts +54 -13
  395. package/bin/process-manager.ts +0 -10
  396. package/lib/AWS/Account.d.ts +0 -26
  397. package/lib/AWS/Account.d.ts.map +0 -1
  398. package/lib/AWS/Account.js +0 -32
  399. package/lib/AWS/Account.js.map +0 -1
  400. package/lib/AWS/Profile.d.ts +0 -6
  401. package/lib/AWS/Profile.d.ts.map +0 -1
  402. package/lib/AWS/Profile.js +0 -4
  403. package/lib/AWS/Profile.js.map +0 -1
  404. package/lib/AWS/StageConfig.d.ts +0 -25
  405. package/lib/AWS/StageConfig.d.ts.map +0 -1
  406. package/lib/AWS/StageConfig.js +0 -23
  407. package/lib/AWS/StageConfig.js.map +0 -1
  408. package/lib/Cloudflare/Account.d.ts +0 -10
  409. package/lib/Cloudflare/Account.d.ts.map +0 -1
  410. package/lib/Cloudflare/Account.js +0 -24
  411. package/lib/Cloudflare/Account.js.map +0 -1
  412. package/lib/Cloudflare/StageConfig.d.ts +0 -8
  413. package/lib/Cloudflare/StageConfig.d.ts.map +0 -1
  414. package/lib/Cloudflare/StageConfig.js +0 -4
  415. package/lib/Cloudflare/StageConfig.js.map +0 -1
  416. package/src/AWS/Account.ts +0 -56
  417. package/src/AWS/Profile.ts +0 -5
  418. package/src/AWS/StageConfig.ts +0 -44
  419. package/src/Cloudflare/Account.ts +0 -38
  420. package/src/Cloudflare/StageConfig.ts +0 -8
package/bin/alchemy.js CHANGED
@@ -1,42 +1,47 @@
1
1
  import { createRequire } from "node:module";
2
- import * as Auth from "@distilled.cloud/aws/Auth";
3
- import { NodeRuntime, NodeServices } from "@effect/platform-node";
4
- import * as Config from "effect/Config";
5
2
  import * as ConfigProvider from "effect/ConfigProvider";
6
- import * as Console from "effect/Console";
7
3
  import * as Effect from "effect/Effect";
8
4
  import * as Layer from "effect/Layer";
9
- import * as Logger from "effect/Logger";
10
- import * as Option from "effect/Option";
5
+ import * as Command$1 from "effect/unstable/cli/Command";
6
+ import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
7
+ import * as Context from "effect/Context";
8
+ import * as FileSystem from "effect/FileSystem";
11
9
  import * as Path$1 from "effect/Path";
12
10
  import { Path } from "effect/Path";
13
- import * as S from "effect/Schema";
14
- import * as Stream$1 from "effect/Stream";
15
- import { Argument, Command, Flag } from "effect/unstable/cli";
11
+ import * as Cause from "effect/Cause";
12
+ import * as Config from "effect/Config";
13
+ import * as Console from "effect/Console";
14
+ import * as Option from "effect/Option";
15
+ import * as Schema from "effect/Schema";
16
+ import * as Argument from "effect/unstable/cli/Argument";
16
17
  import * as CliError from "effect/unstable/cli/CliError";
17
- import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
18
- import * as ChildProcess from "effect/unstable/process/ChildProcess";
19
- import * as Deferred from "effect/Deferred";
20
- import * as Context from "effect/Context";
18
+ import * as Flag$1 from "effect/unstable/cli/Flag";
19
+ import "@clack/prompts";
21
20
  import * as Data from "effect/Data";
21
+ import "effect/unstable/process";
22
+ import * as Auth from "@distilled.cloud/aws/Auth";
23
+ import * as Logger from "effect/Logger";
24
+ import * as Region$1 from "@distilled.cloud/aws/Region";
25
+ import { Region } from "@distilled.cloud/aws/Region";
26
+ import * as s3 from "@distilled.cloud/aws/s3";
27
+ import * as Schedule from "effect/Schedule";
28
+ import { Credentials, fromAwsCredentialIdentity } from "@distilled.cloud/aws/Credentials";
29
+ import * as Deferred from "effect/Deferred";
22
30
  import { pipe } from "effect/Function";
23
31
  import { SingleShotGen } from "effect/Utils";
24
32
  import { pipeArguments } from "effect/Pipeable";
25
- import * as FileSystem from "effect/FileSystem";
26
- import "@distilled.cloud/aws/sts";
27
- import { Region, Region as Region$1 } from "@distilled.cloud/aws/Region";
28
- import * as s3 from "@distilled.cloud/aws/s3";
29
- import * as Schedule from "effect/Schedule";
30
- import { Credentials } from "@distilled.cloud/aws/Credentials";
33
+ import * as Redacted from "effect/Redacted";
34
+ import os from "node:os";
31
35
  import { PassThrough, Stream } from "node:stream";
32
36
  import process$1, { cwd, env } from "node:process";
33
- import os from "node:os";
34
37
  import { execFileSync } from "node:child_process";
35
38
  import * as fs$1 from "node:fs";
36
39
  import fs from "node:fs";
37
40
  import tty from "node:tty";
38
41
  import { EventEmitter } from "node:events";
39
42
  import { Buffer as Buffer$1 } from "node:buffer";
43
+ import { Command, Flag } from "effect/unstable/cli";
44
+ import * as Stream$1 from "effect/Stream";
40
45
 
41
46
  //#region rolldown:runtime
42
47
  var __create = Object.create;
@@ -69,7 +74,410 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
69
74
 
70
75
  //#endregion
71
76
  //#region package.json
72
- var version = "2.0.0-beta.10";
77
+ var version = "2.0.0-beta.13";
78
+
79
+ //#endregion
80
+ //#region src/Config.ts
81
+ var DotAlchemy = class extends Context.Service()(".alchemy") {};
82
+ const dotAlchemy = Layer.effect(DotAlchemy, Effect.gen(function* () {
83
+ const fs$2 = yield* FileSystem.FileSystem;
84
+ const dir = (yield* Path$1.Path).join(process.cwd(), ".alchemy");
85
+ yield* fs$2.makeDirectory(dir, { recursive: true });
86
+ return dir;
87
+ }));
88
+
89
+ //#endregion
90
+ //#region src/Util/PlatformServices.ts
91
+ const isBun$1 = typeof Bun !== "undefined";
92
+ const PlatformServices = Effect.promise(async () => {
93
+ if (isBun$1) {
94
+ const [BunServices, BunSocket] = await Promise.all([import("@effect/platform-bun/BunServices"), import("@effect/platform-bun/BunSocket")]);
95
+ return Layer.merge(BunServices.layer, BunSocket.layerWebSocketConstructor);
96
+ } else {
97
+ const [NodeServices, NodeSocket] = await Promise.all([import("@effect/platform-node/NodeServices"), import("@effect/platform-node/NodeSocket")]);
98
+ return Layer.merge(NodeServices.layer, NodeSocket.layerWebSocketConstructor);
99
+ }
100
+ }).pipe(Layer.unwrap);
101
+ const runMain = (effect, options) => {
102
+ if (isBun$1) import("@effect/platform-bun/BunRuntime").then((BunRuntime) => BunRuntime.runMain(effect, options));
103
+ else import("@effect/platform-node/NodeRuntime").then((NodeRuntime) => NodeRuntime.runMain(effect, options));
104
+ };
105
+
106
+ //#endregion
107
+ //#region src/Auth/AuthProvider.ts
108
+ var AuthError = class extends Schema.TaggedErrorClass()("AuthError", {
109
+ message: Schema.String,
110
+ cause: Schema.optional(Schema.Defect)
111
+ }) {};
112
+ var AuthProviders = class extends Context.Service()("AuthProviders") {};
113
+
114
+ //#endregion
115
+ //#region src/Util/Clank.ts
116
+ var PromptCancelled = class extends Data.TaggedError("PromptCancelled") {};
117
+ const retryIfCancelled = Effect.retry({ while: (e) => e instanceof PromptCancelled });
118
+
119
+ //#endregion
120
+ //#region bin/commands/_shared.ts
121
+ const USER = Config.string("USER").pipe(Config.orElse(() => Config.string("USERNAME")), Config.withDefault("unknown"));
122
+ const STAGE = Config.string("stage").pipe(Config.option, (a) => a.asEffect(), Effect.map(Option.getOrUndefined));
123
+ /**
124
+ * `true` if `e` is a {@link PromptCancelled}, or an {@link AuthError} whose
125
+ * `cause` chain bottoms out in one. Schema-tagged errors don't always
126
+ * survive `instanceof` across module boundaries, so we also accept any
127
+ * object whose `_tag` matches.
128
+ */
129
+ const isPromptCancellation = (e) => {
130
+ for (let cur = e, i = 0; cur != null && i < 16; i++) {
131
+ if (cur instanceof PromptCancelled) return true;
132
+ if (typeof cur === "object" && cur._tag === "PromptCancelled") return true;
133
+ if (cur instanceof AuthError || typeof cur === "object" && cur._tag === "AuthError") {
134
+ cur = cur.cause;
135
+ continue;
136
+ }
137
+ return false;
138
+ }
139
+ return false;
140
+ };
141
+ /**
142
+ * Catches user cancellations (Ctrl+C inside a prompt, surfaced as
143
+ * {@link PromptCancelled} or wrapped in an {@link AuthError}) and exits
144
+ * the CLI cleanly with a friendly message instead of dumping a stack
145
+ * trace.
146
+ */
147
+ const handleCancellation = (self$1) => self$1.pipe(Effect.catchCause((cause) => {
148
+ return cause.reasons.some((r) => {
149
+ if (Cause.isFailReason(r)) return isPromptCancellation(r.error);
150
+ if (Cause.isDieReason(r)) return isPromptCancellation(r.defect);
151
+ return false;
152
+ }) ? Console.log("\nCancelled.") : Effect.failCause(cause);
153
+ }), Effect.onInterrupt(() => Console.log("\nInterrupted.")));
154
+ const stage = Flag$1.string("stage").pipe(Flag$1.withSchema(Schema.String.check(Schema.isPattern(/^[a-z0-9]+([-_a-z0-9]+)*$/gi))), Flag$1.withDescription("Stage to deploy to, defaults to dev_${USER}"), Flag$1.optional, Flag$1.map(Option.getOrUndefined), Flag$1.mapEffect(Effect.fn(function* (stage$1) {
155
+ if (stage$1) return stage$1;
156
+ return yield* STAGE.pipe(Effect.catch(() => Effect.fail(new CliError.MissingOption({ option: "stage" }))), Effect.flatMap((s) => s === void 0 ? USER.asEffect().pipe(Effect.map((user) => `dev_${user}`), Effect.catch(() => Effect.succeed("unknown"))) : Effect.succeed(s)));
157
+ })));
158
+ const envFile = Flag$1.file("env-file").pipe(Flag$1.optional, Flag$1.withDescription("File to load environment variables from, defaults to .env"));
159
+ const dryRun = Flag$1.boolean("dry-run").pipe(Flag$1.withDescription("Dry run the deployment, do not actually deploy"), Flag$1.withDefault(false));
160
+ const yes = Flag$1.boolean("yes").pipe(Flag$1.withDescription("Yes to all prompts"), Flag$1.withDefault(false));
161
+ const force = Flag$1.boolean("force").pipe(Flag$1.withDescription("Force updates for resources that would otherwise no-op"), Flag$1.withDefault(false));
162
+ const main = Argument.file("main", { mustExist: true }).pipe(Argument.withDescription("Main file to deploy, defaults to alchemy.run.ts"), Argument.withDefault("alchemy.run.ts"));
163
+ const profile = Flag$1.string("profile").pipe(Flag$1.withDescription("Auth profile to use (~/.alchemy/profiles.json). Defaults to 'default' or $ALCHEMY_PROFILE."), Flag$1.optional, Flag$1.map(Option.getOrElse(() => "default")));
164
+ const resourceFilter = Flag$1.string("filter").pipe(Flag$1.withDescription("Comma-separated logical resource IDs (e.g. Api,Sandbox). Only those resources are included."), Flag$1.optional, Flag$1.map(Option.getOrUndefined));
165
+ const TAIL_COLORS = [
166
+ "\x1B[36m",
167
+ "\x1B[35m",
168
+ "\x1B[33m",
169
+ "\x1B[32m",
170
+ "\x1B[34m",
171
+ "\x1B[91m",
172
+ "\x1B[96m",
173
+ "\x1B[95m",
174
+ "\x1B[93m",
175
+ "\x1B[92m"
176
+ ];
177
+ const TAIL_RESET = "\x1B[0m";
178
+ const formatLocalTimestamp = (date) => {
179
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")} ${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}:${String(date.getSeconds()).padStart(2, "0")}.${String(date.getMilliseconds()).padStart(3, "0")} ${new Intl.DateTimeFormat("en-US", { timeZoneName: "short" }).formatToParts(date).find((p) => p.type === "timeZoneName")?.value ?? ""}`;
180
+ };
181
+ const parseResourceFilter = (filter) => {
182
+ if (filter === void 0) return void 0;
183
+ const ids = filter.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
184
+ if (ids.length === 0) return void 0;
185
+ return new Set(ids);
186
+ };
187
+ const parseSince = (value) => {
188
+ const match = value.match(/^(\d+)([smhd])$/);
189
+ if (match) {
190
+ const num = parseInt(match[1], 10);
191
+ const unit = match[2];
192
+ const ms = unit === "s" ? num * 1e3 : unit === "m" ? num * 6e4 : unit === "h" ? num * 36e5 : num * 864e5;
193
+ return new Date(Date.now() - ms);
194
+ }
195
+ const parsed = new Date(value);
196
+ if (isNaN(parsed.getTime())) throw new Error(`Invalid --since value: '${value}'. Use a duration (e.g. '1h', '30m') or ISO date.`);
197
+ return parsed;
198
+ };
199
+ const importStack = Effect.fn(function* (main$1) {
200
+ const path = yield* Path$1.Path;
201
+ const stackEffect = (yield* Effect.promise(() => import(path.resolve(process.cwd(), main$1)))).default;
202
+ if (!Effect.isEffect(stackEffect)) return yield* Effect.die(/* @__PURE__ */ new Error(`Main file '${main$1}' must export a default stack definition (export default Alchemy.Stack({...}))`));
203
+ return stackEffect;
204
+ });
205
+
206
+ //#endregion
207
+ //#region src/AWS/Environment.ts
208
+ const AWS_PROFILE = Config.string("AWS_PROFILE").pipe(Config.withDefault("default"));
209
+ const AWS_REGION = Config.string("AWS_REGION");
210
+ var AWSEnvironment = class extends Context.Service()("AWS::Environment") {};
211
+ /**
212
+ * Build an `AWSEnvironment` from an SSO profile (`AWS_PROFILE` env var,
213
+ * defaults to `"default"`). Uses the profile's `sso_account_id` and `region`,
214
+ * and resolves credentials lazily via `aws sso login`.
215
+ */
216
+ const Default = Layer.effect(AWSEnvironment, Effect.suspend(() => loadDefault())).pipe(Layer.orDie);
217
+ const loadDefault = () => Effect.gen(function* () {
218
+ const profileName = yield* AWS_PROFILE;
219
+ const auth = yield* Auth.Default;
220
+ const profile$1 = yield* auth.loadProfile(profileName);
221
+ if (!profile$1.sso_account_id) return yield* Effect.die(`AWS SSO profile '${profileName}' is missing sso_account_id`);
222
+ const region = profile$1.region ?? (yield* AWS_REGION.pipe(Config.option, Config.map(Option.getOrElse(() => "us-east-1"))));
223
+ return {
224
+ profile: profileName,
225
+ accountId: profile$1.sso_account_id,
226
+ region,
227
+ credentials: auth.loadProfileCredentials(profileName)
228
+ };
229
+ });
230
+ const isStatic = (shape) => shape.credentials != null && typeof shape.credentials.accessKeyId === "string";
231
+ /**
232
+ * Build an `AWSEnvironment` Layer directly from values — useful for
233
+ * static credentials in CI or tests.
234
+ *
235
+ * Named `makeEnvironment` rather than `of` because `Context.Service.of`
236
+ * already exists with different semantics (builds the service value, not
237
+ * a Layer); putting both on `AWSEnvironment` would be confusing.
238
+ */
239
+ const makeEnvironment = (shape) => Layer.succeed(AWSEnvironment, isStatic(shape) ? {
240
+ ...shape,
241
+ credentials: Effect.succeed(fromAwsCredentialIdentity(shape.credentials))
242
+ } : shape);
243
+
244
+ //#endregion
245
+ //#region src/AWS/Bootstrap.ts
246
+ /**
247
+ * Tag key used to identify the alchemy assets bucket.
248
+ */
249
+ const ASSETS_BUCKET_TAG = "alchemy::assets-bucket";
250
+ /**
251
+ * Tag key used to scope the alchemy assets bucket to an AWS region.
252
+ */
253
+ const ASSETS_BUCKET_REGION_TAG = "alchemy::assets-bucket-region";
254
+ /**
255
+ * Build an account-regional namespace bucket name.
256
+ *
257
+ * Account-regional buckets must follow the naming convention:
258
+ * `<prefix>-<accountId>-<region>-an`
259
+ *
260
+ * @see https://docs.aws.amazon.com/AmazonS3/latest/userguide/gpbucketnamespaces.html#account-regional-gp-buckets
261
+ */
262
+ const createAssetsBucketName = (accountId, region) => `alchemy-assets-${accountId}-${region}-an`.toLowerCase();
263
+ const createAssetsBucketTags = (region) => [{
264
+ Key: ASSETS_BUCKET_TAG,
265
+ Value: "true"
266
+ }, {
267
+ Key: ASSETS_BUCKET_REGION_TAG,
268
+ Value: region
269
+ }];
270
+ const getBucketTags = (bucketName) => s3.getBucketTagging({ Bucket: bucketName }).pipe(Effect.map((response) => response.TagSet ?? []), Effect.catchTag("NoSuchTagSet", () => Effect.succeed([])));
271
+ const hasAssetsBucketTag = (tags) => tags.some((tag) => tag.Key === ASSETS_BUCKET_TAG && tag.Value === "true");
272
+ const normalizeBucketRegion = (location) => {
273
+ if (!location) return "us-east-1";
274
+ if (location === "EU") return "eu-west-1";
275
+ return location;
276
+ };
277
+ const bucketMatchesRegion = (tags, region) => {
278
+ const taggedRegion = tags.find((tag) => tag.Key === ASSETS_BUCKET_REGION_TAG)?.Value;
279
+ return taggedRegion === void 0 ? void 0 : taggedRegion === region;
280
+ };
281
+ const lookupAssetsBuckets = Effect.gen(function* () {
282
+ const region = yield* Region;
283
+ const buckets = (yield* s3.listBuckets({})).Buckets ?? [];
284
+ const matchingBuckets = [];
285
+ for (const bucket of buckets) {
286
+ const bucketName = bucket.Name;
287
+ if (!bucketName) continue;
288
+ const tags = yield* getBucketTags(bucketName).pipe(Effect.catch(() => Effect.succeed([])));
289
+ if (!hasAssetsBucketTag(tags)) continue;
290
+ const taggedRegionMatch = bucketMatchesRegion(tags, region);
291
+ if (taggedRegionMatch === true) {
292
+ matchingBuckets.push(bucketName);
293
+ continue;
294
+ }
295
+ if (taggedRegionMatch === false) continue;
296
+ if ((yield* s3.getBucketLocation({ Bucket: bucketName }).pipe(Effect.map((response) => normalizeBucketRegion(response.LocationConstraint)), Effect.catch(() => Effect.succeed(void 0)))) === region) matchingBuckets.push(bucketName);
297
+ }
298
+ return matchingBuckets;
299
+ });
300
+ const lookupAssetsBucket = Effect.gen(function* () {
301
+ const matchingBuckets = yield* lookupAssetsBuckets;
302
+ for (const bucketName of matchingBuckets) return Option.some(bucketName);
303
+ return Option.none();
304
+ });
305
+ const ensureAssetsBucketTags = Effect.fn(function* (bucketName, region) {
306
+ const tagSet = [...(yield* getBucketTags(bucketName)).filter((tag) => tag.Key !== ASSETS_BUCKET_TAG && tag.Key !== ASSETS_BUCKET_REGION_TAG), ...createAssetsBucketTags(region)];
307
+ yield* s3.putBucketTagging({
308
+ Bucket: bucketName,
309
+ Tagging: { TagSet: tagSet.map((tag) => ({
310
+ Key: tag.Key,
311
+ Value: tag.Value
312
+ })) }
313
+ });
314
+ });
315
+ const deleteAllObjects = Effect.fn(function* (bucketName) {
316
+ let continuationToken;
317
+ do {
318
+ const listResponse = yield* s3.listObjectsV2({
319
+ Bucket: bucketName,
320
+ ContinuationToken: continuationToken
321
+ });
322
+ if (listResponse.Contents && listResponse.Contents.length > 0) yield* s3.deleteObjects({
323
+ Bucket: bucketName,
324
+ Delete: {
325
+ Objects: listResponse.Contents.map((obj) => ({ Key: obj.Key })),
326
+ Quiet: true
327
+ }
328
+ });
329
+ continuationToken = listResponse.NextContinuationToken;
330
+ } while (continuationToken);
331
+ let keyMarker;
332
+ let versionIdMarker;
333
+ do {
334
+ const listVersionsResponse = yield* s3.listObjectVersions({
335
+ Bucket: bucketName,
336
+ KeyMarker: keyMarker,
337
+ VersionIdMarker: versionIdMarker
338
+ });
339
+ const objectsToDelete = [...(listVersionsResponse.Versions ?? []).map((v) => ({
340
+ Key: v.Key,
341
+ VersionId: v.VersionId
342
+ })), ...(listVersionsResponse.DeleteMarkers ?? []).map((dm) => ({
343
+ Key: dm.Key,
344
+ VersionId: dm.VersionId
345
+ }))];
346
+ if (objectsToDelete.length > 0) yield* s3.deleteObjects({
347
+ Bucket: bucketName,
348
+ Delete: {
349
+ Objects: objectsToDelete,
350
+ Quiet: true
351
+ }
352
+ });
353
+ keyMarker = listVersionsResponse.NextKeyMarker;
354
+ versionIdMarker = listVersionsResponse.NextVersionIdMarker;
355
+ } while (keyMarker);
356
+ });
357
+ /**
358
+ * Bootstrap the AWS environment by creating the assets bucket.
359
+ *
360
+ * This is idempotent - running it multiple times is safe.
361
+ * The bucket is tagged and later discovered by tag lookup instead of by name.
362
+ */
363
+ const bootstrap = Effect.fn(function* () {
364
+ const region = yield* Region;
365
+ const existingBucket = yield* lookupAssetsBucket;
366
+ if (Option.isSome(existingBucket)) {
367
+ yield* ensureAssetsBucketTags(existingBucket.value, region);
368
+ yield* Effect.logInfo(`Assets bucket already exists: ${existingBucket.value}`);
369
+ return {
370
+ bucketName: existingBucket.value,
371
+ created: false
372
+ };
373
+ }
374
+ const { accountId } = yield* AWSEnvironment;
375
+ const bucketName = createAssetsBucketName(accountId, region);
376
+ yield* s3.createBucket({
377
+ Bucket: bucketName,
378
+ BucketNamespace: "account-regional",
379
+ CreateBucketConfiguration: {
380
+ Tags: createAssetsBucketTags(region),
381
+ ...region === "us-east-1" ? {} : { LocationConstraint: region }
382
+ }
383
+ }).pipe(Effect.catchTag("BucketAlreadyOwnedByYou", () => Effect.void), Effect.retry({
384
+ while: (e) => e._tag === "OperationAborted" || e._tag === "ServiceUnavailable",
385
+ schedule: Schedule.exponential(100)
386
+ }));
387
+ yield* s3.headBucket({ Bucket: bucketName }).pipe(Effect.retry({ schedule: Schedule.exponential(100).pipe(Schedule.both(Schedule.recurs(10))) }));
388
+ yield* Effect.logInfo(`Created assets bucket: ${bucketName}`);
389
+ return {
390
+ bucketName,
391
+ created: true
392
+ };
393
+ });
394
+ const destroyBootstrap = Effect.fn(function* () {
395
+ const bucketNames = yield* lookupAssetsBuckets;
396
+ for (const bucketName of bucketNames) {
397
+ yield* Effect.logInfo(`Destroying assets bucket: ${bucketName}`);
398
+ yield* deleteAllObjects(bucketName);
399
+ yield* s3.deleteBucket({ Bucket: bucketName }).pipe(Effect.retry({
400
+ while: (e) => e._tag === "OperationAborted" || e._tag === "ServiceUnavailable",
401
+ schedule: Schedule.exponential(100).pipe(Schedule.both(Schedule.recurs(10)))
402
+ }));
403
+ }
404
+ return {
405
+ bucketNames,
406
+ destroyed: bucketNames.length
407
+ };
408
+ });
409
+
410
+ //#endregion
411
+ //#region src/AWS/Credentials.ts
412
+ /**
413
+ * Lazy `Credentials` layer derived from the surrounding {@link AWSEnvironment}.
414
+ * Credentials are resolved on first access (not during layer construction),
415
+ * matching the existing @distilled.cloud/aws semantics.
416
+ */
417
+ const fromEnvironment$1 = Layer.effect(Credentials, Effect.map(AWSEnvironment.asEffect(), (env$2) => env$2.credentials));
418
+
419
+ //#endregion
420
+ //#region src/AWS/Region.ts
421
+ /**
422
+ * Derive the AWS region from the surrounding {@link AWSEnvironment}.
423
+ */
424
+ const fromEnvironment = Layer.effect(Region$1.Region, Effect.map(AWSEnvironment.asEffect(), (env$2) => env$2.region));
425
+
426
+ //#endregion
427
+ //#region src/Util/ConfigProvider.ts
428
+ const loadConfigProvider = (envFile$1) => {
429
+ if (Option.isSome(envFile$1)) return ConfigProvider.fromDotEnv({ path: envFile$1.value }).pipe(Effect.map((dotEnv) => ConfigProvider.orElse(dotEnv, ConfigProvider.fromEnv())));
430
+ return Effect.gen(function* () {
431
+ if (!(yield* (yield* FileSystem.FileSystem).exists(".env"))) return ConfigProvider.fromEnv();
432
+ return ConfigProvider.orElse(yield* ConfigProvider.fromDotEnv({ path: ".env" }), ConfigProvider.fromEnv());
433
+ });
434
+ };
435
+
436
+ //#endregion
437
+ //#region src/Util/FileLogger.ts
438
+ const fileLogger = Effect.fnUntraced(function* (...segments) {
439
+ const dotAlchemy$1 = yield* DotAlchemy;
440
+ const fs$2 = yield* FileSystem.FileSystem;
441
+ const path = yield* Path;
442
+ const logFile = path.join(dotAlchemy$1, "log", ...segments);
443
+ yield* fs$2.makeDirectory(path.dirname(logFile), { recursive: true });
444
+ return yield* Logger.formatLogFmt.pipe(Logger.toFile(logFile, { flag: "a" }));
445
+ });
446
+
447
+ //#endregion
448
+ //#region bin/commands/bootstrap.ts
449
+ const awsProfile = Flag$1.string("profile").pipe(Flag$1.withDescription("AWS profile to use for credentials"), Flag$1.optional, Flag$1.map(Option.getOrElse(() => "default")));
450
+ const awsRegion = Flag$1.string("region").pipe(Flag$1.withDescription("AWS region to bootstrap (defaults to AWS_REGION env var)"), Flag$1.optional, Flag$1.map(Option.getOrUndefined));
451
+ const bootstrapDestroy = Flag$1.boolean("destroy").pipe(Flag$1.withDescription("Destroy all bootstrap buckets in the selected region"), Flag$1.withDefault(false));
452
+ const bootstrapCommand = Command$1.make("bootstrap", {
453
+ envFile,
454
+ profile: awsProfile,
455
+ region: awsRegion,
456
+ destroy: bootstrapDestroy
457
+ }, Effect.fnUntraced(function* ({ envFile: envFile$1, profile: profile$1, region, destroy }) {
458
+ const logger = Logger.layer([fileLogger("bootstrap.txt")]);
459
+ return yield* Effect.gen(function* () {
460
+ const ssoProfile = yield* Auth.loadProfile(profile$1);
461
+ if (!ssoProfile.sso_account_id) return yield* Effect.die(`AWS SSO profile '${profile$1}' is missing sso_account_id`);
462
+ const ambient = yield* Effect.context();
463
+ const environment = makeEnvironment({
464
+ accountId: ssoProfile.sso_account_id,
465
+ region: region ?? ssoProfile.region ?? "us-east-1",
466
+ credentials: Auth.loadProfileCredentials(profile$1).pipe(Effect.provide(ambient)),
467
+ profile: profile$1
468
+ });
469
+ const awsLayers = Layer.provideMerge(Layer.mergeAll(fromEnvironment, fromEnvironment$1), environment);
470
+ return yield* Effect.gen(function* () {
471
+ const provider = yield* loadConfigProvider(envFile$1);
472
+ const bootstrapLayer = Layer.provide(awsLayers, Layer.succeed(ConfigProvider.ConfigProvider, provider));
473
+ if (destroy) {
474
+ yield* destroyBootstrap().pipe(Effect.tap((result) => result.destroyed === 0 ? Console.log("✓ No bootstrap buckets found to destroy") : Console.log(`✓ Destroyed ${result.destroyed} bootstrap bucket(s): ${result.bucketNames.join(", ")}`)), Effect.provide(bootstrapLayer));
475
+ return;
476
+ }
477
+ yield* bootstrap().pipe(Effect.tap(({ bucketName, created }) => created ? Console.log(`✓ Created assets bucket: ${bucketName}`) : Console.log(`✓ Assets bucket already exists: ${bucketName}`)), Effect.provide(bootstrapLayer));
478
+ });
479
+ }).pipe(Effect.provide(logger));
480
+ }));
73
481
 
74
482
  //#endregion
75
483
  //#region src/Artifacts.ts
@@ -126,11 +534,6 @@ const makeScopedArtifacts = (store, fqn) => {
126
534
  };
127
535
  };
128
536
  /**
129
- * Run an effect with a fresh artifact root, replacing any existing store.
130
- * Use this at top-level entrypoints that intentionally define a new deploy run.
131
- */
132
- const provideFreshArtifactStore = (effect) => effect.pipe(Effect.provideServiceEffect(ArtifactStore, Effect.sync(createArtifactStore)));
133
- /**
134
537
  * Ensure an artifact root exists, reusing the ambient store when one is already
135
538
  * present. This lets nested helpers participate in the same run-scoped cache.
136
539
  */
@@ -287,20 +690,23 @@ const Stack = Object.assign(taggedFunction(Context.Service()("Stack"), (stackNam
287
690
  id: stackName
288
691
  }) }) }))));
289
692
  const StackName = Stack.use((stack) => Effect.succeed(stack.name));
290
- const make$1 = (name, providers, stack) => (effect) => Effect.all([
693
+ const make$1 = (name, providers, stack) => (effect) => Effect.scope.pipe(Effect.flatMap((scope) => {
694
+ const stackLayer = Layer.effect(Stack, Stage.asEffect().pipe(Effect.map((stage$1) => stack ?? {
695
+ name,
696
+ stage: stage$1,
697
+ resources: {},
698
+ bindings: {}
699
+ }), Effect.tap(Effect.logInfo)));
700
+ return providers.pipe(Layer.provideMerge(stackLayer), Layer.buildWithScope(scope));
701
+ }), Effect.flatMap((context) => Effect.all([
291
702
  effect,
292
703
  Stack.asEffect(),
293
704
  Effect.context()
294
- ]).pipe(Effect.map(([output, stack$1, services]) => ({
705
+ ]).pipe(Effect.map(([output, stack$1, services$1]) => ({
295
706
  ...stack$1,
296
707
  output,
297
- services
298
- })), Effect.provide(providers), Effect.provideServiceEffect(Stack, Stage.asEffect().pipe(Effect.map((stage$1) => stack ?? {
299
- name,
300
- stage: stage$1,
301
- resources: {},
302
- bindings: {}
303
- }), Effect.tap(Effect.logInfo))));
708
+ services: services$1
709
+ })), Effect.provideContext(context))));
304
710
  const CurrentStack = Effect.serviceOption(Stack).asEffect().pipe(Effect.map(Option.getOrUndefined));
305
711
 
306
712
  //#endregion
@@ -576,6 +982,28 @@ const generateInstanceId = () => Effect.sync(() => {
576
982
 
577
983
  //#endregion
578
984
  //#region src/State/LocalState.ts
985
+ const REDACTED_MARKER = "__redacted__";
986
+ const encodeState = (value) => {
987
+ if (value === null || value === void 0) return value;
988
+ if (Redacted.isRedacted(value)) return { [REDACTED_MARKER]: encodeState(Redacted.value(value)) };
989
+ if (isResource(value)) return {
990
+ id: value.LogicalId,
991
+ type: value.Type,
992
+ props: encodeState(value.Props),
993
+ attr: encodeState(value.Attributes)
994
+ };
995
+ if (Array.isArray(value)) return value.map(encodeState);
996
+ if (typeof value === "object") {
997
+ const result = {};
998
+ for (const [k, v] of Object.entries(value)) result[k] = encodeState(v);
999
+ return result;
1000
+ }
1001
+ return value;
1002
+ };
1003
+ const reviveState = (_key, value) => {
1004
+ if (value !== null && typeof value === "object" && !Array.isArray(value) && REDACTED_MARKER in value) return Redacted.make(value[REDACTED_MARKER]);
1005
+ return value;
1006
+ };
579
1007
  const LocalState = Layer.effect(State, Effect.gen(function* () {
580
1008
  const fs$2 = yield* FileSystem.FileSystem;
581
1009
  const path = yield* Path$1.Path;
@@ -593,7 +1021,7 @@ const LocalState = Layer.effect(State, Effect.gen(function* () {
593
1021
  const state = {
594
1022
  listStacks: () => fs$2.readDirectory(stateDir).pipe(recover, Effect.map((files) => files ?? [])),
595
1023
  listStages: (stack) => fs$2.readDirectory(path.join(stateDir, stack)).pipe(recover, Effect.map((files) => files ?? [])),
596
- get: (request) => fs$2.readFile(resource(request)).pipe(Effect.map((file) => JSON.parse(file.toString())), recover),
1024
+ get: (request) => fs$2.readFile(resource(request)).pipe(Effect.map((file) => JSON.parse(file.toString(), reviveState)), recover),
597
1025
  getReplacedResources: Effect.fnUntraced(function* (request) {
598
1026
  return (yield* Effect.all((yield* state.list(request)).map((fqn) => state.get({
599
1027
  stack: request.stack,
@@ -601,15 +1029,7 @@ const LocalState = Layer.effect(State, Effect.gen(function* () {
601
1029
  fqn
602
1030
  })))).filter((r) => r?.status === "replaced");
603
1031
  }),
604
- set: (request) => ensure(stageDir(request)).pipe(Effect.flatMap(() => fs$2.writeFileString(resource(request), JSON.stringify(request.value, (k, v) => {
605
- if (isResource(v)) return {
606
- id: v.LogicalId,
607
- type: v.Type,
608
- props: v.Props,
609
- attr: v.Attributes
610
- };
611
- return v;
612
- }, 2))), recover, Effect.map(() => request.value)),
1032
+ set: (request) => ensure(stageDir(request)).pipe(Effect.flatMap(() => fs$2.writeFileString(resource(request), JSON.stringify(encodeState(request.value), null, 2))), recover, Effect.map(() => request.value)),
613
1033
  delete: (request) => fs$2.remove(resource(request)).pipe(recover),
614
1034
  list: (request) => fs$2.readDirectory(stageDir(request)).pipe(recover, Effect.map((files) => files?.map((file) => decodeFqn(file.replace(/\.json$/, ""))) ?? []))
615
1035
  };
@@ -619,7 +1039,7 @@ const LocalState = Layer.effect(State, Effect.gen(function* () {
619
1039
  //#endregion
620
1040
  //#region src/Apply.ts
621
1041
  const provideLifecycleScope = (fqn, instanceId) => (effect) => Effect.serviceOption(ArtifactStore).pipe(Effect.map(Option.getOrElse(createArtifactStore)), Effect.flatMap((store) => effect.pipe(Effect.provideService(Artifacts, makeScopedArtifacts(store, fqn)), Effect.provideService(InstanceId, instanceId))));
622
- const apply = (plan) => ensureArtifactStore(Effect.gen(function* () {
1042
+ const apply = (plan) => Effect.gen(function* () {
623
1043
  const session = yield* (yield* Cli).startApplySession(plan);
624
1044
  const state = yield* State;
625
1045
  const stack = yield* Stack;
@@ -640,7 +1060,7 @@ const apply = (plan) => ensureArtifactStore(Effect.gen(function* () {
640
1060
  if (!plan.output) return;
641
1061
  const outputs = Object.fromEntries(Object.entries(tracker).map(([fqn, t]) => [fqn, t.output]));
642
1062
  return yield* evaluate(plan.output, outputs);
643
- }));
1063
+ }).pipe(ensureArtifactStore);
644
1064
  const executePlan = Effect.fnUntraced(function* (plan, tracker, terminalStatuses, session, state, stackName, stage$1) {
645
1065
  const ready = Object.fromEntries(yield* Effect.all(Object.keys(plan.resources).map((fqn) => Effect.map(Deferred.make(), (d) => [fqn, d]))));
646
1066
  const getOutputs = () => Object.fromEntries(Object.entries(tracker).map(([fqn, t]) => [fqn, t.output]));
@@ -1217,170 +1637,494 @@ const excludeDeletedBindings = (bindings) => bindings.flatMap(({ action, sid, da
1217
1637
  }]);
1218
1638
 
1219
1639
  //#endregion
1220
- //#region src/AWS/Region.ts
1221
- const AWS_REGION = Config.string("AWS_REGION");
1640
+ //#region ../../node_modules/.bun/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs
1641
+ let _lazyMatch = () => {
1642
+ var __lib__ = (() => {
1643
+ var m = Object.defineProperty, V = Object.getOwnPropertyDescriptor, G = Object.getOwnPropertyNames, T = Object.prototype.hasOwnProperty, q = (r, e) => {
1644
+ for (var n in e) m(r, n, {
1645
+ get: e[n],
1646
+ enumerable: true
1647
+ });
1648
+ }, H = (r, e, n, a) => {
1649
+ if (e && typeof e == "object" || typeof e == "function") for (let t of G(e)) !T.call(r, t) && t !== n && m(r, t, {
1650
+ get: () => e[t],
1651
+ enumerable: !(a = V(e, t)) || a.enumerable
1652
+ });
1653
+ return r;
1654
+ }, J = (r) => H(m({}, "__esModule", { value: true }), r), w = {};
1655
+ q(w, { default: () => re$1 });
1656
+ var A = (r) => Array.isArray(r), d = (r) => typeof r == "function", Q = (r) => r.length === 0, W = (r) => typeof r == "number", K = (r) => typeof r == "object" && r !== null, X = (r) => r instanceof RegExp, b = (r) => typeof r == "string", h = (r) => r === void 0, Y = (r) => {
1657
+ const e = /* @__PURE__ */ new Map();
1658
+ return (n) => {
1659
+ const a = e.get(n);
1660
+ if (a) return a;
1661
+ const t = r(n);
1662
+ return e.set(n, t), t;
1663
+ };
1664
+ }, rr = (r, e, n = {}) => {
1665
+ const a = {
1666
+ cache: {},
1667
+ input: r,
1668
+ index: 0,
1669
+ indexMax: 0,
1670
+ options: n,
1671
+ output: []
1672
+ };
1673
+ if (v(e)(a) && a.index === r.length) return a.output;
1674
+ throw new Error(`Failed to parse at index ${a.indexMax}`);
1675
+ }, i = (r, e) => A(r) ? er(r, e) : b(r) ? ar(r, e) : nr(r, e), er = (r, e) => {
1676
+ const n = {};
1677
+ for (const a of r) {
1678
+ if (a.length !== 1) throw new Error(`Invalid character: "${a}"`);
1679
+ const t = a.charCodeAt(0);
1680
+ n[t] = true;
1681
+ }
1682
+ return (a) => {
1683
+ const t = a.index, o = a.input;
1684
+ for (; a.index < o.length && o.charCodeAt(a.index) in n;) a.index += 1;
1685
+ const u = a.index;
1686
+ if (u > t) {
1687
+ if (!h(e) && !a.options.silent) {
1688
+ const s = a.input.slice(t, u), c = d(e) ? e(s, o, String(t)) : e;
1689
+ h(c) || a.output.push(c);
1690
+ }
1691
+ a.indexMax = Math.max(a.indexMax, a.index);
1692
+ }
1693
+ return true;
1694
+ };
1695
+ }, nr = (r, e) => {
1696
+ const n = r.source, a = r.flags.replace(/y|$/, "y"), t = new RegExp(n, a);
1697
+ return g((o) => {
1698
+ t.lastIndex = o.index;
1699
+ const u = t.exec(o.input);
1700
+ if (u) {
1701
+ if (!h(e) && !o.options.silent) {
1702
+ const s = d(e) ? e(...u, o.input, String(o.index)) : e;
1703
+ h(s) || o.output.push(s);
1704
+ }
1705
+ return o.index += u[0].length, o.indexMax = Math.max(o.indexMax, o.index), true;
1706
+ } else return false;
1707
+ });
1708
+ }, ar = (r, e) => (n) => {
1709
+ if (n.input.startsWith(r, n.index)) {
1710
+ if (!h(e) && !n.options.silent) {
1711
+ const t = d(e) ? e(r, n.input, String(n.index)) : e;
1712
+ h(t) || n.output.push(t);
1713
+ }
1714
+ return n.index += r.length, n.indexMax = Math.max(n.indexMax, n.index), true;
1715
+ } else return false;
1716
+ }, C = (r, e, n, a) => {
1717
+ const t = v(r);
1718
+ return g(_(M((o) => {
1719
+ let u = 0;
1720
+ for (; u < n;) {
1721
+ const s = o.index;
1722
+ if (!t(o) || (u += 1, o.index === s)) break;
1723
+ }
1724
+ return u >= e;
1725
+ })));
1726
+ }, tr = (r, e) => C(r, 0, 1), f = (r, e) => C(r, 0, Infinity), x = (r, e) => {
1727
+ const n = r.map(v);
1728
+ return g(_(M((a) => {
1729
+ for (let t = 0, o = n.length; t < o; t++) if (!n[t](a)) return false;
1730
+ return true;
1731
+ })));
1732
+ }, l = (r, e) => {
1733
+ const n = r.map(v);
1734
+ return g(_((a) => {
1735
+ for (let t = 0, o = n.length; t < o; t++) if (n[t](a)) return true;
1736
+ return false;
1737
+ }));
1738
+ }, M = (r, e = false) => {
1739
+ const n = v(r);
1740
+ return (a) => {
1741
+ const t = a.index, o = a.output.length, u = n(a);
1742
+ return (!u || e) && (a.index = t, a.output.length !== o && (a.output.length = o)), u;
1743
+ };
1744
+ }, _ = (r, e) => {
1745
+ return v(r);
1746
+ }, g = (() => {
1747
+ let r = 0;
1748
+ return (e) => {
1749
+ const n = v(e), a = r += 1;
1750
+ return (t) => {
1751
+ var o;
1752
+ if (t.options.memoization === false) return n(t);
1753
+ const u = t.index, s = (o = t.cache)[a] || (o[a] = /* @__PURE__ */ new Map()), c = s.get(u);
1754
+ if (c === false) return false;
1755
+ if (W(c)) return t.index = c, true;
1756
+ if (c) return t.index = c.index, c.output?.length && t.output.push(...c.output), true;
1757
+ {
1758
+ const Z = t.output.length;
1759
+ if (n(t)) {
1760
+ const D = t.index, U = t.output.length;
1761
+ if (U > Z) {
1762
+ const ee = t.output.slice(Z, U);
1763
+ s.set(u, {
1764
+ index: D,
1765
+ output: ee
1766
+ });
1767
+ } else s.set(u, D);
1768
+ return true;
1769
+ } else return s.set(u, false), false;
1770
+ }
1771
+ };
1772
+ };
1773
+ })(), E = (r) => {
1774
+ let e;
1775
+ return (n) => (e || (e = v(r())), e(n));
1776
+ }, v = Y((r) => {
1777
+ if (d(r)) return Q(r) ? E(r) : r;
1778
+ if (b(r) || X(r)) return i(r);
1779
+ if (A(r)) return x(r);
1780
+ if (K(r)) return l(Object.values(r));
1781
+ throw new Error("Invalid rule");
1782
+ }), P = "abcdefghijklmnopqrstuvwxyz", ir = (r) => {
1783
+ let e = "";
1784
+ for (; r > 0;) e = P[(r - 1) % 26] + e, r = Math.floor((r - 1) / 26);
1785
+ return e;
1786
+ }, O = (r) => {
1787
+ let e = 0;
1788
+ for (let n = 0, a = r.length; n < a; n++) e = e * 26 + P.indexOf(r[n]) + 1;
1789
+ return e;
1790
+ }, S = (r, e) => {
1791
+ if (e < r) return S(e, r);
1792
+ const n = [];
1793
+ for (; r <= e;) n.push(r++);
1794
+ return n;
1795
+ }, or = (r, e, n) => S(r, e).map((a) => String(a).padStart(n, "0")), R = (r, e) => S(O(r), O(e)).map(ir), p = (r) => r, z = (r) => ur((e) => rr(e, r, { memoization: false }).join("")), ur = (r) => {
1796
+ const e = {};
1797
+ return (n) => e[n] ?? (e[n] = r(n));
1798
+ }, sr = i(/^\*\*\/\*$/, ".*"), cr = i(/^\*\*\/(\*)?([ a-zA-Z0-9._-]+)$/, (r, e, n) => `.*${e ? "" : "(?:^|/)"}${n.replaceAll(".", "\\.")}`), lr = i(/^\*\*\/(\*)?([ a-zA-Z0-9._-]*)\{([ a-zA-Z0-9._-]+(?:,[ a-zA-Z0-9._-]+)*)\}$/, (r, e, n, a) => `.*${e ? "" : "(?:^|/)"}${n.replaceAll(".", "\\.")}(?:${a.replaceAll(",", "|").replaceAll(".", "\\.")})`), y = i(/\\./, p), pr = i(/[$.*+?^(){}[\]\|]/, (r) => `\\${r}`), vr = i(/./, p), fr = l([i(/^(?:!!)*!(.*)$/, (r, e) => `(?!^${L(e)}$).*?`), i(/^(!!)+/, "")]), j = l([
1799
+ i(/\/(\*\*\/)+/, "(?:/.+/|/)"),
1800
+ i(/^(\*\*\/)+/, "(?:^|.*/)"),
1801
+ i(/\/(\*\*)$/, "(?:/.*|$)"),
1802
+ i(/\*\*/, ".*")
1803
+ ]), N = l([i(/\*\/(?!\*\*\/)/, "[^/]*/"), i(/\*/, "[^/]*")]), k = i("?", "[^/]"), $r = i("[", p), wr = i("]", p), Ar = i(/[!^]/, "^/"), br = i(/[a-z]-[a-z]|[0-9]-[0-9]/i, p), Er = l([
1804
+ y,
1805
+ i(/[$.*+?^(){}[\|]/, (r) => `\\${r}`),
1806
+ br,
1807
+ i(/[^\]]/, p)
1808
+ ]), B = x([
1809
+ $r,
1810
+ tr(Ar),
1811
+ f(Er),
1812
+ wr
1813
+ ]), Pr = i("{", "(?:"), Or = i("}", ")"), I = x([
1814
+ Pr,
1815
+ l([
1816
+ i(/(\d+)\.\.(\d+)/, (r, e, n) => or(+e, +n, Math.min(e.length, n.length)).join("|")),
1817
+ i(/([a-z]+)\.\.([a-z]+)/, (r, e, n) => R(e, n).join("|")),
1818
+ i(/([A-Z]+)\.\.([A-Z]+)/, (r, e, n) => R(e.toLowerCase(), n.toLowerCase()).join("|").toUpperCase())
1819
+ ]),
1820
+ Or
1821
+ ]), kr = i("{", "(?:"), Br = i("}", ")"), Ir = i(",", "|"), Fr = i(/[$.*+?^(){[\]\|]/, (r) => `\\${r}`), Lr = i(/[^}]/, p), F = x([
1822
+ kr,
1823
+ f(l([
1824
+ j,
1825
+ N,
1826
+ k,
1827
+ B,
1828
+ I,
1829
+ E(() => F),
1830
+ y,
1831
+ Fr,
1832
+ Ir,
1833
+ Lr
1834
+ ])),
1835
+ Br
1836
+ ]), L = z(f(l([
1837
+ sr,
1838
+ cr,
1839
+ lr,
1840
+ fr,
1841
+ j,
1842
+ N,
1843
+ k,
1844
+ B,
1845
+ I,
1846
+ F,
1847
+ y,
1848
+ pr,
1849
+ vr
1850
+ ]))), Tr = i(/\\./, p), qr = i(/./, p), Yr = z(f(l([
1851
+ Tr,
1852
+ i(/\*\*\*+/, "*"),
1853
+ i(/([^/{[(!])\*\*/, (r, e) => `${e}*`),
1854
+ i(/(^|.)\*\*(?=[^*/)\]}])/, (r, e) => `${e}*`),
1855
+ qr
1856
+ ]))), $ = (r, e) => {
1857
+ const n = Array.isArray(r) ? r : [r];
1858
+ if (!n.length) return false;
1859
+ const a = n.map($.compile), t = n.every((s) => /(\/(?:\*\*)?|\[\/\])$/.test(s)), o = e.replace(/[\\\/]+/g, "/").replace(/\/$/, t ? "/" : "");
1860
+ return a.some((s) => s.test(o));
1861
+ };
1862
+ $.compile = (r) => new RegExp(`^${L(Yr(r))}$`, "s");
1863
+ var re$1 = $;
1864
+ return J(w);
1865
+ })();
1866
+ return __lib__.default || __lib__;
1867
+ };
1868
+ let _match;
1869
+ const zeptomatch = (path, pattern) => {
1870
+ if (!_match) {
1871
+ _match = _lazyMatch();
1872
+ _lazyMatch = null;
1873
+ }
1874
+ return _match(path, pattern);
1875
+ };
1876
+ const _DRIVE_LETTER_START_RE = /^[A-Za-z]:\//;
1877
+ function normalizeWindowsPath(input = "") {
1878
+ if (!input) return input;
1879
+ return input.replace(/\\/g, "/").replace(_DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
1880
+ }
1881
+ const _UNC_REGEX = /^[/\\]{2}/;
1882
+ const _IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Za-z]:[/\\]/;
1883
+ const _DRIVE_LETTER_RE = /^[A-Za-z]:$/;
1884
+ const _ROOT_FOLDER_RE = /^\/([A-Za-z]:)?$/;
1885
+ const _EXTNAME_RE = /.(\.[^./]+|\.)$/;
1886
+ const _PATH_ROOT_RE = /^[/\\]|^[a-zA-Z]:[/\\]/;
1887
+ const sep = "/";
1888
+ const normalize = function(path) {
1889
+ if (path.length === 0) return ".";
1890
+ path = normalizeWindowsPath(path);
1891
+ const isUNCPath = path.match(_UNC_REGEX);
1892
+ const isPathAbsolute = isAbsolute(path);
1893
+ const trailingSeparator = path[path.length - 1] === "/";
1894
+ path = normalizeString(path, !isPathAbsolute);
1895
+ if (path.length === 0) {
1896
+ if (isPathAbsolute) return "/";
1897
+ return trailingSeparator ? "./" : ".";
1898
+ }
1899
+ if (trailingSeparator) path += "/";
1900
+ if (_DRIVE_LETTER_RE.test(path)) path += "/";
1901
+ if (isUNCPath) {
1902
+ if (!isPathAbsolute) return `//./${path}`;
1903
+ return `//${path}`;
1904
+ }
1905
+ return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
1906
+ };
1907
+ const join = function(...segments) {
1908
+ let path = "";
1909
+ for (const seg of segments) {
1910
+ if (!seg) continue;
1911
+ if (path.length > 0) {
1912
+ const pathTrailing = path[path.length - 1] === "/";
1913
+ const segLeading = seg[0] === "/";
1914
+ if (pathTrailing && segLeading) path += seg.slice(1);
1915
+ else path += pathTrailing || segLeading ? seg : `/${seg}`;
1916
+ } else path += seg;
1917
+ }
1918
+ return normalize(path);
1919
+ };
1920
+ function cwd$2() {
1921
+ if (typeof process !== "undefined" && typeof process.cwd === "function") return process.cwd().replace(/\\/g, "/");
1922
+ return "/";
1923
+ }
1924
+ const resolve = function(...arguments_) {
1925
+ arguments_ = arguments_.map((argument) => normalizeWindowsPath(argument));
1926
+ let resolvedPath = "";
1927
+ let resolvedAbsolute = false;
1928
+ for (let index = arguments_.length - 1; index >= -1 && !resolvedAbsolute; index--) {
1929
+ const path = index >= 0 ? arguments_[index] : cwd$2();
1930
+ if (!path || path.length === 0) continue;
1931
+ resolvedPath = `${path}/${resolvedPath}`;
1932
+ resolvedAbsolute = isAbsolute(path);
1933
+ }
1934
+ resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute);
1935
+ if (resolvedAbsolute && !isAbsolute(resolvedPath)) return `/${resolvedPath}`;
1936
+ return resolvedPath.length > 0 ? resolvedPath : ".";
1937
+ };
1938
+ function normalizeString(path, allowAboveRoot) {
1939
+ let res = "";
1940
+ let lastSegmentLength = 0;
1941
+ let lastSlash = -1;
1942
+ let dots = 0;
1943
+ let char = null;
1944
+ for (let index = 0; index <= path.length; ++index) {
1945
+ if (index < path.length) char = path[index];
1946
+ else if (char === "/") break;
1947
+ else char = "/";
1948
+ if (char === "/") {
1949
+ if (lastSlash === index - 1 || dots === 1);
1950
+ else if (dots === 2) {
1951
+ if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
1952
+ if (res.length > 2) {
1953
+ const lastSlashIndex = res.lastIndexOf("/");
1954
+ if (lastSlashIndex === -1) {
1955
+ res = "";
1956
+ lastSegmentLength = 0;
1957
+ } else {
1958
+ res = res.slice(0, lastSlashIndex);
1959
+ lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
1960
+ }
1961
+ lastSlash = index;
1962
+ dots = 0;
1963
+ continue;
1964
+ } else if (res.length > 0) {
1965
+ res = "";
1966
+ lastSegmentLength = 0;
1967
+ lastSlash = index;
1968
+ dots = 0;
1969
+ continue;
1970
+ }
1971
+ }
1972
+ if (allowAboveRoot) {
1973
+ res += res.length > 0 ? "/.." : "..";
1974
+ lastSegmentLength = 2;
1975
+ }
1976
+ } else {
1977
+ if (res.length > 0) res += `/${path.slice(lastSlash + 1, index)}`;
1978
+ else res = path.slice(lastSlash + 1, index);
1979
+ lastSegmentLength = index - lastSlash - 1;
1980
+ }
1981
+ lastSlash = index;
1982
+ dots = 0;
1983
+ } else if (char === "." && dots !== -1) ++dots;
1984
+ else dots = -1;
1985
+ }
1986
+ return res;
1987
+ }
1988
+ const isAbsolute = function(p) {
1989
+ return _IS_ABSOLUTE_RE.test(p);
1990
+ };
1991
+ const toNamespacedPath = function(p) {
1992
+ return normalizeWindowsPath(p);
1993
+ };
1994
+ const extname = function(p) {
1995
+ if (p === "..") return "";
1996
+ const match = _EXTNAME_RE.exec(normalizeWindowsPath(p));
1997
+ return match && match[1] || "";
1998
+ };
1999
+ const relative = function(from, to) {
2000
+ const _from = resolve(from).replace(_ROOT_FOLDER_RE, "$1").split("/");
2001
+ const _to = resolve(to).replace(_ROOT_FOLDER_RE, "$1").split("/");
2002
+ if (_to[0][1] === ":" && _from[0][1] === ":" && _from[0] !== _to[0]) return _to.join("/");
2003
+ const _fromCopy = [..._from];
2004
+ for (const segment of _fromCopy) {
2005
+ if (_to[0] !== segment) break;
2006
+ _from.shift();
2007
+ _to.shift();
2008
+ }
2009
+ return [..._from.map(() => ".."), ..._to].join("/");
2010
+ };
2011
+ const dirname = function(p) {
2012
+ const segments = normalizeWindowsPath(p).replace(/\/$/, "").split("/").slice(0, -1);
2013
+ if (segments.length === 1 && _DRIVE_LETTER_RE.test(segments[0])) segments[0] += "/";
2014
+ return segments.join("/") || (isAbsolute(p) ? "/" : ".");
2015
+ };
2016
+ const format$2 = function(p) {
2017
+ const ext = p.ext ? p.ext.startsWith(".") ? p.ext : `.${p.ext}` : "";
2018
+ const segments = [
2019
+ p.root,
2020
+ p.dir,
2021
+ p.base ?? (p.name ?? "") + ext
2022
+ ].filter(Boolean);
2023
+ return normalizeWindowsPath(p.root ? resolve(...segments) : segments.join("/"));
2024
+ };
2025
+ const basename = function(p, extension$2) {
2026
+ const segments = normalizeWindowsPath(p).split("/");
2027
+ let lastSegment = "";
2028
+ for (let i = segments.length - 1; i >= 0; i--) {
2029
+ const val = segments[i];
2030
+ if (val) {
2031
+ lastSegment = val;
2032
+ break;
2033
+ }
2034
+ }
2035
+ return extension$2 && lastSegment.endsWith(extension$2) ? lastSegment.slice(0, -extension$2.length) : lastSegment;
2036
+ };
2037
+ const parse$3 = function(p) {
2038
+ const root$1 = _PATH_ROOT_RE.exec(p)?.[0]?.replace(/\\/g, "/") || "";
2039
+ const base = basename(p);
2040
+ const extension$2 = extname(base);
2041
+ return {
2042
+ root: root$1,
2043
+ dir: dirname(p),
2044
+ base,
2045
+ ext: extension$2,
2046
+ name: base.slice(0, base.length - extension$2.length)
2047
+ };
2048
+ };
2049
+ const matchesGlob = (path, pattern) => {
2050
+ return zeptomatch(pattern, normalize(path));
2051
+ };
2052
+ const _path = {
2053
+ __proto__: null,
2054
+ basename,
2055
+ dirname,
2056
+ extname,
2057
+ format: format$2,
2058
+ isAbsolute,
2059
+ join,
2060
+ matchesGlob,
2061
+ normalize,
2062
+ normalizeString,
2063
+ parse: parse$3,
2064
+ relative,
2065
+ resolve,
2066
+ sep,
2067
+ toNamespacedPath
2068
+ };
1222
2069
 
1223
2070
  //#endregion
1224
- //#region src/AWS/Account.ts
1225
- var Account = class extends Context.Service()("AWS::AccountID") {};
2071
+ //#region ../../node_modules/.bun/pathe@2.0.3/node_modules/pathe/dist/index.mjs
2072
+ const delimiter = /* @__PURE__ */ (() => globalThis.process?.platform === "win32" ? ";" : ":")();
2073
+ const _platforms = {
2074
+ posix: void 0,
2075
+ win32: void 0
2076
+ };
2077
+ const mix = (del = delimiter) => {
2078
+ return new Proxy(_path, { get(_, prop) {
2079
+ if (prop === "delimiter") return del;
2080
+ if (prop === "posix") return posix;
2081
+ if (prop === "win32") return win32;
2082
+ return _platforms[prop] || _path[prop];
2083
+ } });
2084
+ };
2085
+ const posix = /* @__PURE__ */ mix(":");
2086
+ const win32 = /* @__PURE__ */ mix(";");
1226
2087
 
1227
2088
  //#endregion
1228
- //#region src/AWS/Bootstrap.ts
1229
- /**
1230
- * Tag key used to identify the alchemy assets bucket.
1231
- */
1232
- const ASSETS_BUCKET_TAG = "alchemy::assets-bucket";
2089
+ //#region src/Auth/Profile.ts
2090
+ const rootDir = posix.join(os.homedir(), ".alchemy");
2091
+ const configFilePath = posix.join(rootDir, "profiles.json");
1233
2092
  /**
1234
- * Tag key used to scope the alchemy assets bucket to an AWS region.
2093
+ * Config key consulted by the various `fromAuthProvider` /
2094
+ * `fromEnvironment` layers to pick which named profile in
2095
+ * `~/.alchemy/profiles.json` to use. Defaults to `"default"`.
1235
2096
  */
1236
- const ASSETS_BUCKET_REGION_TAG = "alchemy::assets-bucket-region";
1237
- const createAssetsBucketName = (region) => `alchemy-assets-${region}-${crypto.randomUUID().replaceAll("-", "").slice(0, 16)}`.toLowerCase();
1238
- const createAssetsBucketTags = (region) => [{
1239
- Key: ASSETS_BUCKET_TAG,
1240
- Value: "true"
1241
- }, {
1242
- Key: ASSETS_BUCKET_REGION_TAG,
1243
- Value: region
1244
- }];
1245
- const getBucketTags = (bucketName) => s3.getBucketTagging({ Bucket: bucketName }).pipe(Effect.map((response) => response.TagSet ?? []), Effect.catchTag("NoSuchTagSet", () => Effect.succeed([])));
1246
- const hasAssetsBucketTag = (tags) => tags.some((tag) => tag.Key === ASSETS_BUCKET_TAG && tag.Value === "true");
1247
- const normalizeBucketRegion = (location) => {
1248
- if (!location) return "us-east-1";
1249
- if (location === "EU") return "eu-west-1";
1250
- return location;
1251
- };
1252
- const bucketMatchesRegion = (tags, region) => {
1253
- const taggedRegion = tags.find((tag) => tag.Key === ASSETS_BUCKET_REGION_TAG)?.Value;
1254
- return taggedRegion === void 0 ? void 0 : taggedRegion === region;
1255
- };
1256
- const lookupAssetsBuckets = Effect.gen(function* () {
1257
- const region = yield* Region;
1258
- const buckets = (yield* s3.listBuckets({})).Buckets ?? [];
1259
- const matchingBuckets = [];
1260
- for (const bucket of buckets) {
1261
- const bucketName = bucket.Name;
1262
- if (!bucketName) continue;
1263
- const tags = yield* getBucketTags(bucketName).pipe(Effect.catch(() => Effect.succeed([])));
1264
- if (!hasAssetsBucketTag(tags)) continue;
1265
- const taggedRegionMatch = bucketMatchesRegion(tags, region);
1266
- if (taggedRegionMatch === true) {
1267
- matchingBuckets.push(bucketName);
1268
- continue;
1269
- }
1270
- if (taggedRegionMatch === false) continue;
1271
- if ((yield* s3.getBucketLocation({ Bucket: bucketName }).pipe(Effect.map((response) => normalizeBucketRegion(response.LocationConstraint)), Effect.catch(() => Effect.succeed(void 0)))) === region) matchingBuckets.push(bucketName);
1272
- }
1273
- return matchingBuckets;
1274
- });
1275
- const lookupAssetsBucket = Effect.gen(function* () {
1276
- const matchingBuckets = yield* lookupAssetsBuckets;
1277
- for (const bucketName of matchingBuckets) return Option.some(bucketName);
1278
- return Option.none();
1279
- });
1280
- const ensureAssetsBucketTags = Effect.fn(function* (bucketName, region) {
1281
- const tagSet = [...(yield* getBucketTags(bucketName)).filter((tag) => tag.Key !== ASSETS_BUCKET_TAG && tag.Key !== ASSETS_BUCKET_REGION_TAG), ...createAssetsBucketTags(region)];
1282
- yield* s3.putBucketTagging({
1283
- Bucket: bucketName,
1284
- Tagging: { TagSet: tagSet.map((tag) => ({
1285
- Key: tag.Key,
1286
- Value: tag.Value
1287
- })) }
1288
- });
1289
- });
1290
- const deleteAllObjects = Effect.fn(function* (bucketName) {
1291
- let continuationToken;
1292
- do {
1293
- const listResponse = yield* s3.listObjectsV2({
1294
- Bucket: bucketName,
1295
- ContinuationToken: continuationToken
1296
- });
1297
- if (listResponse.Contents && listResponse.Contents.length > 0) yield* s3.deleteObjects({
1298
- Bucket: bucketName,
1299
- Delete: {
1300
- Objects: listResponse.Contents.map((obj) => ({ Key: obj.Key })),
1301
- Quiet: true
1302
- }
1303
- });
1304
- continuationToken = listResponse.NextContinuationToken;
1305
- } while (continuationToken);
1306
- let keyMarker;
1307
- let versionIdMarker;
1308
- do {
1309
- const listVersionsResponse = yield* s3.listObjectVersions({
1310
- Bucket: bucketName,
1311
- KeyMarker: keyMarker,
1312
- VersionIdMarker: versionIdMarker
1313
- });
1314
- const objectsToDelete = [...(listVersionsResponse.Versions ?? []).map((v) => ({
1315
- Key: v.Key,
1316
- VersionId: v.VersionId
1317
- })), ...(listVersionsResponse.DeleteMarkers ?? []).map((dm) => ({
1318
- Key: dm.Key,
1319
- VersionId: dm.VersionId
1320
- }))];
1321
- if (objectsToDelete.length > 0) yield* s3.deleteObjects({
1322
- Bucket: bucketName,
1323
- Delete: {
1324
- Objects: objectsToDelete,
1325
- Quiet: true
1326
- }
1327
- });
1328
- keyMarker = listVersionsResponse.NextKeyMarker;
1329
- versionIdMarker = listVersionsResponse.NextVersionIdMarker;
1330
- } while (keyMarker);
2097
+ const ALCHEMY_PROFILE = Config.string("ALCHEMY_PROFILE").pipe(Config.withDefault("default"));
2098
+ const CONFIG_VERSION = 0;
2099
+ const emptyConfig = () => ({
2100
+ version: CONFIG_VERSION,
2101
+ profiles: {}
1331
2102
  });
2103
+ const readConfig = FileSystem.FileSystem.asEffect().pipe(Effect.flatMap((fs$2) => fs$2.readFileString(configFilePath)), Effect.flatMap((data) => Effect.try({
2104
+ try: () => {
2105
+ const parsed = JSON.parse(data);
2106
+ if (parsed?.version !== CONFIG_VERSION) return emptyConfig();
2107
+ return parsed;
2108
+ },
2109
+ catch: emptyConfig
2110
+ })), Effect.orElseSucceed(emptyConfig));
2111
+ const writeConfig = (config) => FileSystem.FileSystem.asEffect().pipe(Effect.tap((fs$2) => fs$2.makeDirectory(posix.dirname(configFilePath), { recursive: true })), Effect.flatMap((fs$2) => fs$2.writeFileString(configFilePath, JSON.stringify(config, null, 2))));
2112
+ const getProfile = (name) => readConfig.pipe(Effect.map((config) => config.profiles[name]));
2113
+ const setProfile = (name, profile$1) => readConfig.pipe(Effect.tap((config) => Effect.sync(() => config.profiles[name] = profile$1)), Effect.flatMap(writeConfig));
1332
2114
  /**
1333
- * Bootstrap the AWS environment by creating the assets bucket.
2115
+ * Returns a `ConfigProvider` that overrides `ALCHEMY_PROFILE` with the
2116
+ * given `profile` (when explicitly passed via the CLI `--profile` flag),
2117
+ * falling through to `base` for everything else.
1334
2118
  *
1335
- * This is idempotent - running it multiple times is safe.
1336
- * The bucket is tagged and later discovered by tag lookup instead of by name.
2119
+ * Use this to let the CLI's `--profile <name>` win over `$ALCHEMY_PROFILE`
2120
+ * without disturbing other config lookups.
1337
2121
  */
1338
- const bootstrap = Effect.fn(function* () {
1339
- const region = yield* Region;
1340
- const existingBucket = yield* lookupAssetsBucket;
1341
- if (Option.isSome(existingBucket)) {
1342
- yield* ensureAssetsBucketTags(existingBucket.value, region);
1343
- yield* Effect.logInfo(`Assets bucket already exists: ${existingBucket.value}`);
1344
- return {
1345
- bucketName: existingBucket.value,
1346
- created: false
1347
- };
1348
- }
1349
- const bucketName = createAssetsBucketName(region);
1350
- if (region === "us-east-1") yield* s3.createBucket({ Bucket: bucketName }).pipe(Effect.retry({
1351
- while: (e) => e._tag === "OperationAborted" || e._tag === "ServiceUnavailable",
1352
- schedule: Schedule.exponential(100)
1353
- }));
1354
- else yield* s3.createBucket({
1355
- Bucket: bucketName,
1356
- CreateBucketConfiguration: { LocationConstraint: region }
1357
- }).pipe(Effect.catchTag("BucketAlreadyOwnedByYou", () => Effect.void), Effect.retry({
1358
- while: (e) => e._tag === "OperationAborted" || e._tag === "ServiceUnavailable",
1359
- schedule: Schedule.exponential(100)
1360
- }));
1361
- yield* s3.headBucket({ Bucket: bucketName }).pipe(Effect.retry({ schedule: Schedule.exponential(100).pipe(Schedule.both(Schedule.recurs(10))) }));
1362
- yield* ensureAssetsBucketTags(bucketName, region);
1363
- yield* Effect.logInfo(`Created assets bucket: ${bucketName}`);
1364
- return {
1365
- bucketName,
1366
- created: true
1367
- };
1368
- });
1369
- const destroyBootstrap = Effect.fn(function* () {
1370
- const bucketNames = yield* lookupAssetsBuckets;
1371
- for (const bucketName of bucketNames) {
1372
- yield* Effect.logInfo(`Destroying assets bucket: ${bucketName}`);
1373
- yield* deleteAllObjects(bucketName);
1374
- yield* s3.deleteBucket({ Bucket: bucketName }).pipe(Effect.retry({
1375
- while: (e) => e._tag === "OperationAborted" || e._tag === "ServiceUnavailable",
1376
- schedule: Schedule.exponential(100).pipe(Schedule.both(Schedule.recurs(10)))
1377
- }));
1378
- }
1379
- return {
1380
- bucketNames,
1381
- destroyed: bucketNames.length
1382
- };
1383
- });
2122
+ const withProfileOverride = (base, profile$1) => {
2123
+ if (profile$1 === void 0) return base;
2124
+ const overrides = { ALCHEMY_PROFILE: profile$1 };
2125
+ const overrideProvider = ConfigProvider.make((path) => Effect.succeed(path.length === 1 && typeof path[0] === "string" && path[0] in overrides ? ConfigProvider.makeValue(overrides[path[0]]) : void 0));
2126
+ return ConfigProvider.orElse(base)(overrideProvider);
2127
+ };
1384
2128
 
1385
2129
  //#endregion
1386
2130
  //#region ../../node_modules/.bun/react@19.2.5/node_modules/react/cjs/react.production.js
@@ -2048,19 +2792,19 @@ var require_react_development = /* @__PURE__ */ __commonJS({ "../../node_modules
2048
2792
  prevActScopeDepth !== actScopeDepth - 1 && console.error("You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one. ");
2049
2793
  actScopeDepth = prevActScopeDepth;
2050
2794
  }
2051
- function recursivelyFlushAsyncActWork(returnValue, resolve, reject) {
2795
+ function recursivelyFlushAsyncActWork(returnValue, resolve$1, reject) {
2052
2796
  var queue = ReactSharedInternals$1.actQueue;
2053
2797
  if (null !== queue) if (0 !== queue.length) try {
2054
2798
  flushActQueue(queue);
2055
2799
  enqueueTask(function() {
2056
- return recursivelyFlushAsyncActWork(returnValue, resolve, reject);
2800
+ return recursivelyFlushAsyncActWork(returnValue, resolve$1, reject);
2057
2801
  });
2058
2802
  return;
2059
2803
  } catch (error) {
2060
2804
  ReactSharedInternals$1.thrownErrors.push(error);
2061
2805
  }
2062
2806
  else ReactSharedInternals$1.actQueue = null;
2063
- 0 < ReactSharedInternals$1.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals$1.thrownErrors), ReactSharedInternals$1.thrownErrors.length = 0, reject(queue)) : resolve(returnValue);
2807
+ 0 < ReactSharedInternals$1.thrownErrors.length ? (queue = aggregateErrors(ReactSharedInternals$1.thrownErrors), ReactSharedInternals$1.thrownErrors.length = 0, reject(queue)) : resolve$1(returnValue);
2064
2808
  }
2065
2809
  function flushActQueue(queue) {
2066
2810
  if (!isFlushing) {
@@ -2221,14 +2965,14 @@ var require_react_development = /* @__PURE__ */ __commonJS({ "../../node_modules
2221
2965
  queueSeveralMicrotasks(function() {
2222
2966
  didAwaitActCall || didWarnNoAwaitAct || (didWarnNoAwaitAct = !0, console.error("You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);"));
2223
2967
  });
2224
- return { then: function(resolve, reject) {
2968
+ return { then: function(resolve$1, reject) {
2225
2969
  didAwaitActCall = !0;
2226
2970
  thenable.then(function(returnValue) {
2227
2971
  popActScope(prevActQueue, prevActScopeDepth);
2228
2972
  if (0 === prevActScopeDepth) {
2229
2973
  try {
2230
2974
  flushActQueue(queue), enqueueTask(function() {
2231
- return recursivelyFlushAsyncActWork(returnValue, resolve, reject);
2975
+ return recursivelyFlushAsyncActWork(returnValue, resolve$1, reject);
2232
2976
  });
2233
2977
  } catch (error$0) {
2234
2978
  ReactSharedInternals$1.thrownErrors.push(error$0);
@@ -2238,7 +2982,7 @@ var require_react_development = /* @__PURE__ */ __commonJS({ "../../node_modules
2238
2982
  ReactSharedInternals$1.thrownErrors.length = 0;
2239
2983
  reject(_thrownError);
2240
2984
  }
2241
- } else resolve(returnValue);
2985
+ } else resolve$1(returnValue);
2242
2986
  }, function(error) {
2243
2987
  popActScope(prevActQueue, prevActScopeDepth);
2244
2988
  0 < ReactSharedInternals$1.thrownErrors.length ? (error = aggregateErrors(ReactSharedInternals$1.thrownErrors), ReactSharedInternals$1.thrownErrors.length = 0, reject(error)) : reject(error);
@@ -2251,11 +2995,11 @@ var require_react_development = /* @__PURE__ */ __commonJS({ "../../node_modules
2251
2995
  didAwaitActCall || didWarnNoAwaitAct || (didWarnNoAwaitAct = !0, console.error("A component suspended inside an `act` scope, but the `act` call was not awaited. When testing React components that depend on asynchronous data, you must await the result:\n\nawait act(() => ...)"));
2252
2996
  }), ReactSharedInternals$1.actQueue = null);
2253
2997
  if (0 < ReactSharedInternals$1.thrownErrors.length) throw callback = aggregateErrors(ReactSharedInternals$1.thrownErrors), ReactSharedInternals$1.thrownErrors.length = 0, callback;
2254
- return { then: function(resolve, reject) {
2998
+ return { then: function(resolve$1, reject) {
2255
2999
  didAwaitActCall = !0;
2256
3000
  0 === prevActScopeDepth ? (ReactSharedInternals$1.actQueue = queue, enqueueTask(function() {
2257
- return recursivelyFlushAsyncActWork(returnValue$jscomp$0, resolve, reject);
2258
- })) : resolve(returnValue$jscomp$0);
3001
+ return recursivelyFlushAsyncActWork(returnValue$jscomp$0, resolve$1, reject);
3002
+ })) : resolve$1(returnValue$jscomp$0);
2259
3003
  } };
2260
3004
  };
2261
3005
  exports.cache = function(fn) {
@@ -3092,7 +3836,7 @@ var loadYoga = (() => {
3092
3836
  function Ja(a) {
3093
3837
  a = Ka(a);
3094
3838
  var b = N(a);
3095
- S$1(a);
3839
+ S(a);
3096
3840
  return b;
3097
3841
  }
3098
3842
  function La(a, b) {
@@ -3910,7 +4654,7 @@ var loadYoga = (() => {
3910
4654
  for (k = 0; k < e; ++k) l[k] = String.fromCharCode(A[f + k]);
3911
4655
  l = l.join("");
3912
4656
  }
3913
- S$1(d);
4657
+ S(d);
3914
4658
  return l;
3915
4659
  },
3916
4660
  toWireType: function(d, e) {
@@ -3960,15 +4704,15 @@ var loadYoga = (() => {
3960
4704
  }
3961
4705
  f[g] = 0;
3962
4706
  }
3963
- } else if (g) for (g = 0; g < f; ++g) l = e.charCodeAt(g), 255 < l && (S$1(m), L("String has UTF-16 code units that do not fit in 8 bits")), A[m + g] = l;
4707
+ } else if (g) for (g = 0; g < f; ++g) l = e.charCodeAt(g), 255 < l && (S(m), L("String has UTF-16 code units that do not fit in 8 bits")), A[m + g] = l;
3964
4708
  else for (g = 0; g < f; ++g) A[m + g] = e[g];
3965
- null !== d && d.push(S$1, k);
4709
+ null !== d && d.push(S, k);
3966
4710
  return k;
3967
4711
  },
3968
4712
  argPackAdvance: 8,
3969
4713
  readValueFromPointer: Xa,
3970
4714
  V: function(d) {
3971
- S$1(d);
4715
+ S(d);
3972
4716
  }
3973
4717
  });
3974
4718
  },
@@ -3988,7 +4732,7 @@ var loadYoga = (() => {
3988
4732
  var t = m + 4 + u * b;
3989
4733
  if (u == l || 0 == n[t >> k]) r = d(r, t - r), void 0 === p ? p = r : (p += String.fromCharCode(0), p += r), r = t + b;
3990
4734
  }
3991
- S$1(m);
4735
+ S(m);
3992
4736
  return p;
3993
4737
  },
3994
4738
  toWireType: function(m, l) {
@@ -3996,13 +4740,13 @@ var loadYoga = (() => {
3996
4740
  var n = f(l), p = Ib(4 + n + b);
3997
4741
  E[p >> 2] = n >> k;
3998
4742
  e(l, p + 4, n + b);
3999
- null !== m && m.push(S$1, p);
4743
+ null !== m && m.push(S, p);
4000
4744
  return p;
4001
4745
  },
4002
4746
  argPackAdvance: 8,
4003
4747
  readValueFromPointer: Xa,
4004
4748
  V: function(m) {
4005
- S$1(m);
4749
+ S(m);
4006
4750
  }
4007
4751
  });
4008
4752
  },
@@ -4176,8 +4920,8 @@ var loadYoga = (() => {
4176
4920
  };
4177
4921
  var Ib = h._malloc = function() {
4178
4922
  return (Ib = h._malloc = h.asm.I).apply(null, arguments);
4179
- }, S$1 = h._free = function() {
4180
- return (S$1 = h._free = h.asm.K).apply(null, arguments);
4923
+ }, S = h._free = function() {
4924
+ return (S = h._free = h.asm.K).apply(null, arguments);
4181
4925
  };
4182
4926
  h.dynCall_jiji = function() {
4183
4927
  return (h.dynCall_jiji = h.asm.L).apply(null, arguments);
@@ -7024,8 +7768,8 @@ var require_react_reconciler_production = /* @__PURE__ */ __commonJS({ "../../no
7024
7768
  currentEntangledActionThenable = {
7025
7769
  status: "pending",
7026
7770
  value: void 0,
7027
- then: function(resolve) {
7028
- entangledListeners.push(resolve);
7771
+ then: function(resolve$1) {
7772
+ entangledListeners.push(resolve$1);
7029
7773
  }
7030
7774
  };
7031
7775
  }
@@ -7048,8 +7792,8 @@ var require_react_reconciler_production = /* @__PURE__ */ __commonJS({ "../../no
7048
7792
  status: "pending",
7049
7793
  value: null,
7050
7794
  reason: null,
7051
- then: function(resolve) {
7052
- listeners.push(resolve);
7795
+ then: function(resolve$1) {
7796
+ listeners.push(resolve$1);
7053
7797
  }
7054
7798
  };
7055
7799
  thenable.then(function() {
@@ -14131,8 +14875,8 @@ var require_react_reconciler_development = /* @__PURE__ */ __commonJS({ "../../n
14131
14875
  currentEntangledActionThenable = {
14132
14876
  status: "pending",
14133
14877
  value: void 0,
14134
- then: function(resolve) {
14135
- entangledListeners.push(resolve);
14878
+ then: function(resolve$1) {
14879
+ entangledListeners.push(resolve$1);
14136
14880
  }
14137
14881
  };
14138
14882
  }
@@ -14155,8 +14899,8 @@ var require_react_reconciler_development = /* @__PURE__ */ __commonJS({ "../../n
14155
14899
  status: "pending",
14156
14900
  value: null,
14157
14901
  reason: null,
14158
- then: function(resolve) {
14159
- listeners.push(resolve);
14902
+ then: function(resolve$1) {
14903
+ listeners.push(resolve$1);
14160
14904
  }
14161
14905
  };
14162
14906
  thenable.then(function() {
@@ -32682,11 +33426,11 @@ var require_backend = /* @__PURE__ */ __commonJS({ "../../node_modules/.bun/reac
32682
33426
  var componentInfo = getCurrentComponentInfo();
32683
33427
  if (componentInfo === null) return;
32684
33428
  if (args.length > 3 && typeof args[0] === "string" && args[0].startsWith("%c%s%c ") && typeof args[1] === "string" && typeof args[2] === "string" && typeof args[3] === "string") {
32685
- var format$2 = args[0].slice(7);
33429
+ var format$3 = args[0].slice(7);
32686
33430
  var env$2 = args[2].trim();
32687
33431
  args = args.slice(4);
32688
- if (env$2 !== componentInfo.env) args.unshift("[" + env$2 + "] " + format$2);
32689
- else args.unshift(format$2);
33432
+ if (env$2 !== componentInfo.env) args.unshift("[" + env$2 + "] " + format$3);
33433
+ else args.unshift(format$3);
32690
33434
  }
32691
33435
  var message = formatConsoleArgumentsToSingleString.apply(void 0, renderer_toConsumableArray(args));
32692
33436
  var componentLogsEntry = componentInfoToComponentLogsMap.get(componentInfo);
@@ -42130,10 +42874,10 @@ var require_stack_utils = /* @__PURE__ */ __commonJS({ "../../node_modules/.bun/
42130
42874
  return res;
42131
42875
  }
42132
42876
  };
42133
- function setFile(result, filename, cwd$2) {
42877
+ function setFile(result, filename, cwd$3) {
42134
42878
  if (filename) {
42135
42879
  filename = filename.replace(/\\/g, "/");
42136
- if (filename.startsWith(`${cwd$2}/`)) filename = filename.slice(cwd$2.length + 1);
42880
+ if (filename.startsWith(`${cwd$3}/`)) filename = filename.slice(cwd$3.length + 1);
42137
42881
  result.file = filename;
42138
42882
  }
42139
42883
  }
@@ -42976,8 +43720,8 @@ var Ink = class {
42976
43720
  else setImmediate(resolveOrReject);
42977
43721
  }
42978
43722
  async waitUntilExit() {
42979
- this.exitPromise ||= new Promise((resolve, reject) => {
42980
- this.resolveExitPromise = resolve;
43723
+ this.exitPromise ||= new Promise((resolve$1, reject) => {
43724
+ this.resolveExitPromise = resolve$1;
42981
43725
  this.rejectExitPromise = reject;
42982
43726
  });
42983
43727
  if (!this.beforeExitHandler) {
@@ -44362,16 +45106,6 @@ const startApplySession = Effect.fn(function* (plan) {
44362
45106
  };
44363
45107
  });
44364
45108
 
44365
- //#endregion
44366
- //#region src/Config.ts
44367
- var DotAlchemy = class extends Context.Service()(".alchemy") {};
44368
- const dotAlchemy = Layer.effect(DotAlchemy, Effect.gen(function* () {
44369
- const fs$2 = yield* FileSystem.FileSystem;
44370
- const dir = (yield* Path$1.Path).join(process.cwd(), ".alchemy");
44371
- yield* fs$2.makeDirectory(dir, { recursive: true });
44372
- return dir;
44373
- }));
44374
-
44375
45109
  //#endregion
44376
45110
  //#region src/Util/types.ts
44377
45111
  const asEffect = (effect) => Effect.isEffect(effect) ? effect : Effect.succeed(effect);
@@ -44703,224 +45437,114 @@ var DeleteResourceHasDownstreamDependencies = class extends Data.TaggedError("De
44703
45437
  var UnsatisfiedResourceCycle = class extends Data.TaggedError("UnsatisfiedResourceCycle") {};
44704
45438
 
44705
45439
  //#endregion
44706
- //#region src/Util/ConfigProvider.ts
44707
- const loadConfigProvider = (envFile$1) => {
44708
- if (Option.isSome(envFile$1)) return ConfigProvider.fromDotEnv({ path: envFile$1.value }).pipe(Effect.map((dotEnv) => ConfigProvider.orElse(dotEnv, ConfigProvider.fromEnv())));
44709
- return Effect.gen(function* () {
44710
- if (!(yield* (yield* FileSystem.FileSystem).exists(".env"))) return ConfigProvider.fromEnv();
44711
- return ConfigProvider.orElse(yield* ConfigProvider.fromDotEnv({ path: ".env" }), ConfigProvider.fromEnv());
44712
- });
44713
- };
44714
-
44715
- //#endregion
44716
- //#region src/Util/FileLogger.ts
44717
- const fileLogger = Effect.fnUntraced(function* (...segments) {
44718
- const dotAlchemy$1 = yield* DotAlchemy;
44719
- const fs$2 = yield* FileSystem.FileSystem;
44720
- const path = yield* Path;
44721
- const logFile = path.join(dotAlchemy$1, "log", ...segments);
44722
- yield* fs$2.makeDirectory(path.dirname(logFile), { recursive: true });
44723
- return yield* Logger.formatLogFmt.pipe(Logger.toFile(logFile, { flag: "a" }));
45440
+ //#region bin/commands/deploy.ts
45441
+ const execStack = Effect.fn(function* ({ main: main$1, stage: stage$1, envFile: envFile$1, profile: profile$1, dryRun: dryRun$1 = false, force: force$1 = false, yes: yes$1 = false, destroy = false }) {
45442
+ const stackEffect = yield* importStack(main$1);
45443
+ const services$1 = Layer.mergeAll(Layer.succeed(ArtifactStore, createArtifactStore()), Layer.succeed(AuthProviders, {}), ConfigProvider.layer(withProfileOverride(yield* loadConfigProvider(envFile$1), profile$1)), inkCLI(), Logger.layer([fileLogger("out")]), Layer.succeed(Stage, stage$1), LocalState);
45444
+ yield* Effect.gen(function* () {
45445
+ const cli$1 = yield* Cli;
45446
+ const stack = yield* stackEffect;
45447
+ yield* Effect.gen(function* () {
45448
+ const updatePlan = yield* make(destroy ? {
45449
+ ...stack,
45450
+ resources: {},
45451
+ bindings: {},
45452
+ output: {}
45453
+ } : stack, { force: force$1 });
45454
+ if (dryRun$1) yield* cli$1.displayPlan(updatePlan);
45455
+ else {
45456
+ if (!yes$1) {
45457
+ if (!(yield* cli$1.approvePlan(updatePlan))) return;
45458
+ }
45459
+ const outputs = yield* apply(updatePlan);
45460
+ yield* Console.log(outputs);
45461
+ }
45462
+ }).pipe(Effect.provide(stack.services));
45463
+ }).pipe(Effect.provide(services$1));
44724
45464
  });
44725
-
44726
- //#endregion
44727
- //#region bin/alchemy.ts
44728
- const USER = Config.string("USER").pipe(Config.orElse(() => Config.string("USERNAME")), Config.withDefault("unknown"));
44729
- const STAGE = Config.string("stage").pipe(Config.option, (a) => a.asEffect(), Effect.map(Option.getOrUndefined));
44730
- const stage = Flag.string("stage").pipe(Flag.withSchema(S.String.check(S.isPattern(/^[a-z0-9]+([-_a-z0-9]+)*$/gi))), Flag.withDescription("Stage to deploy to, defaults to dev_${USER}"), Flag.optional, Flag.map(Option.getOrUndefined), Flag.mapEffect(Effect.fn(function* (stage$1) {
44731
- if (stage$1) return stage$1;
44732
- return yield* STAGE.pipe(Effect.catch(() => Effect.fail(new CliError.MissingOption({ option: "stage" }))), Effect.flatMap((s) => s === void 0 ? USER.asEffect().pipe(Effect.map((user) => `dev_${user}`), Effect.catch(() => Effect.succeed("unknown"))) : Effect.succeed(s)));
44733
- })));
44734
- const envFile = Flag.file("env-file").pipe(Flag.optional, Flag.withDescription("File to load environment variables from, defaults to .env"));
44735
- const dryRun = Flag.boolean("dry-run").pipe(Flag.withDescription("Dry run the deployment, do not actually deploy"), Flag.withDefault(false));
44736
- const yes = Flag.boolean("yes").pipe(Flag.withDescription("Yes to all prompts"), Flag.withDefault(false));
44737
- const force = Flag.boolean("force").pipe(Flag.withDescription("Force updates for resources that would otherwise no-op"), Flag.withDefault(false));
44738
- const main = Argument.file("main", { mustExist: true }).pipe(Argument.withDescription("Main file to deploy, defaults to alchemy.run.ts"), Argument.withDefault("alchemy.run.ts"));
44739
- const deployCommand = Command.make("deploy", {
45465
+ const deployCommand = Command$1.make("deploy", {
44740
45466
  dryRun,
44741
45467
  force,
44742
45468
  main,
44743
45469
  envFile,
44744
45470
  stage,
44745
- yes
44746
- }, (args) => execStack(args));
44747
- const destroyCommand = Command.make("destroy", {
45471
+ yes,
45472
+ profile
45473
+ }, execStack);
45474
+ const destroyCommand = Command$1.make("destroy", {
44748
45475
  dryRun,
44749
45476
  main,
44750
45477
  envFile,
44751
45478
  stage,
44752
- yes
45479
+ yes,
45480
+ profile
44753
45481
  }, (args) => execStack({
44754
45482
  ...args,
44755
45483
  destroy: true
44756
45484
  }));
44757
- const planCommand = Command.make("plan", {
45485
+ const planCommand = Command$1.make("plan", {
44758
45486
  main,
44759
45487
  envFile,
44760
- stage
45488
+ stage,
45489
+ profile
44761
45490
  }, (args) => execStack({
44762
45491
  ...args,
44763
45492
  dryRun: true
44764
45493
  }));
44765
- const execStack = Effect.fn(function* ({ main: main$1, stage: stage$1, envFile: envFile$1, dryRun: dryRun$1 = false, force: force$1 = false, yes: yes$1 = false, destroy = false }) {
44766
- const path = yield* Path;
44767
- const stackEffect = (yield* Effect.promise(() => import(path.resolve(process.cwd(), main$1)))).default;
44768
- if (!stackEffect) return yield* Effect.die(/* @__PURE__ */ new Error(`Main file '${main$1}' must export a default stack definition (export default defineStack({...}))`));
44769
- const configProvider = yield* loadConfigProvider(envFile$1);
44770
- const platform$1 = Layer.mergeAll(NodeServices.layer, FetchHttpClient.layer);
44771
- const rootLogger = Logger.layer([fileLogger("out")]);
44772
- const alchemy = Layer.mergeAll(LocalState, inkCLI(), Layer.provideMerge(rootLogger, dotAlchemy));
44773
- yield* Effect.gen(function* () {
44774
- const cli = yield* Cli;
44775
- const stack = yield* stackEffect;
44776
- yield* Effect.gen(function* () {
44777
- const updatePlan = yield* make(destroy ? {
44778
- ...stack,
44779
- resources: {},
44780
- bindings: {},
44781
- output: {}
44782
- } : stack, { force: force$1 });
44783
- if (dryRun$1) yield* cli.displayPlan(updatePlan);
44784
- else {
44785
- if (!yes$1) {
44786
- if (!(yield* cli.approvePlan(updatePlan))) return;
44787
- }
44788
- const outputs = yield* apply(updatePlan);
44789
- yield* Console.log(outputs);
44790
- }
44791
- }).pipe(Effect.provide(stack.services), provideFreshArtifactStore);
44792
- }).pipe(Effect.provide(Layer.provideMerge(alchemy, Layer.mergeAll(platform$1, Layer.succeed(Stage, stage$1)))), Effect.provideService(ConfigProvider.ConfigProvider, configProvider));
44793
- });
44794
- const resourceFilter = Flag.string("filter").pipe(Flag.withDescription("Comma-separated logical resource IDs (e.g. Api,Sandbox). Only those resources are included."), Flag.optional, Flag.map(Option.getOrUndefined));
44795
- const tailCommand = Command.make("tail", {
45494
+
45495
+ //#endregion
45496
+ //#region bin/commands/login.ts
45497
+ const loginConfigure = Flag.boolean("configure").pipe(Flag.withDescription("Run the provider's interactive configure step before logging in"), Flag.withDefault(false));
45498
+ const loginCommand = Command.make("login", {
44796
45499
  main,
44797
45500
  envFile,
44798
45501
  stage,
44799
- filter: resourceFilter
44800
- }, Effect.fnUntraced(function* ({ main: main$1, stage: stage$1, envFile: envFile$1, filter }) {
44801
- const path = yield* Path;
44802
- const stackEffect = (yield* Effect.promise(() => import(path.resolve(process.cwd(), main$1)))).default;
44803
- if (!stackEffect) return yield* Effect.die(/* @__PURE__ */ new Error(`Main file '${main$1}' must export a default stack definition (export default defineStack({...}))`));
44804
- const configProvider = yield* loadConfigProvider(envFile$1);
44805
- const platform$1 = Layer.mergeAll(NodeServices.layer, FetchHttpClient.layer);
44806
- const rootLogger = Logger.layer([fileLogger("out")]);
44807
- const alchemy = Layer.mergeAll(LocalState, Layer.provideMerge(rootLogger, dotAlchemy));
45502
+ profile,
45503
+ configure: loginConfigure
45504
+ }, Effect.fnUntraced(function* ({ main: main$1, stage: stage$1, envFile: envFile$1, profile: profile$1, configure }) {
45505
+ const stackEffect = yield* importStack(main$1);
45506
+ const authProviders = {};
45507
+ const services$1 = Layer.mergeAll(Layer.succeed(AuthProviders, authProviders), ConfigProvider.layer(withProfileOverride(yield* loadConfigProvider(envFile$1), profile$1)), Logger.layer([fileLogger("out")]), Layer.succeed(Stage, stage$1), LocalState);
44808
45508
  yield* Effect.gen(function* () {
44809
- const state = yield* State;
44810
- const stack = yield* stackEffect;
44811
- yield* Effect.gen(function* () {
44812
- const filterSet = parseResourceFilter(filter);
44813
- const availableIds = [...new Set(Object.values(stack.resources).map((r) => r.LogicalId))].sort();
44814
- if (filterSet) {
44815
- for (const id of filterSet) if (!availableIds.includes(id)) return yield* Effect.die(/* @__PURE__ */ new Error(`Unknown resource '${id}' in --filter. Available: ${availableIds.join(", ") || "(none)"}`));
44816
- }
44817
- const fqns = Object.keys(stack.resources);
44818
- const tailable = [];
44819
- for (const fqn of fqns) {
44820
- const resource = stack.resources[fqn];
44821
- if (filterSet && !filterSet.has(resource.LogicalId)) continue;
44822
- const resourceState = yield* state.get({
44823
- stack: stack.name,
44824
- stage: stack.stage,
44825
- fqn
44826
- });
44827
- if (!resourceState?.attr) continue;
44828
- const provider = yield* findProviderByType(resource.Type);
44829
- if (!provider.tail) continue;
44830
- tailable.push({
44831
- logicalId: resource.LogicalId,
44832
- stream: provider.tail({
44833
- id: resource.LogicalId,
44834
- instanceId: resourceState.instanceId,
44835
- props: resourceState.props,
44836
- output: resourceState.attr
44837
- })
45509
+ yield* stackEffect;
45510
+ const ci = yield* Config.boolean("CI").pipe(Config.withDefault(false));
45511
+ const providers = Object.values(authProviders);
45512
+ if (providers.length === 0) {
45513
+ yield* Console.log("No AuthProviders registered. Make sure the stack's providers() layer includes AuthProviderLayer entries.");
45514
+ return;
45515
+ }
45516
+ yield* Effect.forEach(providers, (provider) => Effect.gen(function* () {
45517
+ const existing = yield* getProfile(profile$1);
45518
+ const stored = existing?.[provider.name];
45519
+ let cfg;
45520
+ if (configure || stored == null) {
45521
+ cfg = yield* provider.configure(profile$1, { ci });
45522
+ yield* setProfile(profile$1, {
45523
+ ...existing,
45524
+ [provider.name]: cfg
44838
45525
  });
44839
- }
44840
- if (tailable.length === 0) {
44841
- if (filterSet) yield* Console.log("No tailable resources match --filter (deploy first, or selected resources may not support tail).");
44842
- else yield* Console.log("No tailable resources found. Deploy first, then run tail.");
44843
- return;
44844
- }
44845
- yield* Console.log(`Tailing: ${tailable.map((t) => t.logicalId).join(", ")}`);
44846
- const taggedStreams = tailable.map(({ logicalId, stream }, i) => {
44847
- const color = TAIL_COLORS[i % TAIL_COLORS.length];
44848
- return stream.pipe(Stream$1.map(({ timestamp, message }) => {
44849
- return `${color}${formatLocalTimestamp(timestamp)} [${logicalId}]${TAIL_RESET} ${message}`;
44850
- }));
44851
- });
44852
- yield* Stream$1.mergeAll(taggedStreams, { concurrency: "unbounded" }).pipe(Stream$1.runForEach((line) => Console.log(line)));
44853
- }).pipe(Effect.provide(stack.services));
44854
- }).pipe(Effect.provide(Layer.provideMerge(alchemy, Layer.mergeAll(platform$1, Layer.succeed(Stage, stage$1)))), Effect.provideService(ConfigProvider.ConfigProvider, configProvider), Effect.scoped);
45526
+ } else cfg = stored;
45527
+ yield* provider.login(profile$1, cfg);
45528
+ yield* provider.prettyPrint(profile$1, cfg);
45529
+ }), { discard: true });
45530
+ }).pipe(Effect.provide(services$1));
44855
45531
  }));
44856
- const awsProfile = Flag.string("profile").pipe(Flag.withDescription("AWS profile to use for credentials"), Flag.optional, Flag.map(Option.getOrElse(() => "default")));
44857
- const awsRegion = Flag.string("region").pipe(Flag.withDescription("AWS region to bootstrap (defaults to AWS_REGION env var)"), Flag.optional, Flag.map(Option.getOrUndefined));
44858
- const bootstrapDestroy = Flag.boolean("destroy").pipe(Flag.withDescription("Destroy all bootstrap buckets in the selected region"), Flag.withDefault(false));
44859
- const bootstrapCommand = Command.make("bootstrap", {
44860
- envFile,
44861
- profile: awsProfile,
44862
- region: awsRegion,
44863
- destroy: bootstrapDestroy
44864
- }, Effect.fnUntraced(function* ({ envFile: envFile$1, profile, region, destroy }) {
44865
- const platform$1 = Layer.mergeAll(NodeServices.layer, FetchHttpClient.layer, Layer.provideMerge(Logger.layer([fileLogger("bootstrap.txt")]), dotAlchemy));
44866
- return yield* Effect.gen(function* () {
44867
- const ssoProfile = yield* Auth.loadProfile(profile);
44868
- const credentials = yield* Auth.loadProfileCredentials(profile);
44869
- const awsLayers = Layer.mergeAll(Layer.succeed(Account, profile), Layer.succeed(Region$1, region ?? ssoProfile.region ?? "us-east-1"), Layer.succeed(Credentials, Effect.succeed(credentials)));
44870
- return yield* Effect.gen(function* () {
44871
- const provider = yield* loadConfigProvider(envFile$1);
44872
- const bootstrapLayer = Layer.provide(awsLayers, Layer.succeed(ConfigProvider.ConfigProvider, provider));
44873
- if (destroy) {
44874
- yield* destroyBootstrap().pipe(Effect.tap((result) => result.destroyed === 0 ? Console.log("✓ No bootstrap buckets found to destroy") : Console.log(`✓ Destroyed ${result.destroyed} bootstrap bucket(s): ${result.bucketNames.join(", ")}`)), Effect.provide(bootstrapLayer));
44875
- return;
44876
- }
44877
- yield* bootstrap().pipe(Effect.tap(({ bucketName, created }) => created ? Console.log(`✓ Created assets bucket: ${bucketName}`) : Console.log(`✓ Assets bucket already exists: ${bucketName}`)), Effect.provide(bootstrapLayer));
44878
- });
44879
- }).pipe(Effect.provide(platform$1));
44880
- }));
44881
- Command.make("dev", {
44882
- main,
44883
- envFile,
44884
- stage
44885
- }, ({ envFile: envFile$1, main: main$1, stage: stage$1 }) => Effect.gen(function* () {
44886
- const proc = yield* ChildProcess.make("bun", ["--hot", main$1], { env: { ALCHEMY_PHASE: "dev" } });
44887
- proc.stdout;
44888
- proc.stderr;
44889
- proc.all;
44890
- }));
44891
- const TAIL_COLORS = [
44892
- "\x1B[36m",
44893
- "\x1B[35m",
44894
- "\x1B[33m",
44895
- "\x1B[32m",
44896
- "\x1B[34m",
44897
- "\x1B[91m",
44898
- "\x1B[96m",
44899
- "\x1B[95m",
44900
- "\x1B[93m",
44901
- "\x1B[92m"
44902
- ];
44903
- const TAIL_RESET = "\x1B[0m";
44904
- const formatLocalTimestamp = (date) => {
44905
- return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")} ${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}:${String(date.getSeconds()).padStart(2, "0")}.${String(date.getMilliseconds()).padStart(3, "0")} ${new Intl.DateTimeFormat("en-US", { timeZoneName: "short" }).formatToParts(date).find((p) => p.type === "timeZoneName")?.value ?? ""}`;
44906
- };
45532
+
45533
+ //#endregion
45534
+ //#region bin/commands/logs.ts
44907
45535
  const logsLimit = Flag.integer("limit").pipe(Flag.withDescription("Number of log entries to fetch"), Flag.withDefault(100));
44908
45536
  const logsSince = Flag.string("since").pipe(Flag.withDescription("Fetch logs since this time (e.g. '1h', '30m', '2024-01-01T00:00:00Z')"), Flag.optional, Flag.map(Option.getOrUndefined));
44909
45537
  const logsCommand = Command.make("logs", {
44910
45538
  main,
44911
45539
  envFile,
44912
45540
  stage,
45541
+ profile,
44913
45542
  filter: resourceFilter,
44914
45543
  limit: logsLimit,
44915
45544
  since: logsSince
44916
- }, Effect.fnUntraced(function* ({ main: main$1, stage: stage$1, envFile: envFile$1, filter, limit, since }) {
44917
- const path = yield* Path;
44918
- const stackEffect = (yield* Effect.promise(() => import(path.resolve(process.cwd(), main$1)))).default;
44919
- if (!stackEffect) return yield* Effect.die(/* @__PURE__ */ new Error(`Main file '${main$1}' must export a default stack definition (export default defineStack({...}))`));
44920
- const configProvider = yield* loadConfigProvider(envFile$1);
44921
- const platform$1 = Layer.mergeAll(NodeServices.layer, FetchHttpClient.layer);
44922
- const rootLogger = Logger.layer([fileLogger("out")]);
44923
- const alchemy = Layer.mergeAll(LocalState, Layer.provideMerge(rootLogger, dotAlchemy));
45545
+ }, Effect.fnUntraced(function* ({ main: main$1, stage: stage$1, envFile: envFile$1, profile: profile$1, filter, limit, since }) {
45546
+ const stackEffect = yield* importStack(main$1);
45547
+ const services$1 = Layer.mergeAll(ConfigProvider.layer(withProfileOverride(yield* loadConfigProvider(envFile$1), profile$1)), Layer.succeed(AuthProviders, {}), Layer.succeed(Stage, stage$1), Logger.layer([fileLogger("out")]), LocalState);
44924
45548
  const sinceDate = since ? parseSince(since) : void 0;
44925
45549
  yield* Effect.gen(function* () {
44926
45550
  const state = yield* State;
@@ -44973,35 +45597,83 @@ const logsCommand = Command.make("logs", {
44973
45597
  }).sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
44974
45598
  for (const entry of merged) yield* Console.log(entry.formatted);
44975
45599
  }).pipe(Effect.provide(stack.services));
44976
- }).pipe(Effect.provide(Layer.provideMerge(alchemy, Layer.mergeAll(platform$1, Layer.succeed(Stage, stage$1)))), Effect.provideService(ConfigProvider.ConfigProvider, configProvider), Effect.scoped);
45600
+ }).pipe(Effect.provide(services$1));
44977
45601
  }));
44978
- const parseResourceFilter = (filter) => {
44979
- if (filter === void 0) return void 0;
44980
- const ids = filter.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
44981
- if (ids.length === 0) return void 0;
44982
- return new Set(ids);
44983
- };
44984
- const parseSince = (value) => {
44985
- const match = value.match(/^(\d+)([smhd])$/);
44986
- if (match) {
44987
- const num = parseInt(match[1], 10);
44988
- const unit = match[2];
44989
- const ms = unit === "s" ? num * 1e3 : unit === "m" ? num * 6e4 : unit === "h" ? num * 36e5 : num * 864e5;
44990
- return new Date(Date.now() - ms);
44991
- }
44992
- const parsed = new Date(value);
44993
- if (isNaN(parsed.getTime())) throw new Error(`Invalid --since value: '${value}'. Use a duration (e.g. '1h', '30m') or ISO date.`);
44994
- return parsed;
44995
- };
44996
- const root = Command.make("alchemy", {}).pipe(Command.withSubcommands([
45602
+
45603
+ //#endregion
45604
+ //#region bin/commands/tail.ts
45605
+ const tailCommand = Command$1.make("tail", {
45606
+ main,
45607
+ envFile,
45608
+ stage,
45609
+ profile,
45610
+ filter: resourceFilter
45611
+ }, Effect.fnUntraced(function* ({ main: main$1, stage: stage$1, envFile: envFile$1, profile: profile$1, filter }) {
45612
+ const stackEffect = yield* importStack(main$1);
45613
+ const services$1 = Layer.mergeAll(ConfigProvider.layer(withProfileOverride(yield* loadConfigProvider(envFile$1), profile$1)), Layer.succeed(AuthProviders, {}), Layer.succeed(Stage, stage$1), Logger.layer([fileLogger("out")]), LocalState);
45614
+ yield* Effect.gen(function* () {
45615
+ const state = yield* State;
45616
+ const stack = yield* stackEffect;
45617
+ yield* Effect.gen(function* () {
45618
+ const filterSet = parseResourceFilter(filter);
45619
+ const availableIds = [...new Set(Object.values(stack.resources).map((r) => r.LogicalId))].sort();
45620
+ if (filterSet) {
45621
+ for (const id of filterSet) if (!availableIds.includes(id)) return yield* Effect.die(/* @__PURE__ */ new Error(`Unknown resource '${id}' in --filter. Available: ${availableIds.join(", ") || "(none)"}`));
45622
+ }
45623
+ const fqns = Object.keys(stack.resources);
45624
+ const tailable = [];
45625
+ for (const fqn of fqns) {
45626
+ const resource = stack.resources[fqn];
45627
+ if (filterSet && !filterSet.has(resource.LogicalId)) continue;
45628
+ const resourceState = yield* state.get({
45629
+ stack: stack.name,
45630
+ stage: stack.stage,
45631
+ fqn
45632
+ });
45633
+ if (!resourceState?.attr) continue;
45634
+ const provider = yield* findProviderByType(resource.Type);
45635
+ if (!provider.tail) continue;
45636
+ tailable.push({
45637
+ logicalId: resource.LogicalId,
45638
+ stream: provider.tail({
45639
+ id: resource.LogicalId,
45640
+ instanceId: resourceState.instanceId,
45641
+ props: resourceState.props,
45642
+ output: resourceState.attr
45643
+ })
45644
+ });
45645
+ }
45646
+ if (tailable.length === 0) {
45647
+ if (filterSet) yield* Console.log("No tailable resources match --filter (deploy first, or selected resources may not support tail).");
45648
+ else yield* Console.log("No tailable resources found. Deploy first, then run tail.");
45649
+ return;
45650
+ }
45651
+ yield* Console.log(`Tailing: ${tailable.map((t) => t.logicalId).join(", ")}`);
45652
+ const taggedStreams = tailable.map(({ logicalId, stream }, i) => {
45653
+ const color = TAIL_COLORS[i % TAIL_COLORS.length];
45654
+ return stream.pipe(Stream$1.map(({ timestamp, message }) => {
45655
+ return `${color}${formatLocalTimestamp(timestamp)} [${logicalId}]${TAIL_RESET} ${message}`;
45656
+ }));
45657
+ });
45658
+ yield* Stream$1.mergeAll(taggedStreams, { concurrency: "unbounded" }).pipe(Stream$1.runForEach((line) => Console.log(line)));
45659
+ }).pipe(Effect.provide(stack.services));
45660
+ }).pipe(Effect.provide(services$1));
45661
+ }));
45662
+
45663
+ //#endregion
45664
+ //#region bin/alchemy.ts
45665
+ const root = Command$1.make("alchemy", {}).pipe(Command$1.withSubcommands([
44997
45666
  bootstrapCommand,
44998
45667
  deployCommand,
44999
45668
  destroyCommand,
45000
45669
  planCommand,
45001
45670
  tailCommand,
45002
- logsCommand
45671
+ logsCommand,
45672
+ loginCommand
45003
45673
  ]));
45004
- Command.run(root, { version }).pipe(Effect.provideService(ConfigProvider.ConfigProvider, ConfigProvider.fromEnv()), Effect.provide(NodeServices.layer), Effect.scoped, NodeRuntime.runMain);
45674
+ const cli = Command$1.run(root, { version });
45675
+ const services = Layer.mergeAll(Layer.provideMerge(dotAlchemy, PlatformServices), FetchHttpClient.layer, ConfigProvider.layer(ConfigProvider.fromEnv()));
45676
+ cli.pipe(Effect.provide(services), Effect.scoped, handleCancellation, runMain);
45005
45677
 
45006
45678
  //#endregion
45007
45679
  export { };