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.ts CHANGED
@@ -1,730 +1,23 @@
1
- import * as Auth from "@distilled.cloud/aws/Auth";
2
- import { NodeRuntime, NodeServices } from "@effect/platform-node";
3
- import * as Config from "effect/Config";
4
1
  import * as ConfigProvider from "effect/ConfigProvider";
5
- import * as Console from "effect/Console";
6
2
  import * as Effect from "effect/Effect";
7
3
  import * as Layer from "effect/Layer";
8
- import * as Logger from "effect/Logger";
9
- import * as Option from "effect/Option";
10
- import { Path } from "effect/Path";
11
- import * as S from "effect/Schema";
12
- import * as Stream from "effect/Stream";
13
- import { Argument, Command, Flag } from "effect/unstable/cli";
14
- import * as CliError from "effect/unstable/cli/CliError";
4
+ import * as Command from "effect/unstable/cli/Command";
15
5
  import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
16
- import * as ChildProcess from "effect/unstable/process/ChildProcess";
17
6
 
18
7
  import packageJson from "../package.json" with { type: "json" };
19
- import { apply } from "../src/Apply.ts";
20
- import { provideFreshArtifactStore } from "../src/Artifacts.ts";
21
- import * as AWSAccount from "../src/AWS/Account.ts";
22
- import {
23
- bootstrap as bootstrapAws,
24
- destroyBootstrap as destroyBootstrapAws,
25
- } from "../src/AWS/Bootstrap.ts";
26
- import * as AWSCredentials from "../src/AWS/Credentials.ts";
27
- import * as AWSRegion from "../src/AWS/Region.ts";
28
- import * as CLI from "../src/Cli/index.ts";
29
8
  import { dotAlchemy } from "../src/Config.ts";
30
- import * as Plan from "../src/Plan.ts";
31
- import { findProviderByType, type LogLine } from "../src/Provider.ts";
32
- import * as Stack from "../src/Stack.ts";
33
- import { Stage } from "../src/Stage.ts";
34
- import * as State from "../src/State/index.ts";
35
- import { loadConfigProvider } from "../src/Util/ConfigProvider.ts";
36
- import { fileLogger } from "../src/Util/FileLogger.ts";
37
-
38
- const USER = Config.string("USER").pipe(
39
- Config.orElse(() => Config.string("USERNAME")),
40
- Config.withDefault("unknown"),
41
- );
42
-
43
- const STAGE = Config.string("stage").pipe(
44
- Config.option,
45
- (a) => a.asEffect(),
46
- Effect.map(Option.getOrUndefined),
47
- );
48
-
49
- const stage = Flag.string("stage").pipe(
50
- Flag.withSchema(S.String.check(S.isPattern(/^[a-z0-9]+([-_a-z0-9]+)*$/gi))),
51
- Flag.withDescription("Stage to deploy to, defaults to dev_${USER}"),
52
- Flag.optional,
53
- Flag.map(Option.getOrUndefined),
54
- Flag.mapEffect(
55
- Effect.fn(function* (stage) {
56
- if (stage) {
57
- return stage;
58
- }
59
- return yield* STAGE.pipe(
60
- Effect.catch(() =>
61
- Effect.fail(
62
- new CliError.MissingOption({
63
- option: "stage",
64
- }),
65
- ),
66
- ),
67
- Effect.flatMap((s) =>
68
- s === undefined
69
- ? USER.asEffect().pipe(
70
- Effect.map((user) => `dev_${user}`),
71
- Effect.catch(() => Effect.succeed("unknown")),
72
- )
73
- : Effect.succeed(s),
74
- ),
75
- );
76
- }),
77
- ),
78
- );
79
-
80
- const envFile = Flag.file("env-file").pipe(
81
- Flag.optional,
82
- Flag.withDescription(
83
- "File to load environment variables from, defaults to .env",
84
- ),
85
- );
86
-
87
- const dryRun = Flag.boolean("dry-run").pipe(
88
- Flag.withDescription("Dry run the deployment, do not actually deploy"),
89
- Flag.withDefault(false),
90
- );
91
-
92
- const yes = Flag.boolean("yes").pipe(
93
- Flag.withDescription("Yes to all prompts"),
94
- Flag.withDefault(false),
95
- );
96
-
97
- const force = Flag.boolean("force").pipe(
98
- Flag.withDescription(
99
- "Force updates for resources that would otherwise no-op",
100
- ),
101
- Flag.withDefault(false),
102
- );
103
-
104
- const main = Argument.file("main", {
105
- mustExist: true,
106
- }).pipe(
107
- Argument.withDescription("Main file to deploy, defaults to alchemy.run.ts"),
108
- Argument.withDefault("alchemy.run.ts"),
109
- );
110
-
111
- const deployCommand = Command.make(
112
- "deploy",
113
- {
114
- dryRun,
115
- force,
116
- main,
117
- envFile,
118
- stage,
119
- yes,
120
- },
121
- (args) => execStack(args),
122
- );
123
-
124
- const destroyCommand = Command.make(
125
- "destroy",
126
- {
127
- dryRun,
128
- main,
129
- envFile,
130
- stage,
131
- yes,
132
- },
133
- (args) =>
134
- execStack({
135
- ...args,
136
- destroy: true,
137
- }),
138
- );
139
-
140
- const planCommand = Command.make(
141
- "plan",
142
- {
143
- main,
144
- envFile,
145
- stage,
146
- },
147
- (args) =>
148
- execStack({
149
- ...args,
150
- // plan is the same as deploy with dryRun always set to true
151
- dryRun: true,
152
- }),
153
- );
154
-
155
- const execStack = Effect.fn(function* ({
156
- main,
157
- stage,
158
- envFile,
159
- dryRun = false,
160
- force = false,
161
- yes = false,
162
- destroy = false,
163
- }: {
164
- main: string;
165
- stage: string;
166
- envFile: Option.Option<string>;
167
- dryRun?: boolean;
168
- force?: boolean;
169
- yes?: boolean;
170
- destroy?: boolean;
171
- }) {
172
- const path = yield* Path;
173
- const module = yield* Effect.promise(
174
- () => import(path.resolve(process.cwd(), main)),
175
- );
176
- const stackEffect = module.default as ReturnType<
177
- ReturnType<typeof Stack.make>
178
- >;
179
- if (!stackEffect) {
180
- return yield* Effect.die(
181
- new Error(
182
- `Main file '${main}' must export a default stack definition (export default defineStack({...}))`,
183
- ),
184
- );
185
- }
186
-
187
- const configProvider = yield* loadConfigProvider(envFile);
188
-
189
- // TODO(sam): implement local and watch
190
- const platform = Layer.mergeAll(NodeServices.layer, FetchHttpClient.layer);
191
-
192
- const rootLogger = Logger.layer([fileLogger("out")]);
193
-
194
- // override alchemy state store, CLI/reporting and dotAlchemy
195
- const alchemy = Layer.mergeAll(
196
- // TODO(sam): support overriding these
197
- State.LocalState,
198
- CLI.inkCLI(),
199
- // optional
200
- Layer.provideMerge(rootLogger, dotAlchemy),
201
- );
202
-
203
- yield* Effect.gen(function* () {
204
- const cli = yield* CLI.Cli;
205
- const stack = yield* stackEffect;
206
-
207
- yield* Effect.gen(function* () {
208
- const updatePlan = yield* Plan.make(
209
- destroy
210
- ? {
211
- ...stack,
212
- // zero these out (destroy will treat all as orphans)
213
- // TODO(sam): probably better to have Plan.destroy and Plan.update
214
- resources: {},
215
- bindings: {},
216
- output: {},
217
- }
218
- : stack,
219
- { force },
220
- );
221
- if (dryRun) {
222
- yield* cli.displayPlan(updatePlan);
223
- } else {
224
- if (!yes) {
225
- const approved = yield* cli.approvePlan(updatePlan);
226
- if (!approved) {
227
- return;
228
- }
229
- }
230
- const outputs = yield* apply(updatePlan);
231
-
232
- yield* Console.log(outputs);
233
- }
234
- }).pipe(
235
- Effect.provide(stack.services),
236
- provideFreshArtifactStore,
237
- // Effect.provide(Logger.layer([fileLogger("stacks", stack.name, stage)])),
238
- );
239
- }).pipe(
240
- Effect.provide(
241
- Layer.provideMerge(
242
- alchemy,
243
- Layer.mergeAll(platform, Layer.succeed(Stage, stage)),
244
- ),
245
- ),
246
- Effect.provideService(ConfigProvider.ConfigProvider, configProvider),
247
- ) as Effect.Effect<void, any, never>;
248
- // TODO(sam): figure out why we need to cast to remove the Provider<never> requirement
249
- // Effect.Effect<void, any, Provider<never>>;
250
- });
251
-
252
- const resourceFilter = Flag.string("filter").pipe(
253
- Flag.withDescription(
254
- "Comma-separated logical resource IDs (e.g. Api,Sandbox). Only those resources are included.",
255
- ),
256
- Flag.optional,
257
- Flag.map(Option.getOrUndefined),
258
- );
259
-
260
- const tailCommand = Command.make(
261
- "tail",
262
- {
263
- main,
264
- envFile,
265
- stage,
266
- filter: resourceFilter,
267
- },
268
- Effect.fnUntraced(function* ({
269
- main,
270
- stage,
271
- envFile,
272
- filter,
273
- }: {
274
- main: string;
275
- stage: string;
276
- envFile: Option.Option<string>;
277
- filter: string | undefined;
278
- }) {
279
- const path = yield* Path;
280
- const module = yield* Effect.promise(
281
- () => import(path.resolve(process.cwd(), main)),
282
- );
283
- const stackEffect = module.default as ReturnType<
284
- ReturnType<typeof Stack.make>
285
- >;
286
- if (!stackEffect) {
287
- return yield* Effect.die(
288
- new Error(
289
- `Main file '${main}' must export a default stack definition (export default defineStack({...}))`,
290
- ),
291
- );
292
- }
293
-
294
- const configProvider = yield* loadConfigProvider(envFile);
295
-
296
- const platform = Layer.mergeAll(NodeServices.layer, FetchHttpClient.layer);
297
-
298
- const rootLogger = Logger.layer([fileLogger("out")]);
299
-
300
- const alchemy = Layer.mergeAll(
301
- State.LocalState,
302
- Layer.provideMerge(rootLogger, dotAlchemy),
303
- );
304
-
305
- yield* Effect.gen(function* () {
306
- const state = yield* State.State;
307
- const stack = yield* stackEffect;
308
-
309
- yield* Effect.gen(function* () {
310
- const filterSet = parseResourceFilter(filter);
311
- const availableIds = [
312
- ...new Set(Object.values(stack.resources).map((r) => r.LogicalId)),
313
- ].sort();
314
-
315
- if (filterSet) {
316
- for (const id of filterSet) {
317
- if (!availableIds.includes(id)) {
318
- return yield* Effect.die(
319
- new Error(
320
- `Unknown resource '${id}' in --filter. Available: ${availableIds.join(", ") || "(none)"}`,
321
- ),
322
- );
323
- }
324
- }
325
- }
326
-
327
- const fqns = Object.keys(stack.resources);
328
- const tailable: {
329
- logicalId: string;
330
- stream: Stream.Stream<LogLine, any, any>;
331
- }[] = [];
332
-
333
- for (const fqn of fqns) {
334
- const resource = stack.resources[fqn]!;
335
- if (filterSet && !filterSet.has(resource.LogicalId)) continue;
336
-
337
- const resourceState = yield* state.get({
338
- stack: stack.name,
339
- stage: stack.stage,
340
- fqn,
341
- });
342
- if (!resourceState?.attr) continue;
343
-
344
- const provider = yield* findProviderByType(resource.Type);
345
- if (!provider.tail) continue;
346
-
347
- tailable.push({
348
- logicalId: resource.LogicalId,
349
- stream: provider.tail({
350
- id: resource.LogicalId,
351
- instanceId: resourceState.instanceId,
352
- props: resourceState.props as any,
353
- output: resourceState.attr as any,
354
- }),
355
- });
356
- }
357
-
358
- if (tailable.length === 0) {
359
- if (filterSet) {
360
- yield* Console.log(
361
- "No tailable resources match --filter (deploy first, or selected resources may not support tail).",
362
- );
363
- } else {
364
- yield* Console.log(
365
- "No tailable resources found. Deploy first, then run tail.",
366
- );
367
- }
368
- return;
369
- }
370
-
371
- yield* Console.log(
372
- `Tailing: ${tailable.map((t) => t.logicalId).join(", ")}`,
373
- );
9
+ import { PlatformServices, runMain } from "../src/Util/PlatformServices.ts";
374
10
 
375
- const taggedStreams = tailable.map(({ logicalId, stream }, i) => {
376
- const color = TAIL_COLORS[i % TAIL_COLORS.length]!;
377
- return stream.pipe(
378
- Stream.map(({ timestamp, message }) => {
379
- const ts = formatLocalTimestamp(timestamp);
380
- return `${color}${ts} [${logicalId}]${TAIL_RESET} ${message}`;
381
- }),
382
- );
383
- });
384
-
385
- yield* Stream.mergeAll(taggedStreams, {
386
- concurrency: "unbounded",
387
- }).pipe(Stream.runForEach((line) => Console.log(line)));
388
- }).pipe(Effect.provide(stack.services));
389
- }).pipe(
390
- Effect.provide(
391
- Layer.provideMerge(
392
- alchemy,
393
- Layer.mergeAll(platform, Layer.succeed(Stage, stage)),
394
- ),
395
- ),
396
- Effect.provideService(ConfigProvider.ConfigProvider, configProvider),
397
- Effect.scoped,
398
- ) as Effect.Effect<void, any, never>;
399
- }),
400
- );
401
-
402
- const awsProfile = Flag.string("profile").pipe(
403
- Flag.withDescription("AWS profile to use for credentials"),
404
- Flag.optional,
405
- Flag.map(Option.getOrElse(() => "default")),
406
- );
407
-
408
- const awsRegion = Flag.string("region").pipe(
409
- Flag.withDescription(
410
- "AWS region to bootstrap (defaults to AWS_REGION env var)",
411
- ),
412
- Flag.optional,
413
- Flag.map(Option.getOrUndefined),
414
- );
415
-
416
- const bootstrapDestroy = Flag.boolean("destroy").pipe(
417
- Flag.withDescription("Destroy all bootstrap buckets in the selected region"),
418
- Flag.withDefault(false),
419
- );
420
-
421
- const bootstrapCommand = Command.make(
422
- "bootstrap",
423
- {
424
- envFile,
425
- profile: awsProfile,
426
- region: awsRegion,
427
- destroy: bootstrapDestroy,
428
- },
429
- Effect.fnUntraced(function* ({ envFile, profile, region, destroy }) {
430
- const platform = Layer.mergeAll(
431
- NodeServices.layer,
432
- FetchHttpClient.layer,
433
- Layer.provideMerge(
434
- Logger.layer([fileLogger("bootstrap.txt")]),
435
- dotAlchemy,
436
- ),
437
- );
438
-
439
- return yield* Effect.gen(function* () {
440
- const ssoProfile = yield* Auth.loadProfile(profile);
441
-
442
- const credentials = yield* Auth.loadProfileCredentials(profile);
443
-
444
- const awsLayers = Layer.mergeAll(
445
- Layer.succeed(AWSAccount.Account, profile),
446
- Layer.succeed(
447
- AWSRegion.Region,
448
- region ?? ssoProfile.region ?? "us-east-1",
449
- ),
450
- Layer.succeed(AWSCredentials.Credentials, Effect.succeed(credentials)),
451
- );
452
-
453
- return yield* Effect.gen(function* () {
454
- const provider = yield* loadConfigProvider(envFile);
455
- const bootstrapLayer = Layer.provide(
456
- awsLayers,
457
- Layer.succeed(ConfigProvider.ConfigProvider, provider),
458
- );
459
- if (destroy) {
460
- yield* destroyBootstrapAws().pipe(
461
- Effect.tap((result) =>
462
- result.destroyed === 0
463
- ? Console.log("✓ No bootstrap buckets found to destroy")
464
- : Console.log(
465
- `✓ Destroyed ${result.destroyed} bootstrap bucket(s): ${result.bucketNames.join(", ")}`,
466
- ),
467
- ),
468
- Effect.provide(bootstrapLayer),
469
- );
470
- return;
471
- }
472
- yield* bootstrapAws().pipe(
473
- Effect.tap(({ bucketName, created }) =>
474
- created
475
- ? Console.log(`✓ Created assets bucket: ${bucketName}`)
476
- : Console.log(`✓ Assets bucket already exists: ${bucketName}`),
477
- ),
478
- Effect.provide(bootstrapLayer),
479
- );
480
- });
481
- }).pipe(Effect.provide(platform)) as Effect.Effect<void, any, never>;
482
- }),
483
- );
484
-
485
- const devCommand = Command.make(
486
- "dev",
487
- {
488
- main,
489
- envFile,
490
- stage,
491
- },
492
- ({ envFile, main, stage }) =>
493
- Effect.gen(function* () {
494
- const cmd = ChildProcess.make("bun", ["--hot", main], {
495
- env: {
496
- ALCHEMY_PHASE: "dev",
497
- },
498
- });
499
-
500
- const proc = yield* cmd;
501
-
502
- proc.stdout;
503
- proc.stderr;
504
- proc.all;
505
- }),
506
- );
507
-
508
- const TAIL_COLORS = [
509
- "\x1b[36m", // cyan
510
- "\x1b[35m", // magenta
511
- "\x1b[33m", // yellow
512
- "\x1b[32m", // green
513
- "\x1b[34m", // blue
514
- "\x1b[91m", // bright red
515
- "\x1b[96m", // bright cyan
516
- "\x1b[95m", // bright magenta
517
- "\x1b[93m", // bright yellow
518
- "\x1b[92m", // bright green
519
- ];
520
- const TAIL_RESET = "\x1b[0m";
521
-
522
- const formatLocalTimestamp = (date: Date): string => {
523
- const y = date.getFullYear();
524
- const mo = String(date.getMonth() + 1).padStart(2, "0");
525
- const d = String(date.getDate()).padStart(2, "0");
526
- const h = String(date.getHours()).padStart(2, "0");
527
- const mi = String(date.getMinutes()).padStart(2, "0");
528
- const s = String(date.getSeconds()).padStart(2, "0");
529
- const ms = String(date.getMilliseconds()).padStart(3, "0");
530
- const tz =
531
- new Intl.DateTimeFormat("en-US", { timeZoneName: "short" })
532
- .formatToParts(date)
533
- .find((p) => p.type === "timeZoneName")?.value ?? "";
534
- return `${y}-${mo}-${d} ${h}:${mi}:${s}.${ms} ${tz}`;
535
- };
536
-
537
- const logsLimit = Flag.integer("limit").pipe(
538
- Flag.withDescription("Number of log entries to fetch"),
539
- Flag.withDefault(100),
540
- );
541
-
542
- const logsSince = Flag.string("since").pipe(
543
- Flag.withDescription(
544
- "Fetch logs since this time (e.g. '1h', '30m', '2024-01-01T00:00:00Z')",
545
- ),
546
- Flag.optional,
547
- Flag.map(Option.getOrUndefined),
548
- );
549
-
550
- const logsCommand = Command.make(
551
- "logs",
552
- {
553
- main,
554
- envFile,
555
- stage,
556
- filter: resourceFilter,
557
- limit: logsLimit,
558
- since: logsSince,
559
- },
560
- Effect.fnUntraced(function* ({
561
- main,
562
- stage,
563
- envFile,
564
- filter,
565
- limit,
566
- since,
567
- }: {
568
- main: string;
569
- stage: string;
570
- envFile: Option.Option<string>;
571
- filter: string | undefined;
572
- limit: number;
573
- since: string | undefined;
574
- }) {
575
- const path = yield* Path;
576
- const module = yield* Effect.promise(
577
- () => import(path.resolve(process.cwd(), main)),
578
- );
579
- const stackEffect = module.default as ReturnType<
580
- ReturnType<typeof Stack.make>
581
- >;
582
- if (!stackEffect) {
583
- return yield* Effect.die(
584
- new Error(
585
- `Main file '${main}' must export a default stack definition (export default defineStack({...}))`,
586
- ),
587
- );
588
- }
589
-
590
- const configProvider = yield* loadConfigProvider(envFile);
591
-
592
- const platform = Layer.mergeAll(NodeServices.layer, FetchHttpClient.layer);
593
-
594
- const rootLogger = Logger.layer([fileLogger("out")]);
595
-
596
- const alchemy = Layer.mergeAll(
597
- State.LocalState,
598
- Layer.provideMerge(rootLogger, dotAlchemy),
599
- );
600
-
601
- const sinceDate = since ? parseSince(since) : undefined;
602
-
603
- yield* Effect.gen(function* () {
604
- const state = yield* State.State;
605
- const stack = yield* stackEffect;
606
-
607
- yield* Effect.gen(function* () {
608
- const filterSet = parseResourceFilter(filter);
609
- const availableIds = [
610
- ...new Set(Object.values(stack.resources).map((r) => r.LogicalId)),
611
- ].sort();
612
-
613
- if (filterSet) {
614
- for (const id of filterSet) {
615
- if (!availableIds.includes(id)) {
616
- return yield* Effect.die(
617
- new Error(
618
- `Unknown resource '${id}' in --filter. Available: ${availableIds.join(", ") || "(none)"}`,
619
- ),
620
- );
621
- }
622
- }
623
- }
624
-
625
- const fqns = Object.keys(stack.resources);
626
- const allLogs: { logicalId: string; lines: LogLine[] }[] = [];
627
-
628
- for (const fqn of fqns) {
629
- const resource = stack.resources[fqn]!;
630
- if (filterSet && !filterSet.has(resource.LogicalId)) continue;
631
-
632
- const resourceState = yield* state.get({
633
- stack: stack.name,
634
- stage: stack.stage,
635
- fqn,
636
- });
637
- if (!resourceState?.attr) continue;
638
-
639
- const provider = yield* findProviderByType(resource.Type);
640
- if (!provider.logs) continue;
641
-
642
- const lines = yield* provider.logs({
643
- id: resource.LogicalId,
644
- instanceId: resourceState.instanceId,
645
- props: resourceState.props as any,
646
- output: resourceState.attr as any,
647
- options: { limit, since: sinceDate },
648
- });
649
-
650
- allLogs.push({ logicalId: resource.LogicalId, lines });
651
- }
652
-
653
- if (allLogs.length === 0) {
654
- if (filterSet) {
655
- yield* Console.log(
656
- "No resources with logs match --filter (deploy first, or selected resources may not expose logs).",
657
- );
658
- } else {
659
- yield* Console.log(
660
- "No resources with logs found. Deploy first, then run logs.",
661
- );
662
- }
663
- return;
664
- }
665
-
666
- const merged = allLogs
667
- .flatMap(({ logicalId, lines }, i) => {
668
- const color = TAIL_COLORS[i % TAIL_COLORS.length]!;
669
- return lines.map((line) => ({
670
- ...line,
671
- formatted: `${color}${formatLocalTimestamp(line.timestamp)} [${logicalId}]${TAIL_RESET} ${line.message}`,
672
- }));
673
- })
674
- .sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
675
-
676
- for (const entry of merged) {
677
- yield* Console.log(entry.formatted);
678
- }
679
- }).pipe(Effect.provide(stack.services));
680
- }).pipe(
681
- Effect.provide(
682
- Layer.provideMerge(
683
- alchemy,
684
- Layer.mergeAll(platform, Layer.succeed(Stage, stage)),
685
- ),
686
- ),
687
- Effect.provideService(ConfigProvider.ConfigProvider, configProvider),
688
- Effect.scoped,
689
- ) as Effect.Effect<void, any, never>;
690
- }),
691
- );
692
-
693
- const parseResourceFilter = (
694
- filter: string | undefined,
695
- ): ReadonlySet<string> | undefined => {
696
- if (filter === undefined) return undefined;
697
- const ids = filter
698
- .split(",")
699
- .map((s) => s.trim())
700
- .filter((s) => s.length > 0);
701
- if (ids.length === 0) return undefined;
702
- return new Set(ids);
703
- };
704
-
705
- const parseSince = (value: string): Date => {
706
- const match = value.match(/^(\d+)([smhd])$/);
707
- if (match) {
708
- const num = parseInt(match[1]!, 10);
709
- const unit = match[2]!;
710
- const ms =
711
- unit === "s"
712
- ? num * 1000
713
- : unit === "m"
714
- ? num * 60_000
715
- : unit === "h"
716
- ? num * 3_600_000
717
- : num * 86_400_000;
718
- return new Date(Date.now() - ms);
719
- }
720
- const parsed = new Date(value);
721
- if (isNaN(parsed.getTime())) {
722
- throw new Error(
723
- `Invalid --since value: '${value}'. Use a duration (e.g. '1h', '30m') or ISO date.`,
724
- );
725
- }
726
- return parsed;
727
- };
11
+ import { handleCancellation } from "./commands/_shared.ts";
12
+ import { bootstrapCommand } from "./commands/bootstrap.ts";
13
+ import {
14
+ deployCommand,
15
+ destroyCommand,
16
+ planCommand,
17
+ } from "./commands/deploy.ts";
18
+ import { loginCommand } from "./commands/login.ts";
19
+ import { logsCommand } from "./commands/logs.ts";
20
+ import { tailCommand } from "./commands/tail.ts";
728
21
 
729
22
  const root = Command.make("alchemy", {}).pipe(
730
23
  Command.withSubcommands([
@@ -734,23 +27,25 @@ const root = Command.make("alchemy", {}).pipe(
734
27
  planCommand,
735
28
  tailCommand,
736
29
  logsCommand,
30
+ loginCommand,
737
31
  ]),
738
32
  );
739
33
 
740
- // Set up the CLI application
741
34
  const cli = Command.run(root, {
742
35
  // name: "Alchemy Effect CLI",
743
36
  version: packageJson.version,
744
37
  });
745
38
 
746
- // Prepare and run the CLI application
39
+ const services = Layer.mergeAll(
40
+ Layer.provideMerge(dotAlchemy, PlatformServices),
41
+ FetchHttpClient.layer,
42
+ ConfigProvider.layer(ConfigProvider.fromEnv()),
43
+ );
44
+
747
45
  cli.pipe(
748
46
  // $USER and $STAGE are set by the environment
749
- Effect.provideService(
750
- ConfigProvider.ConfigProvider,
751
- ConfigProvider.fromEnv(),
752
- ),
753
- Effect.provide(NodeServices.layer),
47
+ Effect.provide(services),
754
48
  Effect.scoped,
755
- NodeRuntime.runMain,
49
+ handleCancellation,
50
+ runMain,
756
51
  );