alchemy-effect 0.1.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 (420) hide show
  1. package/lib/app.d.ts +7 -2
  2. package/lib/app.d.ts.map +1 -1
  3. package/lib/app.js +1 -0
  4. package/lib/app.js.map +1 -1
  5. package/lib/apply.d.ts +57 -1
  6. package/lib/apply.d.ts.map +1 -1
  7. package/lib/apply.js +141 -55
  8. package/lib/apply.js.map +1 -1
  9. package/lib/aws/account.d.ts +4 -3
  10. package/lib/aws/account.d.ts.map +1 -1
  11. package/lib/aws/account.js +2 -2
  12. package/lib/aws/account.js.map +1 -1
  13. package/lib/aws/arn.d.ts +1 -5
  14. package/lib/aws/arn.d.ts.map +1 -1
  15. package/lib/aws/client.d.ts.map +1 -1
  16. package/lib/aws/client.js +9 -1
  17. package/lib/aws/client.js.map +1 -1
  18. package/lib/aws/credentials.d.ts +1 -1
  19. package/lib/aws/credentials.d.ts.map +1 -1
  20. package/lib/aws/credentials.js.map +1 -1
  21. package/lib/aws/dynamodb/attribute-value.d.ts +20 -0
  22. package/lib/aws/dynamodb/attribute-value.d.ts.map +1 -0
  23. package/lib/aws/dynamodb/attribute-value.js +217 -0
  24. package/lib/aws/dynamodb/attribute-value.js.map +1 -0
  25. package/lib/aws/dynamodb/client.d.ts +12 -0
  26. package/lib/aws/dynamodb/client.d.ts.map +1 -0
  27. package/lib/aws/{sqs/queue.client.js → dynamodb/client.js} +6 -6
  28. package/lib/aws/dynamodb/client.js.map +1 -0
  29. package/lib/aws/dynamodb/expr.d.ts +41 -0
  30. package/lib/aws/dynamodb/expr.d.ts.map +1 -0
  31. package/lib/aws/dynamodb/expr.js +1 -0
  32. package/lib/aws/dynamodb/expr.js.map +1 -0
  33. package/lib/aws/dynamodb/index.d.ts +9 -0
  34. package/lib/aws/dynamodb/index.d.ts.map +1 -0
  35. package/lib/aws/dynamodb/index.js +10 -0
  36. package/lib/aws/dynamodb/index.js.map +1 -0
  37. package/lib/aws/dynamodb/projection.d.ts +25 -0
  38. package/lib/aws/dynamodb/projection.d.ts.map +1 -0
  39. package/lib/aws/dynamodb/projection.js +1 -0
  40. package/lib/aws/dynamodb/projection.js.map +1 -0
  41. package/lib/aws/dynamodb/secondary-index.d.ts +25 -0
  42. package/lib/aws/dynamodb/secondary-index.d.ts.map +1 -0
  43. package/lib/aws/dynamodb/secondary-index.js +4 -0
  44. package/lib/aws/dynamodb/secondary-index.js.map +1 -0
  45. package/lib/aws/dynamodb/table.d.ts +56 -0
  46. package/lib/aws/dynamodb/table.d.ts.map +1 -0
  47. package/lib/aws/dynamodb/table.get-item.d.ts +55 -0
  48. package/lib/aws/dynamodb/table.get-item.d.ts.map +1 -0
  49. package/lib/aws/dynamodb/table.get-item.js +75 -0
  50. package/lib/aws/dynamodb/table.get-item.js.map +1 -0
  51. package/lib/aws/dynamodb/table.js +4 -0
  52. package/lib/aws/dynamodb/table.js.map +1 -0
  53. package/lib/aws/dynamodb/table.provider.d.ts +8 -0
  54. package/lib/aws/dynamodb/table.provider.d.ts.map +1 -0
  55. package/lib/aws/dynamodb/table.provider.js +199 -0
  56. package/lib/aws/dynamodb/table.provider.js.map +1 -0
  57. package/lib/aws/ec2/client.d.ts +12 -0
  58. package/lib/aws/ec2/client.d.ts.map +1 -0
  59. package/lib/aws/ec2/client.js +11 -0
  60. package/lib/aws/ec2/client.js.map +1 -0
  61. package/lib/aws/ec2/index.d.ts +4 -0
  62. package/lib/aws/ec2/index.d.ts.map +1 -0
  63. package/lib/aws/ec2/index.js +4 -0
  64. package/lib/aws/ec2/index.js.map +1 -0
  65. package/lib/aws/ec2/vpc.d.ts +131 -0
  66. package/lib/aws/ec2/vpc.d.ts.map +1 -0
  67. package/lib/aws/ec2/vpc.js +3 -0
  68. package/lib/aws/ec2/vpc.js.map +1 -0
  69. package/lib/aws/ec2/vpc.provider.d.ts +7 -0
  70. package/lib/aws/ec2/vpc.provider.d.ts.map +1 -0
  71. package/lib/aws/ec2/vpc.provider.js +198 -0
  72. package/lib/aws/ec2/vpc.provider.js.map +1 -0
  73. package/lib/aws/index.d.ts +24 -14
  74. package/lib/aws/index.d.ts.map +1 -1
  75. package/lib/aws/index.js +7 -12
  76. package/lib/aws/index.js.map +1 -1
  77. package/lib/aws/lambda/client.d.ts +8 -0
  78. package/lib/aws/lambda/client.d.ts.map +1 -0
  79. package/lib/aws/lambda/client.js +7 -0
  80. package/lib/aws/lambda/client.js.map +1 -0
  81. package/lib/aws/lambda/consume.d.ts +3 -3
  82. package/lib/aws/lambda/consume.d.ts.map +1 -1
  83. package/lib/aws/lambda/consume.js.map +1 -1
  84. package/lib/aws/lambda/function.d.ts +13 -10
  85. package/lib/aws/lambda/function.d.ts.map +1 -1
  86. package/lib/aws/lambda/function.invoke.d.ts +2 -2
  87. package/lib/aws/lambda/function.invoke.d.ts.map +1 -1
  88. package/lib/aws/lambda/function.invoke.js +2 -2
  89. package/lib/aws/lambda/function.invoke.js.map +1 -1
  90. package/lib/aws/lambda/function.js +1 -1
  91. package/lib/aws/lambda/function.js.map +1 -1
  92. package/lib/aws/lambda/function.provider.d.ts +3 -3
  93. package/lib/aws/lambda/function.provider.d.ts.map +1 -1
  94. package/lib/aws/lambda/function.provider.js +145 -55
  95. package/lib/aws/lambda/function.provider.js.map +1 -1
  96. package/lib/aws/lambda/index.d.ts +1 -2
  97. package/lib/aws/lambda/index.d.ts.map +1 -1
  98. package/lib/aws/lambda/index.js +1 -1
  99. package/lib/aws/lambda/index.js.map +1 -1
  100. package/lib/aws/lambda/serve.d.ts +1 -1
  101. package/lib/aws/lambda/serve.d.ts.map +1 -1
  102. package/lib/aws/lambda/serve.js.map +1 -1
  103. package/lib/aws/region.d.ts +1 -0
  104. package/lib/aws/region.d.ts.map +1 -1
  105. package/lib/aws/region.js.map +1 -1
  106. package/lib/aws/sqs/client.d.ts +12 -0
  107. package/lib/aws/sqs/client.d.ts.map +1 -0
  108. package/lib/aws/sqs/client.js +11 -0
  109. package/lib/aws/sqs/client.js.map +1 -0
  110. package/lib/aws/sqs/index.d.ts +2 -1
  111. package/lib/aws/sqs/index.d.ts.map +1 -1
  112. package/lib/aws/sqs/index.js +2 -1
  113. package/lib/aws/sqs/index.js.map +1 -1
  114. package/lib/aws/sqs/queue.consume.d.ts +1 -10
  115. package/lib/aws/sqs/queue.consume.d.ts.map +1 -1
  116. package/lib/aws/sqs/queue.consume.js +1 -19
  117. package/lib/aws/sqs/queue.consume.js.map +1 -1
  118. package/lib/aws/sqs/queue.d.ts +2 -10
  119. package/lib/aws/sqs/queue.d.ts.map +1 -1
  120. package/lib/aws/sqs/queue.event-source.d.ts +20 -0
  121. package/lib/aws/sqs/queue.event-source.d.ts.map +1 -0
  122. package/lib/aws/sqs/queue.event-source.js +148 -0
  123. package/lib/aws/sqs/queue.event-source.js.map +1 -0
  124. package/lib/aws/sqs/queue.provider.d.ts +4 -3
  125. package/lib/aws/sqs/queue.provider.d.ts.map +1 -1
  126. package/lib/aws/sqs/queue.provider.js +4 -4
  127. package/lib/aws/sqs/queue.provider.js.map +1 -1
  128. package/lib/aws/sqs/queue.send-message.d.ts +2 -2
  129. package/lib/aws/sqs/queue.send-message.d.ts.map +1 -1
  130. package/lib/aws/sqs/queue.send-message.js +2 -2
  131. package/lib/aws/sqs/queue.send-message.js.map +1 -1
  132. package/lib/binding.d.ts +70 -22
  133. package/lib/binding.d.ts.map +1 -1
  134. package/lib/binding.js.map +1 -1
  135. package/lib/capability.d.ts +38 -0
  136. package/lib/capability.d.ts.map +1 -1
  137. package/lib/cli/components/Plan.d.ts.map +1 -1
  138. package/lib/cli/components/Plan.js +3 -1
  139. package/lib/cli/components/Plan.js.map +1 -1
  140. package/lib/cli/index.d.ts +204 -116
  141. package/lib/cli/index.d.ts.map +1 -1
  142. package/lib/cli/index.js +25707 -11055
  143. package/lib/cli/index.js.map +1 -1
  144. package/lib/cli/progress.d.ts.map +1 -1
  145. package/lib/cli/progress.js +1 -0
  146. package/lib/cli/progress.js.map +1 -1
  147. package/lib/cloudflare/api.d.ts +29 -17
  148. package/lib/cloudflare/api.d.ts.map +1 -1
  149. package/lib/cloudflare/api.js +92 -27
  150. package/lib/cloudflare/api.js.map +1 -1
  151. package/lib/cloudflare/context.d.ts +27 -0
  152. package/lib/cloudflare/context.d.ts.map +1 -0
  153. package/lib/cloudflare/context.js +24 -0
  154. package/lib/cloudflare/context.js.map +1 -0
  155. package/lib/cloudflare/index.d.ts +5 -4
  156. package/lib/cloudflare/index.d.ts.map +1 -1
  157. package/lib/cloudflare/index.js +4 -4
  158. package/lib/cloudflare/index.js.map +1 -1
  159. package/lib/cloudflare/kv/index.d.ts +4 -0
  160. package/lib/cloudflare/kv/index.d.ts.map +1 -0
  161. package/lib/cloudflare/kv/index.js +4 -0
  162. package/lib/cloudflare/kv/index.js.map +1 -0
  163. package/lib/cloudflare/kv/namespace.binding.d.ts +8 -0
  164. package/lib/cloudflare/kv/namespace.binding.d.ts.map +1 -0
  165. package/lib/cloudflare/kv/namespace.binding.js +15 -0
  166. package/lib/cloudflare/kv/namespace.binding.js.map +1 -0
  167. package/lib/cloudflare/kv/namespace.client.d.ts +11 -0
  168. package/lib/cloudflare/kv/namespace.client.d.ts.map +1 -0
  169. package/lib/cloudflare/kv/namespace.client.js +31 -0
  170. package/lib/cloudflare/kv/namespace.client.js.map +1 -0
  171. package/lib/cloudflare/kv/namespace.d.ts +23 -0
  172. package/lib/cloudflare/kv/namespace.d.ts.map +1 -0
  173. package/lib/cloudflare/kv/namespace.js +3 -0
  174. package/lib/cloudflare/kv/namespace.js.map +1 -0
  175. package/lib/cloudflare/kv/namespace.provider.d.ts +5 -0
  176. package/lib/cloudflare/kv/namespace.provider.d.ts.map +1 -0
  177. package/lib/cloudflare/kv/namespace.provider.js +80 -0
  178. package/lib/cloudflare/kv/namespace.provider.js.map +1 -0
  179. package/lib/cloudflare/live.d.ts +11 -0
  180. package/lib/cloudflare/live.d.ts.map +1 -0
  181. package/lib/cloudflare/live.js +18 -0
  182. package/lib/cloudflare/live.js.map +1 -0
  183. package/lib/cloudflare/r2/bucket.binding.d.ts +8 -0
  184. package/lib/cloudflare/r2/bucket.binding.d.ts.map +1 -0
  185. package/lib/cloudflare/r2/bucket.binding.js +18 -0
  186. package/lib/cloudflare/r2/bucket.binding.js.map +1 -0
  187. package/lib/cloudflare/r2/bucket.client.d.ts +8 -0
  188. package/lib/cloudflare/r2/bucket.client.d.ts.map +1 -0
  189. package/lib/cloudflare/r2/bucket.client.js +9 -0
  190. package/lib/cloudflare/r2/bucket.client.js.map +1 -0
  191. package/lib/cloudflare/r2/bucket.d.ts +32 -0
  192. package/lib/cloudflare/r2/bucket.d.ts.map +1 -0
  193. package/lib/cloudflare/r2/bucket.del.d.ts +4 -0
  194. package/lib/cloudflare/r2/bucket.del.d.ts.map +1 -0
  195. package/lib/cloudflare/r2/bucket.del.js +7 -0
  196. package/lib/cloudflare/r2/bucket.del.js.map +1 -0
  197. package/lib/cloudflare/r2/bucket.get.d.ts +5 -0
  198. package/lib/cloudflare/r2/bucket.get.d.ts.map +1 -0
  199. package/lib/cloudflare/r2/bucket.get.js +7 -0
  200. package/lib/cloudflare/r2/bucket.get.js.map +1 -0
  201. package/lib/cloudflare/r2/bucket.head.d.ts +4 -0
  202. package/lib/cloudflare/r2/bucket.head.d.ts.map +1 -0
  203. package/lib/cloudflare/r2/bucket.head.js +7 -0
  204. package/lib/cloudflare/r2/bucket.head.js.map +1 -0
  205. package/lib/cloudflare/r2/bucket.js +3 -0
  206. package/lib/cloudflare/r2/bucket.js.map +1 -0
  207. package/lib/cloudflare/r2/bucket.list.d.ts +5 -0
  208. package/lib/cloudflare/r2/bucket.list.d.ts.map +1 -0
  209. package/lib/cloudflare/r2/bucket.list.js +7 -0
  210. package/lib/cloudflare/r2/bucket.list.js.map +1 -0
  211. package/lib/cloudflare/r2/bucket.multipart.d.ts +19 -0
  212. package/lib/cloudflare/r2/bucket.multipart.d.ts.map +1 -0
  213. package/lib/cloudflare/r2/bucket.multipart.js +25 -0
  214. package/lib/cloudflare/r2/bucket.multipart.js.map +1 -0
  215. package/lib/cloudflare/r2/bucket.provider.d.ts +5 -0
  216. package/lib/cloudflare/r2/bucket.provider.d.ts.map +1 -0
  217. package/lib/cloudflare/r2/bucket.provider.js +66 -0
  218. package/lib/cloudflare/r2/bucket.provider.js.map +1 -0
  219. package/lib/cloudflare/r2/bucket.put.d.ts +6 -0
  220. package/lib/cloudflare/r2/bucket.put.d.ts.map +1 -0
  221. package/lib/cloudflare/r2/bucket.put.js +8 -0
  222. package/lib/cloudflare/r2/bucket.put.js.map +1 -0
  223. package/lib/cloudflare/r2/index.d.ts +10 -0
  224. package/lib/cloudflare/r2/index.d.ts.map +1 -0
  225. package/lib/cloudflare/r2/index.js +10 -0
  226. package/lib/cloudflare/r2/index.js.map +1 -0
  227. package/lib/cloudflare/stream.d.ts +10 -0
  228. package/lib/cloudflare/stream.d.ts.map +1 -0
  229. package/lib/cloudflare/stream.js +16 -0
  230. package/lib/cloudflare/stream.js.map +1 -0
  231. package/lib/cloudflare/worker/assets.fetch.d.ts +8 -0
  232. package/lib/cloudflare/worker/assets.fetch.d.ts.map +1 -0
  233. package/lib/cloudflare/worker/assets.fetch.js +11 -0
  234. package/lib/cloudflare/worker/assets.fetch.js.map +1 -0
  235. package/lib/cloudflare/worker/assets.provider.d.ts +66 -0
  236. package/lib/cloudflare/worker/assets.provider.d.ts.map +1 -0
  237. package/lib/cloudflare/worker/assets.provider.js +145 -0
  238. package/lib/cloudflare/worker/assets.provider.js.map +1 -0
  239. package/lib/cloudflare/worker/index.d.ts +6 -0
  240. package/lib/cloudflare/worker/index.d.ts.map +1 -0
  241. package/lib/cloudflare/worker/index.js +5 -0
  242. package/lib/cloudflare/worker/index.js.map +1 -0
  243. package/lib/cloudflare/worker/worker.d.ts +67 -0
  244. package/lib/cloudflare/worker/worker.d.ts.map +1 -0
  245. package/lib/cloudflare/worker/worker.handler.d.ts +11 -0
  246. package/lib/cloudflare/worker/worker.handler.d.ts.map +1 -0
  247. package/lib/cloudflare/worker/worker.handler.js +15 -0
  248. package/lib/cloudflare/worker/worker.handler.js.map +1 -0
  249. package/lib/cloudflare/worker/worker.js +4 -0
  250. package/lib/cloudflare/worker/worker.js.map +1 -0
  251. package/lib/cloudflare/worker/worker.provider.d.ts +10 -0
  252. package/lib/cloudflare/worker/worker.provider.d.ts.map +1 -0
  253. package/lib/cloudflare/worker/worker.provider.js +193 -0
  254. package/lib/cloudflare/worker/worker.provider.js.map +1 -0
  255. package/lib/cloudflare/worker/worker.serve.d.ts +39 -0
  256. package/lib/cloudflare/worker/worker.serve.d.ts.map +1 -0
  257. package/lib/cloudflare/worker/worker.serve.js +4 -0
  258. package/lib/cloudflare/worker/worker.serve.js.map +1 -0
  259. package/lib/destroy.d.ts +1 -3
  260. package/lib/destroy.d.ts.map +1 -1
  261. package/lib/destroy.js +5 -0
  262. package/lib/destroy.js.map +1 -1
  263. package/lib/dot-alchemy.d.ts +3 -2
  264. package/lib/dot-alchemy.d.ts.map +1 -1
  265. package/lib/dot-alchemy.js +3 -2
  266. package/lib/dot-alchemy.js.map +1 -1
  267. package/lib/esbuild.d.ts +28 -0
  268. package/lib/esbuild.d.ts.map +1 -0
  269. package/lib/esbuild.js +63 -0
  270. package/lib/esbuild.js.map +1 -0
  271. package/lib/index.d.ts +1 -3
  272. package/lib/index.d.ts.map +1 -1
  273. package/lib/index.js +4 -3
  274. package/lib/index.js.map +1 -1
  275. package/lib/plan.d.ts +19 -8
  276. package/lib/plan.d.ts.map +1 -1
  277. package/lib/plan.js +144 -72
  278. package/lib/plan.js.map +1 -1
  279. package/lib/policy.d.ts +19 -1
  280. package/lib/policy.d.ts.map +1 -1
  281. package/lib/policy.js +10 -1
  282. package/lib/policy.js.map +1 -1
  283. package/lib/provider.d.ts +2 -2
  284. package/lib/provider.d.ts.map +1 -1
  285. package/lib/resource.d.ts +2 -10
  286. package/lib/resource.d.ts.map +1 -1
  287. package/lib/resource.js +1 -0
  288. package/lib/resource.js.map +1 -1
  289. package/lib/runtime.d.ts +1 -1
  290. package/lib/runtime.d.ts.map +1 -1
  291. package/lib/schema.d.ts +37 -0
  292. package/lib/schema.d.ts.map +1 -0
  293. package/lib/schema.js +61 -0
  294. package/lib/schema.js.map +1 -0
  295. package/lib/sha256.d.ts +5 -0
  296. package/lib/sha256.d.ts.map +1 -0
  297. package/lib/sha256.js +16 -0
  298. package/lib/sha256.js.map +1 -0
  299. package/lib/state.d.ts +3 -2
  300. package/lib/state.d.ts.map +1 -1
  301. package/lib/state.js +3 -2
  302. package/lib/state.js.map +1 -1
  303. package/lib/tags.d.ts +17 -0
  304. package/lib/tags.d.ts.map +1 -0
  305. package/lib/tags.js +22 -0
  306. package/lib/tags.js.map +1 -0
  307. package/lib/test.d.ts +14 -0
  308. package/lib/test.d.ts.map +1 -0
  309. package/lib/test.js +28 -0
  310. package/lib/test.js.map +1 -0
  311. package/lib/tsconfig.test.tsbuildinfo +1 -0
  312. package/lib/type.d.ts +3 -0
  313. package/lib/type.d.ts.map +1 -0
  314. package/lib/type.js +3 -0
  315. package/lib/type.js.map +1 -0
  316. package/package.json +48 -3
  317. package/src/app.ts +8 -7
  318. package/src/apply.ts +251 -93
  319. package/src/aws/account.ts +6 -4
  320. package/src/aws/arn.ts +1 -7
  321. package/src/aws/client.ts +15 -1
  322. package/src/aws/credentials.ts +1 -0
  323. package/src/aws/dynamodb/attribute-value.ts +240 -0
  324. package/src/aws/{sqs/queue.client.ts → dynamodb/client.ts} +9 -9
  325. package/src/aws/dynamodb/expr.ts +90 -0
  326. package/src/aws/dynamodb/index.ts +12 -0
  327. package/src/aws/dynamodb/projection.ts +159 -0
  328. package/src/aws/dynamodb/secondary-index.ts +45 -0
  329. package/src/aws/dynamodb/table.get-item.ts +177 -0
  330. package/src/aws/dynamodb/table.provider.ts +280 -0
  331. package/src/aws/dynamodb/table.ts +156 -0
  332. package/src/aws/ec2/client.ts +20 -0
  333. package/src/aws/ec2/index.ts +3 -0
  334. package/src/aws/ec2/vpc.provider.ts +285 -0
  335. package/src/aws/ec2/vpc.ts +152 -0
  336. package/src/aws/index.ts +15 -16
  337. package/src/aws/lambda/client.ts +14 -0
  338. package/src/aws/lambda/consume.ts +0 -1
  339. package/src/aws/lambda/function.invoke.ts +2 -2
  340. package/src/aws/lambda/function.provider.ts +197 -105
  341. package/src/aws/lambda/function.ts +16 -10
  342. package/src/aws/lambda/index.ts +1 -4
  343. package/src/aws/lambda/serve.ts +1 -1
  344. package/src/aws/region.ts +3 -1
  345. package/src/aws/sqs/client.ts +20 -0
  346. package/src/aws/sqs/index.ts +2 -1
  347. package/src/aws/sqs/queue.consume.ts +1 -34
  348. package/src/aws/sqs/queue.event-source.ts +253 -0
  349. package/src/aws/sqs/queue.provider.ts +4 -4
  350. package/src/aws/sqs/queue.send-message.ts +2 -2
  351. package/src/binding.ts +121 -25
  352. package/src/capability.ts +44 -0
  353. package/src/cli/components/Plan.tsx +4 -2
  354. package/src/cli/progress.tsx +1 -0
  355. package/src/cloudflare/api.ts +141 -61
  356. package/src/cloudflare/context.ts +49 -0
  357. package/src/cloudflare/index.ts +6 -4
  358. package/src/cloudflare/kv/index.ts +3 -0
  359. package/src/cloudflare/kv/namespace.binding.ts +25 -0
  360. package/src/cloudflare/kv/namespace.client.ts +70 -0
  361. package/src/cloudflare/kv/namespace.provider.ts +99 -0
  362. package/src/cloudflare/kv/namespace.ts +29 -0
  363. package/src/cloudflare/live.ts +38 -0
  364. package/src/cloudflare/r2/bucket.binding.ts +27 -0
  365. package/src/cloudflare/r2/bucket.client.ts +22 -0
  366. package/src/cloudflare/r2/bucket.del.ts +11 -0
  367. package/src/cloudflare/r2/bucket.get.ts +13 -0
  368. package/src/cloudflare/r2/bucket.head.ts +11 -0
  369. package/src/cloudflare/r2/bucket.list.ts +12 -0
  370. package/src/cloudflare/r2/bucket.multipart.ts +55 -0
  371. package/src/cloudflare/r2/bucket.provider.ts +83 -0
  372. package/src/cloudflare/r2/bucket.put.ts +17 -0
  373. package/src/cloudflare/r2/bucket.ts +38 -0
  374. package/src/cloudflare/r2/index.ts +9 -0
  375. package/src/cloudflare/stream.ts +21 -0
  376. package/src/cloudflare/worker/assets.fetch.ts +27 -0
  377. package/src/cloudflare/worker/assets.provider.ts +249 -0
  378. package/src/cloudflare/worker/index.ts +6 -0
  379. package/src/cloudflare/worker/worker.handler.ts +39 -0
  380. package/src/cloudflare/worker/worker.provider.ts +246 -0
  381. package/src/cloudflare/worker/worker.serve.ts +19 -0
  382. package/src/cloudflare/worker/worker.ts +76 -0
  383. package/src/destroy.ts +6 -3
  384. package/src/dot-alchemy.ts +3 -2
  385. package/src/esbuild.ts +98 -0
  386. package/src/index.ts +5 -4
  387. package/src/plan.ts +233 -120
  388. package/src/policy.ts +55 -2
  389. package/src/provider.ts +2 -2
  390. package/src/resource.ts +3 -2
  391. package/src/runtime.ts +1 -1
  392. package/src/schema.ts +102 -0
  393. package/src/sha256.ts +23 -0
  394. package/src/state.ts +3 -2
  395. package/src/tags.ts +38 -0
  396. package/src/test.ts +71 -0
  397. package/src/type.ts +2 -0
  398. package/lib/aws/lambda/function.client.d.ts +0 -8
  399. package/lib/aws/lambda/function.client.d.ts.map +0 -1
  400. package/lib/aws/lambda/function.client.js +0 -7
  401. package/lib/aws/lambda/function.client.js.map +0 -1
  402. package/lib/aws/sqs/queue.client.d.ts +0 -12
  403. package/lib/aws/sqs/queue.client.d.ts.map +0 -1
  404. package/lib/aws/sqs/queue.client.js.map +0 -1
  405. package/lib/cloudflare/kv.d.ts +0 -29
  406. package/lib/cloudflare/kv.d.ts.map +0 -1
  407. package/lib/cloudflare/kv.js +0 -3
  408. package/lib/cloudflare/kv.js.map +0 -1
  409. package/lib/cloudflare/kv.provider.d.ts +0 -4
  410. package/lib/cloudflare/kv.provider.d.ts.map +0 -1
  411. package/lib/cloudflare/kv.provider.js +0 -39
  412. package/lib/cloudflare/kv.provider.js.map +0 -1
  413. package/lib/cloudflare/worker.d.ts +0 -33
  414. package/lib/cloudflare/worker.d.ts.map +0 -1
  415. package/lib/cloudflare/worker.js +0 -4
  416. package/lib/cloudflare/worker.js.map +0 -1
  417. package/src/aws/lambda/function.client.ts +0 -14
  418. package/src/cloudflare/kv.provider.ts +0 -51
  419. package/src/cloudflare/kv.ts +0 -20
  420. package/src/cloudflare/worker.ts +0 -34
@@ -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
+ );
@@ -2,18 +2,18 @@ import * as Effect from "effect/Effect";
2
2
  import * as Schedule from "effect/Schedule";
3
3
 
4
4
  import { App, type ProviderService } from "alchemy-effect";
5
- import { AccountID } from "../account.ts";
5
+ import { Account } from "../account.ts";
6
6
  import { Region } from "../region.ts";
7
- import { QueueClient } from "./queue.client.ts";
7
+ import { SQSClient } from "./client.ts";
8
8
  import { Queue, type QueueProps } from "./queue.ts";
9
9
 
10
10
  export const queueProvider = () =>
11
11
  Queue.provider.effect(
12
12
  Effect.gen(function* () {
13
- const sqs = yield* QueueClient;
13
+ const sqs = yield* SQSClient;
14
14
  const app = yield* App;
15
15
  const region = yield* Region;
16
- const accountId = yield* AccountID;
16
+ const accountId = yield* Account;
17
17
  const createQueueName = (id: string, props: QueueProps) =>
18
18
  props.queueName ??
19
19
  `${app.name}-${id}-${app.stage}${props.fifo ? ".fifo" : ""}`;
@@ -8,7 +8,7 @@ import {
8
8
  type To,
9
9
  } from "alchemy-effect";
10
10
  import { Function } from "../lambda/index.ts";
11
- import { QueueClient } from "./queue.client.ts";
11
+ import { SQSClient } from "./client.ts";
12
12
  import { Queue } from "./queue.ts";
13
13
 
14
14
  export interface SendMessage<Q = Queue>
@@ -24,7 +24,7 @@ export const sendMessage = <Q extends Queue>(
24
24
  ) =>
25
25
  Effect.gen(function* () {
26
26
  yield* declare<SendMessage<To<Q>>>();
27
- const sqs = yield* QueueClient;
27
+ const sqs = yield* SQSClient;
28
28
  const url = process.env[toEnvKey(queue.id, "QUEUE_URL")]!;
29
29
  return yield* sqs.sendMessage({
30
30
  QueueUrl: url,
package/src/binding.ts CHANGED
@@ -2,6 +2,7 @@ import * as Context from "effect/Context";
2
2
  import type { Effect } from "effect/Effect";
3
3
  import * as Layer from "effect/Layer";
4
4
  import type { Capability, ICapability } from "./capability.ts";
5
+ import type { Diff } from "./provider.ts";
5
6
  import type { Resource } from "./resource.ts";
6
7
  import type { Runtime } from "./runtime.ts";
7
8
 
@@ -16,14 +17,16 @@ export type AnyBinding<F extends Runtime = any> = Binding<
16
17
  F,
17
18
  any,
18
19
  any,
20
+ any,
19
21
  string,
20
22
  boolean
21
23
  >;
22
24
 
23
25
  export interface Binding<
24
- Run extends Runtime,
26
+ Run extends Runtime<any, any, any>,
25
27
  Cap extends Capability = Capability,
26
28
  Props = any,
29
+ Attr extends Run["binding"] = any,
27
30
  Tag extends string = Cap["type"],
28
31
  IsCustom extends boolean = Cap["type"] extends Tag ? false : true,
29
32
  > {
@@ -31,6 +34,7 @@ export interface Binding<
31
34
  capability: Cap;
32
35
  tag: Tag;
33
36
  props: Props;
37
+ attr: Attr;
34
38
  isCustom: IsCustom;
35
39
  }
36
40
 
@@ -81,7 +85,7 @@ export const Binding: {
81
85
  tag: tag ?? cap,
82
86
  // @ts-expect-error - we smuggle this property because it interacts poorly with inference
83
87
  Tag,
84
- }) satisfies Binding<any, any, any, string, false>,
88
+ }) satisfies Binding<any, any, any, any, string, false>,
85
89
  {
86
90
  provider: {
87
91
  effect: (eff) => Layer.effect(Tag, eff),
@@ -100,45 +104,137 @@ export interface BindingDeclaration<
100
104
  provider: {
101
105
  effect<Err, Req>(
102
106
  eff: Effect<
103
- BindingService<Run, Parameters<F>[0], Parameters<F>[1]>,
107
+ BindingService<
108
+ Run,
109
+ Parameters<F>[0],
110
+ Parameters<F>[1],
111
+ ReturnType<F>["attr"]
112
+ >,
104
113
  Err,
105
114
  Req
106
115
  >,
107
116
  ): Layer.Layer<Bind<Run, Cap, Tag>, Err, Req>;
108
117
  succeed(
109
- service: BindingService<Run, Parameters<F>[0], Parameters<F>[1]>,
118
+ service: BindingService<
119
+ Run,
120
+ Parameters<F>[0],
121
+ Parameters<F>[1],
122
+ ReturnType<F>["attr"]
123
+ >,
110
124
  ): Layer.Layer<Bind<Run, Cap, Tag>>;
111
125
  };
112
126
  }
113
127
 
128
+ export interface BindingDiffProps<
129
+ Source extends Resource = Resource,
130
+ Target extends Resource = Resource,
131
+ Props = any,
132
+ Attr = any,
133
+ > {
134
+ source: {
135
+ id: string;
136
+ props: Source["props"];
137
+ oldProps?: Source["props"];
138
+ oldAttr?: Source["attr"];
139
+ };
140
+ props: Props;
141
+ attr: Attr | undefined;
142
+ target: {
143
+ id: string;
144
+ props: Target["props"];
145
+ oldProps?: Target["props"];
146
+ oldAttr?: Target["attr"];
147
+ };
148
+ }
149
+
150
+ export interface BindingAttachProps<
151
+ Source extends Resource,
152
+ Target extends Resource,
153
+ Props,
154
+ Attr,
155
+ > {
156
+ source: {
157
+ id: string;
158
+ attr: Source["attr"];
159
+ props: Source["props"];
160
+ };
161
+ props: Props;
162
+ attr: Attr | undefined;
163
+ target: {
164
+ id: string;
165
+ props: Target["props"];
166
+ attr: Target["attr"];
167
+ };
168
+ }
169
+
170
+ export interface BindingReattachProps<
171
+ Source extends Resource,
172
+ Target extends Resource,
173
+ Props,
174
+ Attr,
175
+ > {
176
+ source: {
177
+ id: string;
178
+ attr: Source["attr"];
179
+ props: Source["props"];
180
+ };
181
+ props: Props;
182
+ attr: Attr;
183
+ target: {
184
+ id: string;
185
+ props: Target["props"];
186
+ attr: Target["attr"];
187
+ };
188
+ }
189
+
190
+ export interface BindingDetachProps<
191
+ Source extends Resource,
192
+ Target extends Resource,
193
+ Props,
194
+ Attr,
195
+ > {
196
+ source: {
197
+ id: string;
198
+ attr: Source["attr"];
199
+ props: Source["props"];
200
+ };
201
+ props: Props;
202
+ attr: Attr | undefined;
203
+ target: {
204
+ id: string;
205
+ props: Target["props"];
206
+ attr: Target["attr"];
207
+ };
208
+ }
209
+
114
210
  export type BindingService<
115
211
  Target extends Runtime = any,
116
212
  Source extends Resource = Resource,
117
213
  Props = any,
214
+ Attr extends Target["binding"] = any,
215
+ DiffReq = never,
216
+ PreReattachReq = never,
118
217
  AttachReq = never,
218
+ ReattachReq = never,
119
219
  DetachReq = never,
220
+ PostAttachReq = never,
120
221
  > = {
121
- attach: (props: {
122
- source: {
123
- id: string;
124
- attr: Source["attr"];
125
- props: Source["props"];
126
- };
127
- props: Props;
128
- target: {
129
- id: string;
130
- props: Target["props"];
131
- attr: Target["attr"];
132
- };
133
- }) =>
134
- | Effect<Partial<Target["binding"]> | void, never, AttachReq>
135
- | Partial<Target["binding"]>;
222
+ diff?: (
223
+ props: BindingDiffProps<Source, Target, Props>,
224
+ ) => Effect<Diff, never, DiffReq>;
225
+ preattach?: (
226
+ props: BindingAttachProps<Source, Target, Props, Attr>,
227
+ ) => Effect<Partial<Target["attr"]>, never, PreReattachReq>;
228
+ attach: (
229
+ props: BindingAttachProps<Source, Target, Props, Attr>,
230
+ ) => Effect<Attr, never, AttachReq> | Attr;
231
+ postattach?: (
232
+ props: BindingAttachProps<Source, Target, Props, Attr>,
233
+ ) => Effect<Omit<Attr, keyof Target["binding"]>, never, PostAttachReq>;
234
+ reattach?: (
235
+ props: BindingReattachProps<Source, Target, Props, Attr>,
236
+ ) => Effect<Attr, never, ReattachReq> | Attr;
136
237
  detach?: (
137
- resource: {
138
- id: string;
139
- attr: Source["attr"];
140
- props: Source["props"];
141
- },
142
- from: Target["binding"],
238
+ props: BindingDetachProps<Source, Target, Props, Attr>,
143
239
  ) => Effect<void, never, DetachReq> | void;
144
240
  };
package/src/capability.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { Policy } from "./policy";
2
+
1
3
  export interface ICapability<
2
4
  Type extends string = string,
3
5
  Resource = unknown,
@@ -17,3 +19,45 @@ export interface Capability<
17
19
  > extends ICapability<Type, Resource, Constraint> {
18
20
  new (): {};
19
21
  }
22
+
23
+ export declare namespace Capability {
24
+ export type Simplify<C> = [C] extends [
25
+ {
26
+ Constructor: { Reduce: any };
27
+ },
28
+ ]
29
+ ? _Simplify<C>
30
+ : C;
31
+
32
+ type _Simplify<C> = [C] extends [
33
+ infer c extends { Constructor: any; resource: any; constraint: any },
34
+ ]
35
+ ? (c["Constructor"] & {
36
+ resource: c["resource"];
37
+ constraint: Constraint.Simplify<c["constraint"]>;
38
+ })["Reduce"]
39
+ : never;
40
+
41
+ type KeysWithNever<T> = {
42
+ [K in keyof T]: T[K] extends never | Policy.AnyOf<never> ? K : never;
43
+ }[keyof T];
44
+ type DropIrrelevant<T> = T extends any
45
+ ? {
46
+ [k in keyof Omit<T, KeysWithNever<T>>]: Omit<T, KeysWithNever<T>>[k];
47
+ }
48
+ : never;
49
+ type Get<T, K extends string | number | symbol> = T extends {
50
+ [k in K]: infer V;
51
+ }
52
+ ? V
53
+ : never;
54
+ type Keys<T> = T extends any ? keyof T : never;
55
+ type BoxPolicy<T> = [T] extends [{ anyOf: (infer U)[] }]
56
+ ? Policy.AnyOf<U>
57
+ : never;
58
+ export namespace Constraint {
59
+ export type Simplify<Constraint> = {
60
+ [k in Keys<DropIrrelevant<Constraint>>]: BoxPolicy<Get<Constraint, k>>;
61
+ };
62
+ }
63
+ }
@@ -1,7 +1,7 @@
1
1
  // biome-ignore lint/style/useImportType: UMD global
2
2
  import React, { useMemo } from "react";
3
3
 
4
- import type { BindNode, CRUD, Plan } from "alchemy-effect";
4
+ import type { BindNode, Capability, CRUD, Plan } from "alchemy-effect";
5
5
  import { Box, Text } from "ink";
6
6
 
7
7
  export interface PlanProps {
@@ -93,7 +93,7 @@ export function Plan({ plan }: PlanProps): React.JSX.Element {
93
93
  const bindingIcon = bindingActionIcon(node.action);
94
94
  return (
95
95
  <Box
96
- key={node.binding.capability.resource.id}
96
+ key={`${item.resource.id}${(node.binding.capability as Capability).sid}`}
97
97
  flexDirection="row"
98
98
  >
99
99
  <Box width={4}>
@@ -142,6 +142,7 @@ const bindingActionColor = (
142
142
  attach: "green",
143
143
  detach: "red",
144
144
  noop: "gray",
145
+ reattach: "orange",
145
146
  })[action];
146
147
 
147
148
  const bindingActionIcon = (action: BindNode["action"]): string =>
@@ -149,4 +150,5 @@ const bindingActionIcon = (action: BindNode["action"]): string =>
149
150
  attach: "+",
150
151
  detach: "-",
151
152
  noop: "•",
153
+ reattach: "~",
152
154
  })[action];
@@ -16,6 +16,7 @@ export interface ProgressEventSource {
16
16
  export const reportProgress = Layer.succeed(
17
17
  Alchemy.PlanStatusReporter,
18
18
  Alchemy.PlanStatusReporter.of({
19
+ // oxlint-disable-next-line require-yield
19
20
  start: Effect.fn(function* (plan) {
20
21
  const listeners = new Set<(event: Alchemy.ApplyEvent) => void>();
21
22
  const { unmount } = render(