alchemy-effect 0.0.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (494) hide show
  1. package/README.md +179 -0
  2. package/bin/alchemy-effect.js +15 -0
  3. package/bin/alchemy-effect.js.map +1 -0
  4. package/bin/alchemy-effect.ts +10 -0
  5. package/lib/app.d.ts +7 -2
  6. package/lib/app.d.ts.map +1 -1
  7. package/lib/app.js +1 -0
  8. package/lib/app.js.map +1 -1
  9. package/lib/apply.d.ts +57 -1
  10. package/lib/apply.d.ts.map +1 -1
  11. package/lib/apply.js +141 -55
  12. package/lib/apply.js.map +1 -1
  13. package/lib/aws/account.d.ts +18 -0
  14. package/lib/aws/account.d.ts.map +1 -0
  15. package/lib/aws/account.js +18 -0
  16. package/lib/aws/account.js.map +1 -0
  17. package/lib/aws/arn.d.ts +2 -0
  18. package/lib/aws/arn.d.ts.map +1 -0
  19. package/lib/aws/arn.js +1 -0
  20. package/lib/aws/arn.js.map +1 -0
  21. package/lib/aws/assets.d.ts +8 -0
  22. package/lib/aws/assets.d.ts.map +1 -0
  23. package/lib/aws/assets.js +4 -0
  24. package/lib/aws/assets.js.map +1 -0
  25. package/lib/aws/bundle.d.ts +4 -0
  26. package/lib/aws/bundle.d.ts.map +1 -0
  27. package/lib/aws/bundle.js +4 -0
  28. package/lib/aws/bundle.js.map +1 -0
  29. package/lib/aws/client.d.ts +8 -0
  30. package/lib/aws/client.d.ts.map +1 -0
  31. package/lib/aws/client.js +28 -0
  32. package/lib/aws/client.js.map +1 -0
  33. package/lib/aws/credentials.d.ts +146 -0
  34. package/lib/aws/credentials.d.ts.map +1 -0
  35. package/lib/aws/credentials.js +170 -0
  36. package/lib/aws/credentials.js.map +1 -0
  37. package/lib/aws/dynamodb/attribute-value.d.ts +20 -0
  38. package/lib/aws/dynamodb/attribute-value.d.ts.map +1 -0
  39. package/lib/aws/dynamodb/attribute-value.js +217 -0
  40. package/lib/aws/dynamodb/attribute-value.js.map +1 -0
  41. package/lib/aws/dynamodb/client.d.ts +12 -0
  42. package/lib/aws/dynamodb/client.d.ts.map +1 -0
  43. package/lib/aws/dynamodb/client.js +11 -0
  44. package/lib/aws/dynamodb/client.js.map +1 -0
  45. package/lib/aws/dynamodb/expr.d.ts +41 -0
  46. package/lib/aws/dynamodb/expr.d.ts.map +1 -0
  47. package/lib/aws/dynamodb/expr.js +1 -0
  48. package/lib/aws/dynamodb/expr.js.map +1 -0
  49. package/lib/aws/dynamodb/index.d.ts +9 -0
  50. package/lib/aws/dynamodb/index.d.ts.map +1 -0
  51. package/lib/aws/dynamodb/index.js +10 -0
  52. package/lib/aws/dynamodb/index.js.map +1 -0
  53. package/lib/aws/dynamodb/projection.d.ts +25 -0
  54. package/lib/aws/dynamodb/projection.d.ts.map +1 -0
  55. package/lib/aws/dynamodb/projection.js +1 -0
  56. package/lib/aws/dynamodb/projection.js.map +1 -0
  57. package/lib/aws/dynamodb/secondary-index.d.ts +25 -0
  58. package/lib/aws/dynamodb/secondary-index.d.ts.map +1 -0
  59. package/lib/aws/dynamodb/secondary-index.js +4 -0
  60. package/lib/aws/dynamodb/secondary-index.js.map +1 -0
  61. package/lib/aws/dynamodb/table.d.ts +56 -0
  62. package/lib/aws/dynamodb/table.d.ts.map +1 -0
  63. package/lib/aws/dynamodb/table.get-item.d.ts +55 -0
  64. package/lib/aws/dynamodb/table.get-item.d.ts.map +1 -0
  65. package/lib/aws/dynamodb/table.get-item.js +75 -0
  66. package/lib/aws/dynamodb/table.get-item.js.map +1 -0
  67. package/lib/aws/dynamodb/table.js +4 -0
  68. package/lib/aws/dynamodb/table.js.map +1 -0
  69. package/lib/aws/dynamodb/table.provider.d.ts +8 -0
  70. package/lib/aws/dynamodb/table.provider.d.ts.map +1 -0
  71. package/lib/aws/dynamodb/table.provider.js +199 -0
  72. package/lib/aws/dynamodb/table.provider.js.map +1 -0
  73. package/lib/aws/ec2/client.d.ts +12 -0
  74. package/lib/aws/ec2/client.d.ts.map +1 -0
  75. package/lib/aws/ec2/client.js +11 -0
  76. package/lib/aws/ec2/client.js.map +1 -0
  77. package/lib/aws/ec2/index.d.ts +4 -0
  78. package/lib/aws/ec2/index.d.ts.map +1 -0
  79. package/lib/aws/ec2/index.js +4 -0
  80. package/lib/aws/ec2/index.js.map +1 -0
  81. package/lib/aws/ec2/vpc.d.ts +131 -0
  82. package/lib/aws/ec2/vpc.d.ts.map +1 -0
  83. package/lib/aws/ec2/vpc.js +3 -0
  84. package/lib/aws/ec2/vpc.js.map +1 -0
  85. package/lib/aws/ec2/vpc.provider.d.ts +7 -0
  86. package/lib/aws/ec2/vpc.provider.d.ts.map +1 -0
  87. package/lib/aws/ec2/vpc.provider.js +198 -0
  88. package/lib/aws/ec2/vpc.provider.js.map +1 -0
  89. package/lib/aws/iam.d.ts +23 -0
  90. package/lib/aws/iam.d.ts.map +1 -0
  91. package/lib/aws/iam.js +7 -0
  92. package/lib/aws/iam.js.map +1 -0
  93. package/lib/aws/index.d.ts +32 -0
  94. package/lib/aws/index.d.ts.map +1 -0
  95. package/lib/aws/index.js +23 -0
  96. package/lib/aws/index.js.map +1 -0
  97. package/lib/aws/lambda/client.d.ts +8 -0
  98. package/lib/aws/lambda/client.d.ts.map +1 -0
  99. package/lib/aws/lambda/client.js +7 -0
  100. package/lib/aws/lambda/client.js.map +1 -0
  101. package/lib/aws/lambda/consume.d.ts +17 -0
  102. package/lib/aws/lambda/consume.d.ts.map +1 -0
  103. package/lib/aws/lambda/consume.js +30 -0
  104. package/lib/aws/lambda/consume.js.map +1 -0
  105. package/lib/aws/lambda/function.d.ts +41 -0
  106. package/lib/aws/lambda/function.d.ts.map +1 -0
  107. package/lib/aws/lambda/function.handler.d.ts +7 -0
  108. package/lib/aws/lambda/function.handler.d.ts.map +1 -0
  109. package/lib/aws/lambda/function.handler.js +8 -0
  110. package/lib/aws/lambda/function.handler.js.map +1 -0
  111. package/lib/aws/lambda/function.invoke.d.ts +10 -0
  112. package/lib/aws/lambda/function.invoke.d.ts.map +1 -0
  113. package/lib/aws/lambda/function.invoke.js +31 -0
  114. package/lib/aws/lambda/function.invoke.js.map +1 -0
  115. package/lib/aws/lambda/function.js +3 -0
  116. package/lib/aws/lambda/function.js.map +1 -0
  117. package/lib/aws/lambda/function.provider.d.ts +9 -0
  118. package/lib/aws/lambda/function.provider.d.ts.map +1 -0
  119. package/lib/aws/lambda/function.provider.js +465 -0
  120. package/lib/aws/lambda/function.provider.js.map +1 -0
  121. package/lib/aws/lambda/index.d.ts +8 -0
  122. package/lib/aws/lambda/index.d.ts.map +1 -0
  123. package/lib/aws/lambda/index.js +9 -0
  124. package/lib/aws/lambda/index.js.map +1 -0
  125. package/lib/aws/lambda/serve.d.ts +14 -0
  126. package/lib/aws/lambda/serve.d.ts.map +1 -0
  127. package/lib/aws/lambda/serve.js +7 -0
  128. package/lib/aws/lambda/serve.js.map +1 -0
  129. package/lib/aws/parse-ini.d.ts +4 -0
  130. package/lib/aws/parse-ini.d.ts.map +1 -0
  131. package/lib/aws/parse-ini.js +67 -0
  132. package/lib/aws/parse-ini.js.map +1 -0
  133. package/lib/aws/profile.d.ts +6 -0
  134. package/lib/aws/profile.d.ts.map +1 -0
  135. package/lib/aws/profile.js +4 -0
  136. package/lib/aws/profile.js.map +1 -0
  137. package/lib/aws/region.d.ts +19 -0
  138. package/lib/aws/region.d.ts.map +1 -0
  139. package/lib/aws/region.js +21 -0
  140. package/lib/aws/region.js.map +1 -0
  141. package/lib/aws/s3.d.ts +8 -0
  142. package/lib/aws/s3.d.ts.map +1 -0
  143. package/lib/aws/s3.js +7 -0
  144. package/lib/aws/s3.js.map +1 -0
  145. package/lib/aws/sqs/client.d.ts +12 -0
  146. package/lib/aws/sqs/client.d.ts.map +1 -0
  147. package/lib/aws/sqs/client.js +11 -0
  148. package/lib/aws/sqs/client.js.map +1 -0
  149. package/lib/aws/sqs/index.d.ts +7 -0
  150. package/lib/aws/sqs/index.d.ts.map +1 -0
  151. package/lib/aws/sqs/index.js +7 -0
  152. package/lib/aws/sqs/index.js.map +1 -0
  153. package/lib/aws/sqs/queue.consume.d.ts +12 -0
  154. package/lib/aws/sqs/queue.consume.d.ts.map +1 -0
  155. package/lib/aws/sqs/queue.consume.js +3 -0
  156. package/lib/aws/sqs/queue.consume.js.map +1 -0
  157. package/lib/aws/sqs/queue.d.ts +79 -0
  158. package/lib/aws/sqs/queue.d.ts.map +1 -0
  159. package/lib/aws/sqs/queue.event-source.d.ts +20 -0
  160. package/lib/aws/sqs/queue.event-source.d.ts.map +1 -0
  161. package/lib/aws/sqs/queue.event-source.js +148 -0
  162. package/lib/aws/sqs/queue.event-source.js.map +1 -0
  163. package/lib/aws/sqs/queue.js +3 -0
  164. package/lib/aws/sqs/queue.js.map +1 -0
  165. package/lib/aws/sqs/queue.provider.d.ts +7 -0
  166. package/lib/aws/sqs/queue.provider.d.ts.map +1 -0
  167. package/lib/aws/sqs/queue.provider.js +79 -0
  168. package/lib/aws/sqs/queue.provider.js.map +1 -0
  169. package/lib/aws/sqs/queue.send-message.d.ts +11 -0
  170. package/lib/aws/sqs/queue.send-message.d.ts.map +1 -0
  171. package/lib/aws/sqs/queue.send-message.js +32 -0
  172. package/lib/aws/sqs/queue.send-message.js.map +1 -0
  173. package/lib/aws/sts.d.ts +8 -0
  174. package/lib/aws/sts.d.ts.map +1 -0
  175. package/lib/aws/sts.js +7 -0
  176. package/lib/aws/sts.js.map +1 -0
  177. package/lib/aws/zip.d.ts +3 -0
  178. package/lib/aws/zip.d.ts.map +1 -0
  179. package/lib/aws/zip.js +12 -0
  180. package/lib/aws/zip.js.map +1 -0
  181. package/lib/binding.d.ts +70 -22
  182. package/lib/binding.d.ts.map +1 -1
  183. package/lib/binding.js.map +1 -1
  184. package/lib/capability.d.ts +38 -0
  185. package/lib/capability.d.ts.map +1 -1
  186. package/lib/cli/approve.d.ts +4 -0
  187. package/lib/cli/approve.d.ts.map +1 -0
  188. package/lib/cli/approve.js +18 -0
  189. package/lib/cli/approve.js.map +1 -0
  190. package/lib/cli/clack.d.ts +14 -0
  191. package/lib/cli/clack.d.ts.map +1 -0
  192. package/lib/cli/clack.js +12 -0
  193. package/lib/cli/clack.js.map +1 -0
  194. package/lib/cli/components/ApprovePlan.d.ts +8 -0
  195. package/lib/cli/components/ApprovePlan.d.ts.map +1 -0
  196. package/lib/cli/components/ApprovePlan.js +30 -0
  197. package/lib/cli/components/ApprovePlan.js.map +1 -0
  198. package/lib/cli/components/Plan.d.ts +7 -0
  199. package/lib/cli/components/Plan.d.ts.map +1 -0
  200. package/lib/cli/components/Plan.js +100 -0
  201. package/lib/cli/components/Plan.js.map +1 -0
  202. package/lib/cli/components/PlanProgress.d.ts +9 -0
  203. package/lib/cli/components/PlanProgress.d.ts.map +1 -0
  204. package/lib/cli/components/PlanProgress.js +166 -0
  205. package/lib/cli/components/PlanProgress.js.map +1 -0
  206. package/lib/cli/index.d.ts +449 -0
  207. package/lib/cli/index.d.ts.map +1 -0
  208. package/lib/cli/index.js +39912 -0
  209. package/lib/cli/index.js.map +1 -0
  210. package/lib/cli/main.d.ts +2 -0
  211. package/lib/cli/main.d.ts.map +1 -0
  212. package/lib/cli/main.js +1 -0
  213. package/lib/cli/main.js.map +1 -0
  214. package/lib/cli/plan.d.ts +13 -0
  215. package/lib/cli/plan.d.ts.map +1 -0
  216. package/lib/cli/plan.js +1 -0
  217. package/lib/cli/plan.js.map +1 -0
  218. package/lib/cli/progress.d.ts +7 -0
  219. package/lib/cli/progress.d.ts.map +1 -0
  220. package/lib/cli/progress.js +30 -0
  221. package/lib/cli/progress.js.map +1 -0
  222. package/lib/cli/spinner.d.ts +2 -0
  223. package/lib/cli/spinner.d.ts.map +1 -0
  224. package/lib/cli/spinner.js +13 -0
  225. package/lib/cli/spinner.js.map +1 -0
  226. package/lib/cloudflare/api.d.ts +36 -0
  227. package/lib/cloudflare/api.d.ts.map +1 -0
  228. package/lib/cloudflare/api.js +99 -0
  229. package/lib/cloudflare/api.js.map +1 -0
  230. package/lib/cloudflare/context.d.ts +27 -0
  231. package/lib/cloudflare/context.d.ts.map +1 -0
  232. package/lib/cloudflare/context.js +24 -0
  233. package/lib/cloudflare/context.js.map +1 -0
  234. package/lib/cloudflare/index.d.ts +6 -0
  235. package/lib/cloudflare/index.d.ts.map +1 -0
  236. package/lib/cloudflare/index.js +5 -0
  237. package/lib/cloudflare/index.js.map +1 -0
  238. package/lib/cloudflare/kv/index.d.ts +4 -0
  239. package/lib/cloudflare/kv/index.d.ts.map +1 -0
  240. package/lib/cloudflare/kv/index.js +4 -0
  241. package/lib/cloudflare/kv/index.js.map +1 -0
  242. package/lib/cloudflare/kv/namespace.binding.d.ts +8 -0
  243. package/lib/cloudflare/kv/namespace.binding.d.ts.map +1 -0
  244. package/lib/cloudflare/kv/namespace.binding.js +15 -0
  245. package/lib/cloudflare/kv/namespace.binding.js.map +1 -0
  246. package/lib/cloudflare/kv/namespace.client.d.ts +11 -0
  247. package/lib/cloudflare/kv/namespace.client.d.ts.map +1 -0
  248. package/lib/cloudflare/kv/namespace.client.js +31 -0
  249. package/lib/cloudflare/kv/namespace.client.js.map +1 -0
  250. package/lib/cloudflare/kv/namespace.d.ts +23 -0
  251. package/lib/cloudflare/kv/namespace.d.ts.map +1 -0
  252. package/lib/cloudflare/kv/namespace.js +3 -0
  253. package/lib/cloudflare/kv/namespace.js.map +1 -0
  254. package/lib/cloudflare/kv/namespace.provider.d.ts +5 -0
  255. package/lib/cloudflare/kv/namespace.provider.d.ts.map +1 -0
  256. package/lib/cloudflare/kv/namespace.provider.js +80 -0
  257. package/lib/cloudflare/kv/namespace.provider.js.map +1 -0
  258. package/lib/cloudflare/live.d.ts +11 -0
  259. package/lib/cloudflare/live.d.ts.map +1 -0
  260. package/lib/cloudflare/live.js +18 -0
  261. package/lib/cloudflare/live.js.map +1 -0
  262. package/lib/cloudflare/r2/bucket.binding.d.ts +8 -0
  263. package/lib/cloudflare/r2/bucket.binding.d.ts.map +1 -0
  264. package/lib/cloudflare/r2/bucket.binding.js +18 -0
  265. package/lib/cloudflare/r2/bucket.binding.js.map +1 -0
  266. package/lib/cloudflare/r2/bucket.client.d.ts +8 -0
  267. package/lib/cloudflare/r2/bucket.client.d.ts.map +1 -0
  268. package/lib/cloudflare/r2/bucket.client.js +9 -0
  269. package/lib/cloudflare/r2/bucket.client.js.map +1 -0
  270. package/lib/cloudflare/r2/bucket.d.ts +32 -0
  271. package/lib/cloudflare/r2/bucket.d.ts.map +1 -0
  272. package/lib/cloudflare/r2/bucket.del.d.ts +4 -0
  273. package/lib/cloudflare/r2/bucket.del.d.ts.map +1 -0
  274. package/lib/cloudflare/r2/bucket.del.js +7 -0
  275. package/lib/cloudflare/r2/bucket.del.js.map +1 -0
  276. package/lib/cloudflare/r2/bucket.get.d.ts +5 -0
  277. package/lib/cloudflare/r2/bucket.get.d.ts.map +1 -0
  278. package/lib/cloudflare/r2/bucket.get.js +7 -0
  279. package/lib/cloudflare/r2/bucket.get.js.map +1 -0
  280. package/lib/cloudflare/r2/bucket.head.d.ts +4 -0
  281. package/lib/cloudflare/r2/bucket.head.d.ts.map +1 -0
  282. package/lib/cloudflare/r2/bucket.head.js +7 -0
  283. package/lib/cloudflare/r2/bucket.head.js.map +1 -0
  284. package/lib/cloudflare/r2/bucket.js +3 -0
  285. package/lib/cloudflare/r2/bucket.js.map +1 -0
  286. package/lib/cloudflare/r2/bucket.list.d.ts +5 -0
  287. package/lib/cloudflare/r2/bucket.list.d.ts.map +1 -0
  288. package/lib/cloudflare/r2/bucket.list.js +7 -0
  289. package/lib/cloudflare/r2/bucket.list.js.map +1 -0
  290. package/lib/cloudflare/r2/bucket.multipart.d.ts +19 -0
  291. package/lib/cloudflare/r2/bucket.multipart.d.ts.map +1 -0
  292. package/lib/cloudflare/r2/bucket.multipart.js +25 -0
  293. package/lib/cloudflare/r2/bucket.multipart.js.map +1 -0
  294. package/lib/cloudflare/r2/bucket.provider.d.ts +5 -0
  295. package/lib/cloudflare/r2/bucket.provider.d.ts.map +1 -0
  296. package/lib/cloudflare/r2/bucket.provider.js +66 -0
  297. package/lib/cloudflare/r2/bucket.provider.js.map +1 -0
  298. package/lib/cloudflare/r2/bucket.put.d.ts +6 -0
  299. package/lib/cloudflare/r2/bucket.put.d.ts.map +1 -0
  300. package/lib/cloudflare/r2/bucket.put.js +8 -0
  301. package/lib/cloudflare/r2/bucket.put.js.map +1 -0
  302. package/lib/cloudflare/r2/index.d.ts +10 -0
  303. package/lib/cloudflare/r2/index.d.ts.map +1 -0
  304. package/lib/cloudflare/r2/index.js +10 -0
  305. package/lib/cloudflare/r2/index.js.map +1 -0
  306. package/lib/cloudflare/stream.d.ts +10 -0
  307. package/lib/cloudflare/stream.d.ts.map +1 -0
  308. package/lib/cloudflare/stream.js +16 -0
  309. package/lib/cloudflare/stream.js.map +1 -0
  310. package/lib/cloudflare/worker/assets.fetch.d.ts +8 -0
  311. package/lib/cloudflare/worker/assets.fetch.d.ts.map +1 -0
  312. package/lib/cloudflare/worker/assets.fetch.js +11 -0
  313. package/lib/cloudflare/worker/assets.fetch.js.map +1 -0
  314. package/lib/cloudflare/worker/assets.provider.d.ts +66 -0
  315. package/lib/cloudflare/worker/assets.provider.d.ts.map +1 -0
  316. package/lib/cloudflare/worker/assets.provider.js +145 -0
  317. package/lib/cloudflare/worker/assets.provider.js.map +1 -0
  318. package/lib/cloudflare/worker/index.d.ts +6 -0
  319. package/lib/cloudflare/worker/index.d.ts.map +1 -0
  320. package/lib/cloudflare/worker/index.js +5 -0
  321. package/lib/cloudflare/worker/index.js.map +1 -0
  322. package/lib/cloudflare/worker/worker.d.ts +67 -0
  323. package/lib/cloudflare/worker/worker.d.ts.map +1 -0
  324. package/lib/cloudflare/worker/worker.handler.d.ts +11 -0
  325. package/lib/cloudflare/worker/worker.handler.d.ts.map +1 -0
  326. package/lib/cloudflare/worker/worker.handler.js +15 -0
  327. package/lib/cloudflare/worker/worker.handler.js.map +1 -0
  328. package/lib/cloudflare/worker/worker.js +4 -0
  329. package/lib/cloudflare/worker/worker.js.map +1 -0
  330. package/lib/cloudflare/worker/worker.provider.d.ts +10 -0
  331. package/lib/cloudflare/worker/worker.provider.d.ts.map +1 -0
  332. package/lib/cloudflare/worker/worker.provider.js +193 -0
  333. package/lib/cloudflare/worker/worker.provider.js.map +1 -0
  334. package/lib/cloudflare/worker/worker.serve.d.ts +39 -0
  335. package/lib/cloudflare/worker/worker.serve.d.ts.map +1 -0
  336. package/lib/cloudflare/worker/worker.serve.js +4 -0
  337. package/lib/cloudflare/worker/worker.serve.js.map +1 -0
  338. package/lib/destroy.d.ts +1 -3
  339. package/lib/destroy.d.ts.map +1 -1
  340. package/lib/destroy.js +5 -0
  341. package/lib/destroy.js.map +1 -1
  342. package/lib/dot-alchemy.d.ts +3 -2
  343. package/lib/dot-alchemy.d.ts.map +1 -1
  344. package/lib/dot-alchemy.js +3 -2
  345. package/lib/dot-alchemy.js.map +1 -1
  346. package/lib/esbuild.d.ts +28 -0
  347. package/lib/esbuild.d.ts.map +1 -0
  348. package/lib/esbuild.js +63 -0
  349. package/lib/esbuild.js.map +1 -0
  350. package/lib/index.d.ts +1 -0
  351. package/lib/index.d.ts.map +1 -1
  352. package/lib/index.js +4 -0
  353. package/lib/index.js.map +1 -1
  354. package/lib/plan.d.ts +19 -8
  355. package/lib/plan.d.ts.map +1 -1
  356. package/lib/plan.js +144 -72
  357. package/lib/plan.js.map +1 -1
  358. package/lib/policy.d.ts +19 -1
  359. package/lib/policy.d.ts.map +1 -1
  360. package/lib/policy.js +10 -1
  361. package/lib/policy.js.map +1 -1
  362. package/lib/provider.d.ts +2 -2
  363. package/lib/provider.d.ts.map +1 -1
  364. package/lib/resource.d.ts +2 -10
  365. package/lib/resource.d.ts.map +1 -1
  366. package/lib/resource.js +1 -0
  367. package/lib/resource.js.map +1 -1
  368. package/lib/runtime.d.ts +1 -1
  369. package/lib/runtime.d.ts.map +1 -1
  370. package/lib/schema.d.ts +37 -0
  371. package/lib/schema.d.ts.map +1 -0
  372. package/lib/schema.js +61 -0
  373. package/lib/schema.js.map +1 -0
  374. package/lib/sha256.d.ts +5 -0
  375. package/lib/sha256.d.ts.map +1 -0
  376. package/lib/sha256.js +16 -0
  377. package/lib/sha256.js.map +1 -0
  378. package/lib/state.d.ts +3 -2
  379. package/lib/state.d.ts.map +1 -1
  380. package/lib/state.js +3 -2
  381. package/lib/state.js.map +1 -1
  382. package/lib/tags.d.ts +17 -0
  383. package/lib/tags.d.ts.map +1 -0
  384. package/lib/tags.js +22 -0
  385. package/lib/tags.js.map +1 -0
  386. package/lib/test.d.ts +14 -0
  387. package/lib/test.d.ts.map +1 -0
  388. package/lib/test.js +28 -0
  389. package/lib/test.js.map +1 -0
  390. package/lib/tsconfig.test.tsbuildinfo +1 -0
  391. package/lib/type.d.ts +3 -0
  392. package/lib/type.d.ts.map +1 -0
  393. package/lib/type.js +3 -0
  394. package/lib/type.js.map +1 -0
  395. package/package.json +115 -3
  396. package/src/app.ts +8 -7
  397. package/src/apply.ts +251 -93
  398. package/src/aws/account.ts +37 -0
  399. package/src/aws/arn.ts +1 -0
  400. package/src/aws/assets.ts +8 -0
  401. package/src/aws/bundle.ts +5 -0
  402. package/src/aws/client.ts +47 -0
  403. package/src/aws/credentials.ts +409 -0
  404. package/src/aws/dynamodb/attribute-value.ts +240 -0
  405. package/src/aws/dynamodb/client.ts +20 -0
  406. package/src/aws/dynamodb/expr.ts +90 -0
  407. package/src/aws/dynamodb/index.ts +12 -0
  408. package/src/aws/dynamodb/projection.ts +159 -0
  409. package/src/aws/dynamodb/secondary-index.ts +45 -0
  410. package/src/aws/dynamodb/table.get-item.ts +177 -0
  411. package/src/aws/dynamodb/table.provider.ts +280 -0
  412. package/src/aws/dynamodb/table.ts +156 -0
  413. package/src/aws/ec2/client.ts +20 -0
  414. package/src/aws/ec2/index.ts +3 -0
  415. package/src/aws/ec2/vpc.provider.ts +285 -0
  416. package/src/aws/ec2/vpc.ts +152 -0
  417. package/src/aws/iam.ts +30 -0
  418. package/src/aws/index.ts +54 -0
  419. package/src/aws/lambda/client.ts +14 -0
  420. package/src/aws/lambda/consume.ts +63 -0
  421. package/src/aws/lambda/function.handler.ts +30 -0
  422. package/src/aws/lambda/function.invoke.ts +40 -0
  423. package/src/aws/lambda/function.provider.ts +655 -0
  424. package/src/aws/lambda/function.ts +45 -0
  425. package/src/aws/lambda/index.ts +9 -0
  426. package/src/aws/lambda/serve.ts +29 -0
  427. package/src/aws/parse-ini.ts +80 -0
  428. package/src/aws/profile.ts +6 -0
  429. package/src/aws/region.ts +37 -0
  430. package/src/aws/s3.ts +10 -0
  431. package/src/aws/sqs/client.ts +20 -0
  432. package/src/aws/sqs/index.ts +6 -0
  433. package/src/aws/sqs/queue.consume.ts +13 -0
  434. package/src/aws/sqs/queue.event-source.ts +253 -0
  435. package/src/aws/sqs/queue.provider.ts +94 -0
  436. package/src/aws/sqs/queue.send-message.ts +51 -0
  437. package/src/aws/sqs/queue.ts +86 -0
  438. package/src/aws/sts.ts +13 -0
  439. package/src/aws/zip.ts +17 -0
  440. package/src/binding.ts +121 -25
  441. package/src/capability.ts +44 -0
  442. package/src/cli/approve.tsx +30 -0
  443. package/src/cli/clack.ts +22 -0
  444. package/src/cli/components/ApprovePlan.tsx +44 -0
  445. package/src/cli/components/Plan.tsx +154 -0
  446. package/src/cli/components/PlanProgress.tsx +206 -0
  447. package/src/cli/index.ts +6 -0
  448. package/src/cli/main.ts +0 -0
  449. package/src/cli/plan.ts +16 -0
  450. package/src/cli/progress.tsx +46 -0
  451. package/src/cli/spinner.ts +14 -0
  452. package/src/cloudflare/api.ts +152 -0
  453. package/src/cloudflare/context.ts +49 -0
  454. package/src/cloudflare/index.ts +6 -0
  455. package/src/cloudflare/kv/index.ts +3 -0
  456. package/src/cloudflare/kv/namespace.binding.ts +25 -0
  457. package/src/cloudflare/kv/namespace.client.ts +70 -0
  458. package/src/cloudflare/kv/namespace.provider.ts +99 -0
  459. package/src/cloudflare/kv/namespace.ts +29 -0
  460. package/src/cloudflare/live.ts +38 -0
  461. package/src/cloudflare/r2/bucket.binding.ts +27 -0
  462. package/src/cloudflare/r2/bucket.client.ts +22 -0
  463. package/src/cloudflare/r2/bucket.del.ts +11 -0
  464. package/src/cloudflare/r2/bucket.get.ts +13 -0
  465. package/src/cloudflare/r2/bucket.head.ts +11 -0
  466. package/src/cloudflare/r2/bucket.list.ts +12 -0
  467. package/src/cloudflare/r2/bucket.multipart.ts +55 -0
  468. package/src/cloudflare/r2/bucket.provider.ts +83 -0
  469. package/src/cloudflare/r2/bucket.put.ts +17 -0
  470. package/src/cloudflare/r2/bucket.ts +38 -0
  471. package/src/cloudflare/r2/index.ts +9 -0
  472. package/src/cloudflare/stream.ts +21 -0
  473. package/src/cloudflare/worker/assets.fetch.ts +27 -0
  474. package/src/cloudflare/worker/assets.provider.ts +249 -0
  475. package/src/cloudflare/worker/index.ts +6 -0
  476. package/src/cloudflare/worker/worker.handler.ts +39 -0
  477. package/src/cloudflare/worker/worker.provider.ts +246 -0
  478. package/src/cloudflare/worker/worker.serve.ts +19 -0
  479. package/src/cloudflare/worker/worker.ts +76 -0
  480. package/src/destroy.ts +6 -3
  481. package/src/dot-alchemy.ts +3 -2
  482. package/src/esbuild.ts +98 -0
  483. package/src/index.ts +5 -0
  484. package/src/plan.ts +233 -120
  485. package/src/policy.ts +55 -2
  486. package/src/provider.ts +2 -2
  487. package/src/resource.ts +3 -2
  488. package/src/runtime.ts +1 -1
  489. package/src/schema.ts +102 -0
  490. package/src/sha256.ts +23 -0
  491. package/src/state.ts +3 -2
  492. package/src/tags.ts +38 -0
  493. package/src/test.ts +71 -0
  494. package/src/type.ts +2 -0
@@ -0,0 +1,29 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Lambda from "./function.ts";
3
+
4
+ import type {
5
+ LambdaFunctionURLEvent as FunctionURLEvent,
6
+ LambdaFunctionURLResult as FunctionURLResult,
7
+ } from "aws-lambda";
8
+ export type {
9
+ LambdaFunctionURLEvent as FunctionURLEvent,
10
+ LambdaFunctionURLResult as FunctionURLResult,
11
+ } from "aws-lambda";
12
+
13
+ export const serve =
14
+ <const ID extends string, Req>(
15
+ id: ID,
16
+ {
17
+ fetch,
18
+ }: {
19
+ fetch: (
20
+ event: FunctionURLEvent,
21
+ context: Lambda.Context,
22
+ ) => Effect.Effect<FunctionURLResult, never, Req>;
23
+ },
24
+ ) =>
25
+ <const Props extends Lambda.FunctionProps.Simplified<Req>>(props: Props) =>
26
+ Lambda.Function(id, { handle: fetch })({
27
+ ...props,
28
+ url: true,
29
+ });
@@ -0,0 +1,80 @@
1
+ import type { ParsedIniData } from "@smithy/types";
2
+ import { IniSectionType } from "@smithy/types";
3
+
4
+ const CONFIG_PREFIX_SEPARATOR = ".";
5
+
6
+ const prefixKeyRegex = /^([\w-]+)\s(["'])?([\w-@\+\.%:/]+)\2$/;
7
+ const profileNameBlockList = ["__proto__", "profile __proto__"];
8
+
9
+ export const parseIni = (iniData: string): ParsedIniData => {
10
+ const map: ParsedIniData = {};
11
+
12
+ let currentSection: string | undefined;
13
+ let currentSubSection: string | undefined;
14
+
15
+ for (const iniLine of iniData.split(/\r?\n/)) {
16
+ const trimmedLine = iniLine.split(/(^|\s)[;#]/)[0].trim(); // remove comments and trim
17
+ const isSection: boolean =
18
+ trimmedLine[0] === "[" && trimmedLine[trimmedLine.length - 1] === "]";
19
+ if (isSection) {
20
+ // New section found. Reset currentSection and currentSubSection.
21
+ currentSection = undefined;
22
+ currentSubSection = undefined;
23
+
24
+ const sectionName = trimmedLine.substring(1, trimmedLine.length - 1);
25
+ const matches = prefixKeyRegex.exec(sectionName);
26
+ if (matches) {
27
+ const [, prefix, , name] = matches;
28
+ // Add prefix, if the section name starts with `profile`, `sso-session` or `services`.
29
+ if (Object.values(IniSectionType).includes(prefix as IniSectionType)) {
30
+ currentSection = [prefix, name].join(CONFIG_PREFIX_SEPARATOR);
31
+ }
32
+ } else {
33
+ // If the section name does not match the regex, use the section name as is.
34
+ currentSection = sectionName;
35
+ }
36
+
37
+ if (profileNameBlockList.includes(sectionName)) {
38
+ throw new Error(`Found invalid profile name "${sectionName}"`);
39
+ }
40
+ } else if (currentSection) {
41
+ const indexOfEqualsSign = trimmedLine.indexOf("=");
42
+ if (![0, -1].includes(indexOfEqualsSign)) {
43
+ const [name, value]: [string, string] = [
44
+ trimmedLine.substring(0, indexOfEqualsSign).trim(),
45
+ trimmedLine.substring(indexOfEqualsSign + 1).trim(),
46
+ ];
47
+ if (value === "") {
48
+ currentSubSection = name;
49
+ } else {
50
+ if (currentSubSection && iniLine.trimStart() === iniLine) {
51
+ // Reset currentSubSection if there is no whitespace
52
+ currentSubSection = undefined;
53
+ }
54
+ map[currentSection] = map[currentSection] || {};
55
+ const key = currentSubSection
56
+ ? [currentSubSection, name].join(CONFIG_PREFIX_SEPARATOR)
57
+ : name;
58
+ map[currentSection][key] = value;
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ return map;
65
+ };
66
+
67
+ export const parseSSOSessionData = (data: ParsedIniData): ParsedIniData =>
68
+ Object.entries(data)
69
+ // filter out non sso-session keys
70
+ .filter(([key]) =>
71
+ key.startsWith(IniSectionType.SSO_SESSION + CONFIG_PREFIX_SEPARATOR),
72
+ )
73
+ // replace sso-session key with sso-session name
74
+ .reduce(
75
+ (acc, [key, value]) => ({
76
+ ...acc,
77
+ [key.substring(key.indexOf(CONFIG_PREFIX_SEPARATOR) + 1)]: value,
78
+ }),
79
+ {},
80
+ );
@@ -0,0 +1,6 @@
1
+ import * as Context from "effect/Context";
2
+
3
+ export class AwsProfile extends Context.Tag("AWS::Profile")<
4
+ AwsProfile,
5
+ string
6
+ >() {}
@@ -0,0 +1,37 @@
1
+ import * as Context from "effect/Context";
2
+ import * as Data from "effect/Data";
3
+ import * as Effect from "effect/Effect";
4
+ import * as Layer from "effect/Layer";
5
+
6
+ export type RegionID = string;
7
+
8
+ export class Region extends Context.Tag("AWS::Region")<Region, RegionID>() {}
9
+
10
+ export const of = (region: string) => Layer.succeed(Region, region);
11
+
12
+ export const fromEnvOrElse = (region: string) =>
13
+ Layer.succeed(Region, process.env.AWS_REGION ?? region);
14
+
15
+ export class EnvironmentVariableNotSet extends Data.TaggedError(
16
+ "EnvironmentVariableNotSet",
17
+ )<{
18
+ message: string;
19
+ variable: string;
20
+ }> {}
21
+
22
+ export const fromEnv = () =>
23
+ Layer.effect(
24
+ Region,
25
+ Effect.gen(function* () {
26
+ const region = process.env.AWS_REGION;
27
+ if (!region) {
28
+ return yield* Effect.fail(
29
+ new EnvironmentVariableNotSet({
30
+ message: "AWS_REGION is not set",
31
+ variable: "AWS_REGION",
32
+ }),
33
+ );
34
+ }
35
+ return region;
36
+ }),
37
+ );
package/src/aws/s3.ts ADDED
@@ -0,0 +1,10 @@
1
+ import * as Context from "effect/Context";
2
+ import { S3 } from "itty-aws/s3";
3
+ import { createAWSServiceClientLayer } from "./client.ts";
4
+
5
+ export class S3Client extends Context.Tag("AWS::S3::Client")<S3Client, S3>() {}
6
+
7
+ export const client = createAWSServiceClientLayer<typeof S3Client, S3>(
8
+ S3Client,
9
+ S3,
10
+ );
@@ -0,0 +1,20 @@
1
+ import * as Context from "effect/Context";
2
+ import * as Layer from "effect/Layer";
3
+
4
+ import { SQS } from "itty-aws/sqs";
5
+ import { createAWSServiceClientLayer } from "../client.ts";
6
+ import * as Credentials from "../credentials.ts";
7
+ import * as Region from "../region.ts";
8
+
9
+ export class SQSClient extends Context.Tag("AWS.SQS.Client")<
10
+ SQSClient,
11
+ SQS
12
+ >() {}
13
+
14
+ export const client = createAWSServiceClientLayer<typeof SQSClient, SQS>(
15
+ SQSClient,
16
+ SQS,
17
+ );
18
+
19
+ export const clientFromEnv = () =>
20
+ Layer.provide(client(), Layer.merge(Credentials.fromEnv(), Region.fromEnv()));
@@ -0,0 +1,6 @@
1
+ export * from "./client.ts";
2
+ export * from "./queue.consume.ts";
3
+ export * from "./queue.event-source.ts";
4
+ export * from "./queue.provider.ts";
5
+ export * from "./queue.send-message.ts";
6
+ export * from "./queue.ts";
@@ -0,0 +1,13 @@
1
+ import { type Capability } from "alchemy-effect";
2
+ import type * as lambda from "aws-lambda";
3
+ import { Queue } from "./queue.ts";
4
+
5
+ export type QueueRecord<Data> = Omit<lambda.SQSRecord, "body"> & {
6
+ body: Data;
7
+ };
8
+
9
+ export type QueueEvent<Data> = Omit<lambda.SQSEvent, "Records"> & {
10
+ Records: QueueRecord<Data>[];
11
+ };
12
+
13
+ export interface Consume<Q = Queue> extends Capability<"AWS.SQS.Consume", Q> {}
@@ -0,0 +1,253 @@
1
+ import { Binding, type From } from "alchemy-effect";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Schedule from "effect/Schedule";
4
+ import type * as Lambda from "itty-aws/lambda";
5
+ import { createTagger, hasTags } from "../../tags.ts";
6
+ import { Account } from "../account.ts";
7
+ import {
8
+ Function,
9
+ LambdaClient,
10
+ type FunctionBinding,
11
+ } from "../lambda/index.ts";
12
+ import { Region } from "../region.ts";
13
+ import type { Consume } from "./queue.consume.ts";
14
+ import { Queue, type QueueAttrs, type QueueProps } from "./queue.ts";
15
+
16
+ export interface QueueEventSourceProps {
17
+ batchSize?: number;
18
+ maxBatchingWindow?: number;
19
+ scalingConfig?: Lambda.ScalingConfig;
20
+ }
21
+
22
+ export interface QueueEventSourceAttr extends FunctionBinding {
23
+ uuid: string;
24
+ }
25
+
26
+ export interface QueueEventSource<
27
+ Q extends Queue,
28
+ Props extends QueueEventSourceProps,
29
+ > extends Binding<
30
+ Function,
31
+ Consume<From<Q>>,
32
+ Props,
33
+ QueueEventSourceAttr,
34
+ "QueueEventSource"
35
+ > {}
36
+
37
+ export const QueueEventSource = Binding<
38
+ <Q extends Queue, const Props extends QueueEventSourceProps>(
39
+ queue: Q,
40
+ props?: Props,
41
+ ) => QueueEventSource<Q, Props>
42
+ >(Function, "AWS.SQS.Consume", "QueueEventSource");
43
+
44
+ export const queueEventSourceProvider = () =>
45
+ QueueEventSource.provider.effect(
46
+ // @ts-expect-error
47
+ Effect.gen(function* () {
48
+ const region = yield* Region;
49
+ const accountId = yield* Account;
50
+ const lambda = yield* LambdaClient;
51
+ const tagged = yield* createTagger();
52
+
53
+ const findEventSourceMapping: (
54
+ queue: {
55
+ id: string;
56
+ attr: QueueAttrs<QueueProps<any>>;
57
+ props: QueueProps<any>;
58
+ },
59
+ functionName: string,
60
+ marker?: string,
61
+ ) => Effect.Effect<Lambda.EventSourceMappingConfiguration | undefined> =
62
+ Effect.fn(function* (queue, functionName, marker) {
63
+ const retry = Effect.retry({
64
+ while: (
65
+ e:
66
+ | Lambda.InvalidParameterValueException
67
+ | Lambda.ResourceNotFoundException
68
+ | Lambda.ServiceException
69
+ | Lambda.TooManyRequestsException
70
+ | Lambda.CommonAwsError
71
+ | any,
72
+ ) =>
73
+ // TODO(sam): figure out how to write a function that generalizes this or upstream into itty-aws
74
+ e._tag === "InternalFailure" ||
75
+ e._tag === "RequestExpired" ||
76
+ e._tag === "ServiceException" ||
77
+ e._tag === "ServiceUnavailable" ||
78
+ e._tag === "ThrottlingException" ||
79
+ e._tag === "TooManyRequestsException",
80
+ schedule: Schedule.exponential(100),
81
+ });
82
+
83
+ // TODO(sam): return an accepted error
84
+ // const orDie = Effect.catchAll((e) => Effect.die(e));
85
+
86
+ const mappings = yield* lambda
87
+ .listEventSourceMappings({
88
+ FunctionName: functionName,
89
+ Marker: marker,
90
+ })
91
+ .pipe(retry, Effect.orDie);
92
+ const mapping = mappings.EventSourceMappings?.find(
93
+ (mapping) => mapping.EventSourceArn === queue.attr.queueArn,
94
+ );
95
+ if (mapping?.EventSourceArn) {
96
+ const { Tags } = yield* lambda
97
+ .listTags({
98
+ Resource: `arn:aws:lambda:${region}:${accountId}:event-source-mapping:${mapping.UUID!}`,
99
+ })
100
+ .pipe(retry, Effect.orDie);
101
+ if (hasTags(tagged(queue.id), Tags)) {
102
+ return mapping;
103
+ }
104
+ return undefined;
105
+ }
106
+ if (mappings.NextMarker) {
107
+ return yield* findEventSourceMapping(
108
+ queue,
109
+ functionName,
110
+ mappings.NextMarker,
111
+ );
112
+ }
113
+ return undefined;
114
+ });
115
+
116
+ const createFunctionBinding = (queue: {
117
+ attr: { queueArn: string };
118
+ }) => ({
119
+ // we need the policies to be present before the event source mapping is created
120
+ policyStatements: [
121
+ {
122
+ Sid: "AWS.SQS.Consume",
123
+ Effect: "Allow" as const,
124
+ Action: [
125
+ "sqs:ReceiveMessage",
126
+ "sqs:DeleteMessage",
127
+ "sqs:ChangeMessageVisibility",
128
+ ],
129
+ Resource: [queue.attr.queueArn],
130
+ },
131
+ ],
132
+ });
133
+
134
+ return {
135
+ attach: ({ source: queue }) => {
136
+ console.log("attaching queue event source", queue.id);
137
+ return {
138
+ // we need the policies to be present before the event source mapping is created
139
+ policyStatements: [
140
+ {
141
+ Sid: "AWS.SQS.Consume",
142
+ Effect: "Allow" as const,
143
+ Action: [
144
+ "sqs:ReceiveMessage",
145
+ "sqs:DeleteMessage",
146
+ "sqs:ChangeMessageVisibility",
147
+ "sqs:GetQueueAttributes",
148
+ "sqs:GetQueueUrl",
149
+ ],
150
+ Resource: [queue.attr.queueArn],
151
+ },
152
+ ],
153
+ };
154
+ },
155
+ postattach: Effect.fn(function* ({
156
+ source: queue,
157
+ props: { batchSize, maxBatchingWindow, scalingConfig } = {},
158
+ attr,
159
+ target: {
160
+ attr: { functionName },
161
+ },
162
+ }) {
163
+ console.log(
164
+ "postattaching queue event source",
165
+ queue.id,
166
+ functionName,
167
+ );
168
+ const config:
169
+ | Lambda.CreateEventSourceMappingRequest
170
+ | Lambda.UpdateEventSourceMappingRequest = {
171
+ FunctionName: functionName,
172
+ EventSourceArn: queue.attr.queueArn,
173
+ BatchSize: batchSize,
174
+ MaximumBatchingWindowInSeconds: maxBatchingWindow,
175
+ ScalingConfig: scalingConfig,
176
+ Enabled: true,
177
+ FunctionResponseTypes: ["ReportBatchItemFailures"],
178
+ // https://docs.aws.amazon.com/lambda/latest/dg/monitoring-metrics-types.html#event-source-mapping-metrics
179
+ MetricsConfig: { Metrics: ["EventCount"] },
180
+ // KMSKeyArn: (encrypted FilterCriteria)
181
+
182
+ // See: https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html
183
+ // FilterCriteria: {
184
+ // Filters: [{Pattern: ""}]
185
+ // }
186
+ Tags: tagged(queue.id),
187
+ };
188
+
189
+ const findOrDie = findEventSourceMapping(queue, functionName).pipe(
190
+ Effect.flatMap((mapping) =>
191
+ mapping
192
+ ? Effect.succeed(mapping)
193
+ : Effect.die(
194
+ // how the fuck did we get here?
195
+ new Error(
196
+ `QueueEventSource(${queue.id}) not found on function ${functionName}`,
197
+ ),
198
+ ),
199
+ ),
200
+ );
201
+
202
+ const eventSourceMapping = yield* (
203
+ attr?.uuid
204
+ ? lambda.updateEventSourceMapping({
205
+ ...config,
206
+ UUID: attr.uuid,
207
+ })
208
+ : lambda.createEventSourceMapping(config)
209
+ ).pipe(
210
+ Effect.catchTags({
211
+ ResourceConflictException: () => findOrDie,
212
+ ResourceNotFoundException: () => findOrDie,
213
+ }),
214
+ Effect.retry({
215
+ // It takes a few seconds for the IAM policy to propagate, so retry the following error
216
+ while: (e) =>
217
+ e.name === "InvalidParameterValueException" &&
218
+ e.message?.includes(
219
+ "The function execution role does not have permissions to call",
220
+ ),
221
+ schedule: Schedule.exponential(100),
222
+ }),
223
+ );
224
+ return {
225
+ ...attr,
226
+ uuid: eventSourceMapping.UUID,
227
+ };
228
+ }),
229
+ detach: Effect.fn(function* ({
230
+ source: queue,
231
+ target: {
232
+ attr: { functionName },
233
+ },
234
+ attr,
235
+ }) {
236
+ const uuid =
237
+ attr?.uuid ??
238
+ (yield* findEventSourceMapping(queue, functionName))?.UUID!;
239
+ if (uuid) {
240
+ // we found (or were aware of) the event source mapping, so we can delete it
241
+ yield* (
242
+ lambda
243
+ .deleteEventSourceMapping({
244
+ UUID: uuid,
245
+ })
246
+ // TODO(sam): handle errors properly
247
+ .pipe(Effect.catchAll(() => Effect.void))
248
+ );
249
+ }
250
+ }),
251
+ };
252
+ }),
253
+ );
@@ -0,0 +1,94 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Schedule from "effect/Schedule";
3
+
4
+ import { App, type ProviderService } from "alchemy-effect";
5
+ import { Account } from "../account.ts";
6
+ import { Region } from "../region.ts";
7
+ import { SQSClient } from "./client.ts";
8
+ import { Queue, type QueueProps } from "./queue.ts";
9
+
10
+ export const queueProvider = () =>
11
+ Queue.provider.effect(
12
+ Effect.gen(function* () {
13
+ const sqs = yield* SQSClient;
14
+ const app = yield* App;
15
+ const region = yield* Region;
16
+ const accountId = yield* Account;
17
+ const createQueueName = (id: string, props: QueueProps) =>
18
+ props.queueName ??
19
+ `${app.name}-${id}-${app.stage}${props.fifo ? ".fifo" : ""}`;
20
+ const createAttributes = (props: QueueProps) => ({
21
+ FifoQueue: props.fifo ? "true" : "false",
22
+ FifoThroughputLimit: props.fifoThroughputLimit,
23
+ ContentBasedDeduplication: props.contentBasedDeduplication
24
+ ? "true"
25
+ : "false",
26
+ DeduplicationScope: props.deduplicationScope,
27
+ DelaySeconds: props.delaySeconds?.toString(),
28
+ MaximumMessageSize: props.maximumMessageSize?.toString(),
29
+ MessageRetentionPeriod: props.messageRetentionPeriod?.toString(),
30
+ ReceiveMessageWaitTimeSeconds:
31
+ props.receiveMessageWaitTimeSeconds?.toString(),
32
+ VisibilityTimeout: props.visibilityTimeout?.toString(),
33
+ });
34
+ return {
35
+ diff: Effect.fn(function* ({ id, news, olds }) {
36
+ const oldFifo = olds.fifo ?? false;
37
+ const newFifo = news.fifo ?? false;
38
+ if (oldFifo !== newFifo) {
39
+ return { action: "replace" } as const;
40
+ }
41
+ const oldQueueName = createQueueName(id, olds);
42
+ const newQueueName = createQueueName(id, news);
43
+ if (oldQueueName !== newQueueName) {
44
+ return { action: "replace" } as const;
45
+ }
46
+ return { action: "noop" } as const;
47
+ }),
48
+ create: Effect.fn(function* ({ id, news, session }) {
49
+ const queueName = createQueueName(id, news);
50
+ const response = yield* sqs
51
+ .createQueue({
52
+ QueueName: queueName,
53
+ Attributes: createAttributes(news),
54
+ })
55
+ .pipe(
56
+ Effect.retry({
57
+ while: (e) => e.name === "QueueDeletedRecently",
58
+ schedule: Schedule.fixed(1000).pipe(
59
+ Schedule.tapOutput((i) =>
60
+ session.note(
61
+ `Queue was deleted recently, retrying... ${i + 1}s`,
62
+ ),
63
+ ),
64
+ ),
65
+ }),
66
+ );
67
+ const queueArn =
68
+ `arn:aws:sqs:${region}:${accountId}:${queueName}` as const;
69
+ const queueUrl = response.QueueUrl!;
70
+ yield* session.note(queueUrl);
71
+ return {
72
+ queueName,
73
+ queueUrl,
74
+ queueArn: queueArn,
75
+ };
76
+ }),
77
+ update: Effect.fn(function* ({ news, output, session }) {
78
+ yield* sqs.setQueueAttributes({
79
+ QueueUrl: output.queueUrl,
80
+ Attributes: createAttributes(news),
81
+ });
82
+ yield* session.note(output.queueUrl);
83
+ return output;
84
+ }),
85
+ delete: Effect.fn(function* (input) {
86
+ yield* sqs
87
+ .deleteQueue({
88
+ QueueUrl: input.output.queueUrl,
89
+ })
90
+ .pipe(Effect.catchTag("QueueDoesNotExist", () => Effect.void));
91
+ }),
92
+ } satisfies ProviderService<Queue>;
93
+ }),
94
+ );
@@ -0,0 +1,51 @@
1
+ import * as Effect from "effect/Effect";
2
+
3
+ import {
4
+ Binding,
5
+ declare,
6
+ toEnvKey,
7
+ type Capability,
8
+ type To,
9
+ } from "alchemy-effect";
10
+ import { Function } from "../lambda/index.ts";
11
+ import { SQSClient } from "./client.ts";
12
+ import { Queue } from "./queue.ts";
13
+
14
+ export interface SendMessage<Q = Queue>
15
+ extends Capability<"AWS.SQS.SendMessage", Q> {}
16
+
17
+ export const SendMessage = Binding<
18
+ <Q extends Queue>(queue: Q) => Binding<Function, SendMessage<To<Q>>>
19
+ >(Function, "AWS.SQS.SendMessage");
20
+
21
+ export const sendMessage = <Q extends Queue>(
22
+ queue: Q,
23
+ message: Q["props"]["schema"]["Type"],
24
+ ) =>
25
+ Effect.gen(function* () {
26
+ yield* declare<SendMessage<To<Q>>>();
27
+ const sqs = yield* SQSClient;
28
+ const url = process.env[toEnvKey(queue.id, "QUEUE_URL")]!;
29
+ return yield* sqs.sendMessage({
30
+ QueueUrl: url,
31
+ MessageBody: JSON.stringify(message),
32
+ });
33
+ });
34
+
35
+ export const sendMessageFromLambdaFunction = () =>
36
+ SendMessage.provider.succeed({
37
+ attach: ({ source: queue }) => ({
38
+ env: {
39
+ // ask what attribute is needed to interact? e.g. is it the Queue ARN or the Queue URL?
40
+ [toEnvKey(queue.id, "QUEUE_URL")]: queue.attr.queueUrl,
41
+ },
42
+ policyStatements: [
43
+ {
44
+ Sid: "SendMessage",
45
+ Effect: "Allow",
46
+ Action: ["sqs:SendMessage"], // <- ask LLM how to generate this
47
+ Resource: [queue.attr.queueArn],
48
+ },
49
+ ],
50
+ }),
51
+ });