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,5 @@
1
+ import * as Effect from "effect/Effect";
2
+ import esbuild from "esbuild";
3
+
4
+ export const bundle = (props: esbuild.BuildOptions) =>
5
+ Effect.promise(() => esbuild.build(props));
@@ -0,0 +1,47 @@
1
+ import { LogLevel } from "effect";
2
+ import type * as Context from "effect/Context";
3
+ import * as Effect from "effect/Effect";
4
+ import * as Layer from "effect/Layer";
5
+ import * as Logger from "effect/Logger";
6
+ import * as Redacted from "effect/Redacted";
7
+ import type { AWSClientConfig } from "itty-aws";
8
+ import { Credentials } from "./credentials.ts";
9
+ import { Region } from "./region.ts";
10
+
11
+ export type TagInstance<T> = T extends new (_: never) => infer R ? R : never;
12
+
13
+ export const createAWSServiceClientLayer =
14
+ <Tag extends Context.Tag<any, any>, Client>(
15
+ tag: Tag,
16
+ clss: new (config: AWSClientConfig) => Client,
17
+ ) =>
18
+ () =>
19
+ Layer.effect(
20
+ tag,
21
+ Effect.gen(function* () {
22
+ const region = yield* Region;
23
+ const credentials = yield* Credentials;
24
+ //
25
+ const client = new clss({
26
+ region,
27
+ credentials: {
28
+ accessKeyId: Redacted.value(credentials.accessKeyId),
29
+ secretAccessKey: Redacted.value(credentials.secretAccessKey),
30
+ sessionToken: credentials.sessionToken
31
+ ? Redacted.value(credentials.sessionToken)
32
+ : undefined,
33
+ },
34
+ });
35
+ return new Proxy(client as any, {
36
+ get:
37
+ (target: any, prop) =>
38
+ (...args: any[]) =>
39
+ target[prop](...args).pipe(
40
+ // TODO(sam): make it easier to set log lever for a client
41
+ Logger.withMinimumLogLevel(
42
+ process.env.DEBUG ? LogLevel.Debug : LogLevel.Info,
43
+ ),
44
+ ),
45
+ });
46
+ }),
47
+ ) as Layer.Layer<TagInstance<Tag>, never, Region | Credentials>;
@@ -0,0 +1,409 @@
1
+ import {
2
+ fromContainerMetadata as _fromContainerMetadata,
3
+ fromEnv as _fromEnv,
4
+ fromHttp as _fromHttp,
5
+ fromIni as _fromIni,
6
+ fromInstanceMetadata as _fromInstanceMetadata,
7
+ fromNodeProviderChain as _fromNodeProviderChain,
8
+ fromProcess as _fromProcess,
9
+ fromTokenFile as _fromTokenFile,
10
+ fromWebToken as _fromWebToken,
11
+ } from "@aws-sdk/credential-providers";
12
+
13
+ import { FileSystem, HttpClient } from "@effect/platform";
14
+ import * as ini from "@smithy/shared-ini-file-loader";
15
+ import {
16
+ type AwsCredentialIdentity,
17
+ type AwsCredentialIdentityProvider,
18
+ } from "@smithy/types";
19
+ import * as Console from "effect/Console";
20
+ import * as Context from "effect/Context";
21
+ import * as Data from "effect/Data";
22
+ import * as Effect from "effect/Effect";
23
+ import * as Layer from "effect/Layer";
24
+ import * as Option from "effect/Option";
25
+ import * as Redacted from "effect/Redacted";
26
+ import { createHash } from "node:crypto";
27
+ import * as path from "node:path";
28
+ import { parseIni, parseSSOSessionData } from "./parse-ini.ts";
29
+ import { AwsProfile } from "./profile.ts";
30
+
31
+ export class Credentials extends Context.Tag("AWS::Credentials")<
32
+ Credentials,
33
+ {
34
+ accessKeyId: Redacted.Redacted<string>;
35
+ secretAccessKey: Redacted.Redacted<string>;
36
+ sessionToken: Redacted.Redacted<string> | undefined;
37
+ expiration?: number;
38
+ }
39
+ >() {}
40
+
41
+ export const fromAwsCredentialIdentity = (identity: AwsCredentialIdentity) =>
42
+ Credentials.of({
43
+ accessKeyId: Redacted.make(identity.accessKeyId),
44
+ secretAccessKey: Redacted.make(identity.secretAccessKey),
45
+ sessionToken: identity.sessionToken
46
+ ? Redacted.make(identity.sessionToken)
47
+ : undefined,
48
+ expiration: identity.expiration?.getTime(),
49
+ });
50
+
51
+ const createLayer = (provider: (config: {}) => AwsCredentialIdentityProvider) =>
52
+ Layer.effect(
53
+ Credentials,
54
+ Effect.gen(function* () {
55
+ return fromAwsCredentialIdentity(
56
+ yield* Effect.promise(() => provider({})()),
57
+ );
58
+ }),
59
+ );
60
+
61
+ export const fromCredentials = (credentials: AwsCredentialIdentity) =>
62
+ Layer.succeed(Credentials, fromAwsCredentialIdentity(credentials));
63
+
64
+ export const fromEnv = () => createLayer(_fromEnv);
65
+
66
+ export const fromChain = () => createLayer(() => _fromNodeProviderChain());
67
+
68
+ // export const fromSSO = () => createLayer(_fromSSO);
69
+
70
+ export const fromIni = () => createLayer(_fromIni);
71
+
72
+ export const fromContainerMetadata = () => createLayer(_fromContainerMetadata);
73
+
74
+ export const fromHttp = () => createLayer(_fromHttp);
75
+
76
+ export const fromInstanceMetadata = (
77
+ ...parameters: Parameters<typeof _fromInstanceMetadata>
78
+ ) => createLayer(() => _fromInstanceMetadata(...parameters));
79
+
80
+ export const fromProcess = () => createLayer(_fromProcess);
81
+
82
+ export const fromTokenFile = () => createLayer(_fromTokenFile);
83
+
84
+ export const fromWebToken = (...parameters: Parameters<typeof _fromWebToken>) =>
85
+ createLayer(() => _fromWebToken(...parameters));
86
+
87
+ export const ssoRegion = (region: string) => Layer.succeed(SsoRegion, region);
88
+
89
+ /**
90
+ * The time window (5 mins) that SDK will treat the SSO token expires in before the defined expiration date in token.
91
+ * This is needed because server side may have invalidated the token before the defined expiration date.
92
+ */
93
+ const EXPIRE_WINDOW_MS = 5 * 60 * 1000;
94
+
95
+ const REFRESH_MESSAGE = `To refresh this SSO session run 'aws sso login' with the corresponding profile.`;
96
+
97
+ export class SsoRegion extends Context.Tag("AWS::SsoRegion")<
98
+ SsoRegion,
99
+ string
100
+ >() {}
101
+ export class SsoStartUrl extends Context.Tag("AWS::SsoStartUrl")<
102
+ SsoStartUrl,
103
+ string
104
+ >() {}
105
+
106
+ export class ProfileNotFound extends Data.TaggedError(
107
+ "Alchemy::AWS::ProfileNotFound",
108
+ )<{
109
+ message: string;
110
+ profile: string;
111
+ }> {}
112
+
113
+ export class ConflictingSSORegion extends Data.TaggedError(
114
+ "Alchemy::AWS::ConflictingSSORegion",
115
+ )<{
116
+ message: string;
117
+ ssoRegion: string;
118
+ profile: string;
119
+ }> {}
120
+
121
+ export class ConflictingSSOStartUrl extends Data.TaggedError(
122
+ "Alchemy::AWS::ConflictingSSOStartUrl",
123
+ )<{
124
+ message: string;
125
+ ssoStartUrl: string;
126
+ profile: string;
127
+ }> {}
128
+
129
+ export class InvalidSSOProfile extends Data.TaggedError(
130
+ "Alchemy::AWS::InvalidSSOProfile",
131
+ )<{
132
+ message: string;
133
+ profile: string;
134
+ missingFields: string[];
135
+ }> {}
136
+
137
+ export class InvalidSSOToken extends Data.TaggedError(
138
+ "Alchemy::AWS::InvalidSSOToken",
139
+ )<{
140
+ message: string;
141
+ sso_session: string;
142
+ }> {}
143
+
144
+ export class ExpiredSSOToken extends Data.TaggedError(
145
+ "Alchemy::AWS::ExpiredSSOToken",
146
+ )<{
147
+ message: string;
148
+ profile: string;
149
+ }> {}
150
+
151
+ export interface AwsProfileConfig {
152
+ sso_session?: string;
153
+ sso_account_id?: string;
154
+ sso_role_name?: string;
155
+ region?: string;
156
+ output?: string;
157
+ sso_start_url?: string;
158
+ sso_region?: string;
159
+ }
160
+ export interface SsoProfileConfig extends AwsProfileConfig {
161
+ sso_start_url: string;
162
+ sso_region: string;
163
+ sso_account_id: string;
164
+ sso_role_name: string;
165
+ }
166
+
167
+ export const fromSSO = () =>
168
+ Layer.effect(
169
+ Credentials,
170
+ Effect.gen(function* () {
171
+ const client = yield* HttpClient.HttpClient;
172
+ const fs = yield* FileSystem.FileSystem;
173
+ const profileName = Option.getOrElse(
174
+ yield* Effect.serviceOption(AwsProfile),
175
+ () => "default",
176
+ );
177
+
178
+ const profiles: {
179
+ [profileName: string]: AwsProfileConfig;
180
+ } = yield* Effect.promise(() =>
181
+ ini.parseKnownFiles({ profile: profileName }),
182
+ );
183
+
184
+ const profile = profiles[profileName];
185
+
186
+ if (!profile) {
187
+ yield* Effect.fail(
188
+ new ProfileNotFound({
189
+ message: `Profile ${profileName} not found`,
190
+ profile: profileName,
191
+ }),
192
+ );
193
+ }
194
+
195
+ const awsDir = path.join(ini.getHomeDir(), ".aws");
196
+ const configPath = path.join(awsDir, "config");
197
+ const cachePath = path.join(awsDir, "sso", "cache");
198
+
199
+ if (profile.sso_session) {
200
+ const ssoRegion = Option.getOrUndefined(
201
+ yield* Effect.serviceOption(SsoRegion),
202
+ );
203
+ const ssoStartUrl = Option.getOrElse(
204
+ yield* Effect.serviceOption(SsoStartUrl),
205
+ () => profile.sso_start_url,
206
+ );
207
+
208
+ const ssoSessions = yield* fs.readFileString(configPath).pipe(
209
+ Effect.flatMap((config) =>
210
+ Effect.promise(async () => parseIni(config)),
211
+ ),
212
+ Effect.map(parseSSOSessionData),
213
+ );
214
+ const session = ssoSessions[profile.sso_session];
215
+ if (ssoRegion && ssoRegion !== session.sso_region) {
216
+ yield* Effect.fail(
217
+ new ConflictingSSORegion({
218
+ message: `Conflicting SSO region`,
219
+ ssoRegion: ssoRegion,
220
+ profile: profile.sso_session,
221
+ }),
222
+ );
223
+ }
224
+ if (ssoStartUrl && ssoStartUrl !== session.sso_start_url) {
225
+ yield* Effect.fail(
226
+ new ConflictingSSOStartUrl({
227
+ message: `Conflicting SSO start url`,
228
+ ssoStartUrl: ssoStartUrl,
229
+ profile: profile.sso_session,
230
+ }),
231
+ );
232
+ }
233
+ profile.sso_region = session.sso_region;
234
+ profile.sso_start_url = session.sso_start_url;
235
+
236
+ const ssoFields = [
237
+ "sso_start_url",
238
+ "sso_account_id",
239
+ "sso_region",
240
+ "sso_role_name",
241
+ ] as const satisfies (keyof SsoProfileConfig)[];
242
+ const missingFields = ssoFields.filter((field) => !profile[field]);
243
+ if (missingFields.length > 0) {
244
+ yield* Effect.fail(
245
+ new InvalidSSOProfile({
246
+ profile: profileName,
247
+ missingFields,
248
+ message:
249
+ `Profile is configured with invalid SSO credentials. Required parameters "sso_account_id", ` +
250
+ `"sso_region", "sso_role_name", "sso_start_url". Got ${Object.keys(
251
+ profile,
252
+ ).join(
253
+ ", ",
254
+ )}\nReference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html`,
255
+ }),
256
+ );
257
+ }
258
+
259
+ const hasher = createHash("sha1");
260
+ const cacheName = hasher.update(profile.sso_session).digest("hex");
261
+ const ssoTokenFilepath = path.join(cachePath, `${cacheName}.json`);
262
+ const cachedCredsFilePath = path.join(
263
+ cachePath,
264
+ `${cacheName}.credentials.json`,
265
+ );
266
+
267
+ const cachedCreds = yield* fs.readFileString(cachedCredsFilePath).pipe(
268
+ Effect.map((text) => JSON.parse(text)),
269
+ Effect.catchAll(() => Effect.void),
270
+ );
271
+
272
+ const isExpired = (expiry: number | string | undefined) => {
273
+ return (
274
+ expiry === undefined ||
275
+ new Date(expiry).getTime() - Date.now() <= EXPIRE_WINDOW_MS
276
+ );
277
+ };
278
+
279
+ if (cachedCreds && !isExpired(cachedCreds.expiry)) {
280
+ return Credentials.of({
281
+ accessKeyId: Redacted.make(cachedCreds.accessKeyId),
282
+ secretAccessKey: Redacted.make(cachedCreds.secretAccessKey),
283
+ sessionToken: cachedCreds.sessionToken
284
+ ? Redacted.make(cachedCreds.sessionToken)
285
+ : undefined,
286
+ expiration: cachedCreds.expiry,
287
+ });
288
+ }
289
+
290
+ const ssoToken = yield* fs.readFileString(ssoTokenFilepath).pipe(
291
+ Effect.map((text) => JSON.parse(text) as SSOToken),
292
+ Effect.catchAll(() =>
293
+ Effect.fail(
294
+ new InvalidSSOToken({
295
+ message: `The SSO session token associated with profile=${profileName} was not found or is invalid. ${REFRESH_MESSAGE}`,
296
+ sso_session: profile.sso_session!,
297
+ }),
298
+ ),
299
+ ),
300
+ );
301
+
302
+ if (isExpired(ssoToken.expiresAt)) {
303
+ yield* Console.log(
304
+ `The SSO session token associated with profile=${profileName} was not found or is invalid. ${REFRESH_MESSAGE}`,
305
+ );
306
+ yield* Effect.fail(
307
+ new ExpiredSSOToken({
308
+ message: `The SSO session token associated with profile=${profileName} was not found or is invalid. ${REFRESH_MESSAGE}`,
309
+ profile: profileName,
310
+ }),
311
+ );
312
+ }
313
+
314
+ const response = yield* client.get(
315
+ `https://portal.sso.${profile.sso_region}.amazonaws.com/federation/credentials?account_id=${profile.sso_account_id}&role_name=${profile.sso_role_name}`,
316
+ {
317
+ headers: {
318
+ "User-Agent": "alchemy.run",
319
+ "Content-Type": "application/json",
320
+ "x-amz-sso_bearer_token": ssoToken.accessToken,
321
+ },
322
+ },
323
+ );
324
+
325
+ const credentials = (
326
+ (yield* response.json) as {
327
+ roleCredentials: {
328
+ accessKeyId: string;
329
+ secretAccessKey: string;
330
+ sessionToken: string;
331
+ expiration: number;
332
+ };
333
+ }
334
+ ).roleCredentials;
335
+
336
+ yield* fs.writeFileString(
337
+ cachedCredsFilePath,
338
+ JSON.stringify({
339
+ accessKeyId: credentials.accessKeyId,
340
+ secretAccessKey: credentials.secretAccessKey,
341
+ sessionToken: credentials.sessionToken,
342
+ expiry: credentials.expiration,
343
+ }),
344
+ );
345
+
346
+ return Credentials.of({
347
+ accessKeyId: Redacted.make(credentials.accessKeyId),
348
+ secretAccessKey: Redacted.make(credentials.secretAccessKey),
349
+ sessionToken: Redacted.make(credentials.sessionToken),
350
+ expiration: credentials.expiration,
351
+ });
352
+ }
353
+
354
+ return yield* Effect.fail(
355
+ new ProfileNotFound({
356
+ message: `Profile ${profileName} not found`,
357
+ profile: profileName,
358
+ }),
359
+ );
360
+ }),
361
+ );
362
+
363
+ /**
364
+ * Cached SSO token retrieved from SSO login flow.
365
+ * @public
366
+ */
367
+ export interface SSOToken {
368
+ /**
369
+ * A base64 encoded string returned by the sso-oidc service.
370
+ */
371
+ accessToken: string;
372
+
373
+ /**
374
+ * The expiration time of the accessToken as an RFC 3339 formatted timestamp.
375
+ */
376
+ expiresAt: string;
377
+
378
+ /**
379
+ * The token used to obtain an access token in the event that the accessToken is invalid or expired.
380
+ */
381
+ refreshToken?: string;
382
+
383
+ /**
384
+ * The unique identifier string for each client. The client ID generated when performing the registration
385
+ * portion of the OIDC authorization flow. This is used to refresh the accessToken.
386
+ */
387
+ clientId?: string;
388
+
389
+ /**
390
+ * A secret string generated when performing the registration portion of the OIDC authorization flow.
391
+ * This is used to refresh the accessToken.
392
+ */
393
+ clientSecret?: string;
394
+
395
+ /**
396
+ * The expiration time of the client registration (clientId and clientSecret) as an RFC 3339 formatted timestamp.
397
+ */
398
+ registrationExpiresAt?: string;
399
+
400
+ /**
401
+ * The configured sso_region for the profile that credentials are being resolved for.
402
+ */
403
+ region?: string;
404
+
405
+ /**
406
+ * The configured sso_start_url for the profile that credentials are being resolved for.
407
+ */
408
+ startUrl?: string;
409
+ }
@@ -0,0 +1,240 @@
1
+ import * as Data from "effect/Data";
2
+ import * as Effect from "effect/Effect";
3
+ import * as S from "effect/Schema";
4
+ import type { AttributeValue, ScalarAttributeType } from "itty-aws/dynamodb";
5
+ import {
6
+ getSetValueAST,
7
+ isClassSchema,
8
+ isListSchema,
9
+ isMapSchema,
10
+ isNumberSchema,
11
+ isRecordLikeSchema,
12
+ isRecordSchema,
13
+ isSetSchema,
14
+ isStringSchema,
15
+ isStructSchema,
16
+ } from "../../schema.ts";
17
+
18
+ // this seems important for handling S.Struct.Fields https://effect.website/docs/schema/classes/#recursive-types-with-different-encoded-and-type
19
+ // interface CategoryEncoded extends Schema.Struct.Encoded<typeof fields> { .. }
20
+
21
+ export class InvalidAttributeValue extends Data.TaggedError(
22
+ "InvalidAttributeValue",
23
+ )<{
24
+ message: string;
25
+ value: any;
26
+ }> {}
27
+
28
+ export const toAttributeValue: (
29
+ value: any,
30
+ ) => Effect.Effect<AttributeValue, InvalidAttributeValue, never> = Effect.fn(
31
+ function* (value: any) {
32
+ if (value === undefined) {
33
+ return {
34
+ NULL: false,
35
+ };
36
+ } else if (value === null) {
37
+ return {
38
+ NULL: true,
39
+ };
40
+ } else if (typeof value === "boolean") {
41
+ return {
42
+ BOOL: value,
43
+ };
44
+ } else if (typeof value === "string") {
45
+ return {
46
+ S: value,
47
+ };
48
+ } else if (typeof value === "number") {
49
+ return {
50
+ N: value.toString(10),
51
+ };
52
+ } else if (Array.isArray(value)) {
53
+ return {
54
+ L: yield* Effect.all(value.map(toAttributeValue)),
55
+ };
56
+ } else if (value instanceof Set) {
57
+ const setType = getType(value);
58
+ if (setType === "EMPTY_SET") {
59
+ return {
60
+ SS: [],
61
+ };
62
+ } else if (Array.isArray(setType)) {
63
+ return {
64
+ L: yield* Effect.all(setType.map(toAttributeValue)),
65
+ };
66
+ } else if (setType === "SS") {
67
+ return {
68
+ SS: Array.from(value.values()),
69
+ };
70
+ } else if (setType === "NS") {
71
+ return {
72
+ NS: Array.from(value.values()).map((value) => value.toString(10)),
73
+ };
74
+ } else if (setType === "BS") {
75
+ return {
76
+ BS: Array.from(value.values()),
77
+ };
78
+ } else {
79
+ return {
80
+ L: yield* Effect.all(
81
+ Array.from(value.values()).map(toAttributeValue),
82
+ ),
83
+ };
84
+ }
85
+ } else if (Buffer.isBuffer(value)) {
86
+ return {
87
+ B: new Uint8Array(value),
88
+ };
89
+ } else if (value instanceof File) {
90
+ return {
91
+ B: new Uint8Array(yield* Effect.promise(() => value.arrayBuffer())),
92
+ };
93
+ } else if (value instanceof Uint8Array) {
94
+ return {
95
+ B: value,
96
+ };
97
+ } else if (value instanceof ArrayBuffer) {
98
+ return {
99
+ B: new Uint8Array(value),
100
+ };
101
+ } else if (typeof value === "object") {
102
+ return {
103
+ M: Object.fromEntries(
104
+ yield* Effect.all(
105
+ Object.entries(value).map(([key, value]) =>
106
+ toAttributeValue(value).pipe(Effect.map((value) => [key, value])),
107
+ ),
108
+ ),
109
+ ),
110
+ };
111
+ }
112
+
113
+ return yield* Effect.fail(
114
+ new InvalidAttributeValue({
115
+ message: `Unknown value type: ${typeof value}`,
116
+ value,
117
+ }),
118
+ );
119
+ },
120
+ );
121
+
122
+ export const fromAttributeValue = (value: AttributeValue): any => {
123
+ if (value.NULL) {
124
+ return null;
125
+ } else if (typeof value.BOOL === "boolean") {
126
+ return value.BOOL;
127
+ } else if (value.L) {
128
+ return value.L.map(fromAttributeValue);
129
+ } else if (value.M) {
130
+ return Object.fromEntries(
131
+ Object.entries(value.M).map(([key, value]) => [
132
+ key,
133
+ fromAttributeValue(value),
134
+ ]),
135
+ );
136
+ } else if (value.N) {
137
+ return parseFloat(value.N);
138
+ } else if (value.S) {
139
+ // how do we know if this is a date?
140
+ return value.S;
141
+ } else if (value.SS) {
142
+ return new Set(value.SS);
143
+ } else if (value.NS) {
144
+ return new Set(value.NS);
145
+ } else if (value.BS) {
146
+ return new Set(value.BS);
147
+ } else {
148
+ throw new Error(`Unknown attribute value: ${JSON.stringify(value)}`);
149
+ }
150
+ };
151
+
152
+ type ValueType =
153
+ | "L"
154
+ | "BOOL"
155
+ | "EMPTY_SET"
156
+ | "M"
157
+ | "NULL"
158
+ | "N"
159
+ | "M"
160
+ | "S"
161
+ | "SS"
162
+ | "BS"
163
+ | "NS"
164
+ | "undefined";
165
+
166
+ const getType = (value: any): ValueType | ValueType[] => {
167
+ if (value === undefined) {
168
+ return "undefined";
169
+ } else if (value === null) {
170
+ return "NULL";
171
+ } else if (typeof value === "boolean") {
172
+ return "BOOL";
173
+ } else if (typeof value === "string") {
174
+ return "S";
175
+ } else if (typeof value === "number") {
176
+ return "N";
177
+ } else if (Array.isArray(value)) {
178
+ return "L";
179
+ } else if (value instanceof Set) {
180
+ return value.size === 0
181
+ ? "EMPTY_SET"
182
+ : (() => {
183
+ const types = Array.from(value.values())
184
+ .flatMap(getType)
185
+ .filter((type, i, arr) => arr.indexOf(type) === i);
186
+
187
+ return types.length === 1
188
+ ? types[0] === "S"
189
+ ? "SS"
190
+ : types[0] === "N"
191
+ ? "NS"
192
+ : types[0] === "BOOL"
193
+ ? "BS"
194
+ : types[0]
195
+ : "L";
196
+ })();
197
+ } else if (value instanceof Map) {
198
+ return "M";
199
+ } else if (typeof value === "object") {
200
+ return "M";
201
+ } else {
202
+ throw new Error(`Unknown value type: ${typeof value}`);
203
+ }
204
+ };
205
+
206
+ export const isScalarAttributeType = (
207
+ type: string,
208
+ ): type is ScalarAttributeType => {
209
+ return type === "S" || type === "N" || type === "B";
210
+ };
211
+
212
+ export const toAttributeType = (schema: S.Schema<any>) => {
213
+ if (isStringSchema(schema)) {
214
+ return "S";
215
+ } else if (isNumberSchema(schema)) {
216
+ return "N";
217
+ } else if (isRecordLikeSchema(schema)) {
218
+ return "M";
219
+ } else if (isStringSetSchema(schema)) {
220
+ return "SS";
221
+ } else if (isNumberSetSchema(schema)) {
222
+ return "NS";
223
+ } else if (isListSchema(schema)) {
224
+ return "L";
225
+ }
226
+ return "S";
227
+ };
228
+
229
+ export const isMapSchemaType = (schema: S.Schema<any>) =>
230
+ isMapSchema(schema) ||
231
+ isRecordSchema(schema) ||
232
+ isStructSchema(schema) ||
233
+ isClassSchema(schema) ||
234
+ false;
235
+
236
+ export const isStringSetSchema = (schema: S.Schema<any>) =>
237
+ isSetSchema(schema) && isStringSchema(getSetValueAST(schema));
238
+
239
+ export const isNumberSetSchema = (schema: S.Schema<any>) =>
240
+ isSetSchema(schema) && isNumberSchema(getSetValueAST(schema));