alchemy 2.0.0-beta.44 → 2.0.0-beta.46

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 (443) hide show
  1. package/bin/exec.js +67 -8
  2. package/bin/exec.js.map +1 -1
  3. package/lib/AWS/Lambda/Function.d.ts +17 -0
  4. package/lib/AWS/Lambda/Function.d.ts.map +1 -1
  5. package/lib/AWS/Lambda/Function.js +61 -16
  6. package/lib/AWS/Lambda/Function.js.map +1 -1
  7. package/lib/AWS/Providers.d.ts +2 -1
  8. package/lib/AWS/Providers.d.ts.map +1 -1
  9. package/lib/AWS/Providers.js +3 -1
  10. package/lib/AWS/Providers.js.map +1 -1
  11. package/lib/AlchemyContext.d.ts +0 -1
  12. package/lib/AlchemyContext.d.ts.map +1 -1
  13. package/lib/AlchemyContext.js.map +1 -1
  14. package/lib/Apply.js +17 -1
  15. package/lib/Apply.js.map +1 -1
  16. package/lib/Auth/AuthProvider.d.ts.map +1 -1
  17. package/lib/Auth/AuthProvider.js +24 -6
  18. package/lib/Auth/AuthProvider.js.map +1 -1
  19. package/lib/Auth/Credentials.d.ts.map +1 -1
  20. package/lib/Auth/Credentials.js +3 -3
  21. package/lib/Auth/Credentials.js.map +1 -1
  22. package/lib/Cli/commands/_shared.d.ts +13 -1
  23. package/lib/Cli/commands/_shared.d.ts.map +1 -1
  24. package/lib/Cli/commands/_shared.js +33 -2
  25. package/lib/Cli/commands/_shared.js.map +1 -1
  26. package/lib/Cli/commands/cloudflare.d.ts.map +1 -1
  27. package/lib/Cli/commands/cloudflare.js +5 -1
  28. package/lib/Cli/commands/cloudflare.js.map +1 -1
  29. package/lib/Cli/commands/dev.d.ts.map +1 -1
  30. package/lib/Cli/commands/dev.js +10 -1
  31. package/lib/Cli/commands/dev.js.map +1 -1
  32. package/lib/Cli/commands/login.d.ts.map +1 -1
  33. package/lib/Cli/commands/login.js +19 -5
  34. package/lib/Cli/commands/login.js.map +1 -1
  35. package/lib/Cli/commands/profile.d.ts.map +1 -1
  36. package/lib/Cli/commands/profile.js +7 -27
  37. package/lib/Cli/commands/profile.js.map +1 -1
  38. package/lib/Cli/main.d.ts.map +1 -1
  39. package/lib/Cli/main.js +0 -2
  40. package/lib/Cli/main.js.map +1 -1
  41. package/lib/Cloudflare/AiGateway/AiGateway.d.ts +0 -2
  42. package/lib/Cloudflare/AiGateway/AiGateway.d.ts.map +1 -1
  43. package/lib/Cloudflare/AiGateway/AiGateway.js +2 -4
  44. package/lib/Cloudflare/AiGateway/AiGateway.js.map +1 -1
  45. package/lib/Cloudflare/BrowserRendering/BrowserRendering.d.ts +116 -0
  46. package/lib/Cloudflare/BrowserRendering/BrowserRendering.d.ts.map +1 -0
  47. package/lib/Cloudflare/BrowserRendering/BrowserRendering.js +92 -0
  48. package/lib/Cloudflare/BrowserRendering/BrowserRendering.js.map +1 -0
  49. package/lib/Cloudflare/BrowserRendering/BrowserRenderingBinding.d.ts +55 -0
  50. package/lib/Cloudflare/BrowserRendering/BrowserRenderingBinding.d.ts.map +1 -0
  51. package/lib/Cloudflare/BrowserRendering/BrowserRenderingBinding.js +55 -0
  52. package/lib/Cloudflare/BrowserRendering/BrowserRenderingBinding.js.map +1 -0
  53. package/lib/Cloudflare/BrowserRendering/index.d.ts +3 -0
  54. package/lib/Cloudflare/BrowserRendering/index.d.ts.map +1 -0
  55. package/lib/Cloudflare/BrowserRendering/index.js +3 -0
  56. package/lib/Cloudflare/BrowserRendering/index.js.map +1 -0
  57. package/lib/Cloudflare/Container/Container.d.ts +3 -3
  58. package/lib/Cloudflare/Container/Container.js +3 -3
  59. package/lib/Cloudflare/Container/StartContainer.d.ts.map +1 -1
  60. package/lib/Cloudflare/Container/StartContainer.js.map +1 -1
  61. package/lib/Cloudflare/D1/D1Database.d.ts +1 -0
  62. package/lib/Cloudflare/D1/D1Database.d.ts.map +1 -1
  63. package/lib/Cloudflare/D1/D1Database.js +2 -1
  64. package/lib/Cloudflare/D1/D1Database.js.map +1 -1
  65. package/lib/Cloudflare/D1/D1DatabaseBinding.js +1 -1
  66. package/lib/Cloudflare/D1/D1DatabaseBinding.js.map +1 -1
  67. package/lib/Cloudflare/Fetcher.d.ts.map +1 -1
  68. package/lib/Cloudflare/Fetcher.js +0 -2
  69. package/lib/Cloudflare/Fetcher.js.map +1 -1
  70. package/lib/Cloudflare/Hyperdrive/Hyperdrive.d.ts +1 -0
  71. package/lib/Cloudflare/Hyperdrive/Hyperdrive.d.ts.map +1 -1
  72. package/lib/Cloudflare/Hyperdrive/Hyperdrive.js +3 -0
  73. package/lib/Cloudflare/Hyperdrive/Hyperdrive.js.map +1 -1
  74. package/lib/Cloudflare/Hyperdrive/HyperdriveBinding.d.ts +3 -2
  75. package/lib/Cloudflare/Hyperdrive/HyperdriveBinding.d.ts.map +1 -1
  76. package/lib/Cloudflare/Hyperdrive/HyperdriveBinding.js +32 -33
  77. package/lib/Cloudflare/Hyperdrive/HyperdriveBinding.js.map +1 -1
  78. package/lib/Cloudflare/KV/KVNamespace.d.ts +1 -0
  79. package/lib/Cloudflare/KV/KVNamespace.d.ts.map +1 -1
  80. package/lib/Cloudflare/KV/KVNamespace.js +2 -0
  81. package/lib/Cloudflare/KV/KVNamespace.js.map +1 -1
  82. package/lib/Cloudflare/Local.js +1 -1
  83. package/lib/Cloudflare/Local.js.map +1 -1
  84. package/lib/Cloudflare/Providers.d.ts +2 -1
  85. package/lib/Cloudflare/Providers.d.ts.map +1 -1
  86. package/lib/Cloudflare/Providers.js +25 -17
  87. package/lib/Cloudflare/Providers.js.map +1 -1
  88. package/lib/Cloudflare/Queue/Queue.d.ts +1 -0
  89. package/lib/Cloudflare/Queue/Queue.d.ts.map +1 -1
  90. package/lib/Cloudflare/Queue/Queue.js +1 -0
  91. package/lib/Cloudflare/Queue/Queue.js.map +1 -1
  92. package/lib/Cloudflare/Queue/QueueConsumer.d.ts +2 -1
  93. package/lib/Cloudflare/Queue/QueueConsumer.d.ts.map +1 -1
  94. package/lib/Cloudflare/Queue/QueueConsumer.js +10 -3
  95. package/lib/Cloudflare/Queue/QueueConsumer.js.map +1 -1
  96. package/lib/Cloudflare/Queue/QueueEventSource.d.ts +30 -4
  97. package/lib/Cloudflare/Queue/QueueEventSource.d.ts.map +1 -1
  98. package/lib/Cloudflare/Queue/QueueEventSource.js +22 -1
  99. package/lib/Cloudflare/Queue/QueueEventSource.js.map +1 -1
  100. package/lib/Cloudflare/R2/R2Bucket.d.ts +1 -0
  101. package/lib/Cloudflare/R2/R2Bucket.d.ts.map +1 -1
  102. package/lib/Cloudflare/R2/R2Bucket.js +18 -0
  103. package/lib/Cloudflare/R2/R2Bucket.js.map +1 -1
  104. package/lib/Cloudflare/SecretsStore/Secret.d.ts.map +1 -1
  105. package/lib/Cloudflare/SecretsStore/Secret.js +13 -34
  106. package/lib/Cloudflare/SecretsStore/Secret.js.map +1 -1
  107. package/lib/Cloudflare/SecretsStore/SecretBinding.d.ts +3 -2
  108. package/lib/Cloudflare/SecretsStore/SecretBinding.d.ts.map +1 -1
  109. package/lib/Cloudflare/SecretsStore/SecretBinding.js +3 -2
  110. package/lib/Cloudflare/SecretsStore/SecretBinding.js.map +1 -1
  111. package/lib/Cloudflare/StateStore/Api.d.ts +5 -13
  112. package/lib/Cloudflare/StateStore/Api.d.ts.map +1 -1
  113. package/lib/Cloudflare/StateStore/Api.js +14 -8
  114. package/lib/Cloudflare/StateStore/Api.js.map +1 -1
  115. package/lib/Cloudflare/StateStore/State.d.ts +11 -65
  116. package/lib/Cloudflare/StateStore/State.d.ts.map +1 -1
  117. package/lib/Cloudflare/StateStore/State.js +320 -343
  118. package/lib/Cloudflare/StateStore/State.js.map +1 -1
  119. package/lib/Cloudflare/StateStore/Store.d.ts.map +1 -1
  120. package/lib/Cloudflare/StateStore/Store.js +21 -31
  121. package/lib/Cloudflare/StateStore/Store.js.map +1 -1
  122. package/lib/Cloudflare/Vectorize/VectorizeIndex.d.ts +114 -0
  123. package/lib/Cloudflare/Vectorize/VectorizeIndex.d.ts.map +1 -0
  124. package/lib/Cloudflare/Vectorize/VectorizeIndex.js +157 -0
  125. package/lib/Cloudflare/Vectorize/VectorizeIndex.js.map +1 -0
  126. package/lib/Cloudflare/Vectorize/VectorizeIndexBinding.d.ts +38 -0
  127. package/lib/Cloudflare/Vectorize/VectorizeIndexBinding.d.ts.map +1 -0
  128. package/lib/Cloudflare/Vectorize/VectorizeIndexBinding.js +44 -0
  129. package/lib/Cloudflare/Vectorize/VectorizeIndexBinding.js.map +1 -0
  130. package/lib/Cloudflare/Vectorize/VectorizeMetadataIndex.d.ts +72 -0
  131. package/lib/Cloudflare/Vectorize/VectorizeMetadataIndex.d.ts.map +1 -0
  132. package/lib/Cloudflare/Vectorize/VectorizeMetadataIndex.js +131 -0
  133. package/lib/Cloudflare/Vectorize/VectorizeMetadataIndex.js.map +1 -0
  134. package/lib/Cloudflare/Vectorize/index.d.ts +4 -0
  135. package/lib/Cloudflare/Vectorize/index.d.ts.map +1 -0
  136. package/lib/Cloudflare/Vectorize/index.js +4 -0
  137. package/lib/Cloudflare/Vectorize/index.js.map +1 -0
  138. package/lib/Cloudflare/VpcService/VpcService.d.ts +2 -2
  139. package/lib/Cloudflare/VpcService/VpcService.d.ts.map +1 -1
  140. package/lib/Cloudflare/Website/StaticSite.d.ts +5 -5
  141. package/lib/Cloudflare/Website/StaticSite.d.ts.map +1 -1
  142. package/lib/Cloudflare/Website/StaticSite.js +3 -0
  143. package/lib/Cloudflare/Website/StaticSite.js.map +1 -1
  144. package/lib/Cloudflare/Website/Vite.d.ts +5 -5
  145. package/lib/Cloudflare/Website/Vite.d.ts.map +1 -1
  146. package/lib/Cloudflare/Website/Vite.js.map +1 -1
  147. package/lib/Cloudflare/Workers/Assets.d.ts.map +1 -1
  148. package/lib/Cloudflare/Workers/Assets.js +1 -1
  149. package/lib/Cloudflare/Workers/Assets.js.map +1 -1
  150. package/lib/Cloudflare/Workers/DurableObjectBridge.d.ts.map +1 -1
  151. package/lib/Cloudflare/Workers/DurableObjectBridge.js +4 -2
  152. package/lib/Cloudflare/Workers/DurableObjectBridge.js.map +1 -1
  153. package/lib/Cloudflare/Workers/DurableObjectNamespace.d.ts +183 -6
  154. package/lib/Cloudflare/Workers/DurableObjectNamespace.d.ts.map +1 -1
  155. package/lib/Cloudflare/Workers/DurableObjectNamespace.js +279 -76
  156. package/lib/Cloudflare/Workers/DurableObjectNamespace.js.map +1 -1
  157. package/lib/Cloudflare/Workers/HttpServer.d.ts +6 -4
  158. package/lib/Cloudflare/Workers/HttpServer.d.ts.map +1 -1
  159. package/lib/Cloudflare/Workers/HttpServer.js +20 -15
  160. package/lib/Cloudflare/Workers/HttpServer.js.map +1 -1
  161. package/lib/Cloudflare/Workers/InferEnv.d.ts +3 -2
  162. package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
  163. package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts +4 -7
  164. package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
  165. package/lib/Cloudflare/Workers/LocalWorkerProvider.js +111 -66
  166. package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
  167. package/lib/Cloudflare/Workers/Rpc.d.ts +16 -0
  168. package/lib/Cloudflare/Workers/Rpc.d.ts.map +1 -1
  169. package/lib/Cloudflare/Workers/Rpc.js +22 -0
  170. package/lib/Cloudflare/Workers/Rpc.js.map +1 -1
  171. package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.d.ts +285 -0
  172. package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.d.ts.map +1 -0
  173. package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.js +288 -0
  174. package/lib/Cloudflare/Workers/RpcDurableObjectNamespace.js.map +1 -0
  175. package/lib/Cloudflare/Workers/RpcWorker.d.ts +305 -0
  176. package/lib/Cloudflare/Workers/RpcWorker.d.ts.map +1 -0
  177. package/lib/Cloudflare/Workers/RpcWorker.js +350 -0
  178. package/lib/Cloudflare/Workers/RpcWorker.js.map +1 -0
  179. package/lib/Cloudflare/Workers/Vite.d.ts +1 -1
  180. package/lib/Cloudflare/Workers/Vite.d.ts.map +1 -1
  181. package/lib/Cloudflare/Workers/Vite.js +2 -1
  182. package/lib/Cloudflare/Workers/Vite.js.map +1 -1
  183. package/lib/Cloudflare/Workers/Worker.d.ts +69 -24
  184. package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
  185. package/lib/Cloudflare/Workers/Worker.js +168 -47
  186. package/lib/Cloudflare/Workers/Worker.js.map +1 -1
  187. package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts +1 -1
  188. package/lib/Cloudflare/Workers/WorkerAsyncBindings.d.ts.map +1 -1
  189. package/lib/Cloudflare/Workers/WorkerAsyncBindings.js +166 -97
  190. package/lib/Cloudflare/Workers/WorkerAsyncBindings.js.map +1 -1
  191. package/lib/Cloudflare/Workers/WorkerBinding.d.ts +12 -23
  192. package/lib/Cloudflare/Workers/WorkerBinding.d.ts.map +1 -1
  193. package/lib/Cloudflare/Workers/WorkerBinding.js +3 -0
  194. package/lib/Cloudflare/Workers/WorkerBinding.js.map +1 -1
  195. package/lib/Cloudflare/Workers/WorkerBridge.d.ts.map +1 -1
  196. package/lib/Cloudflare/Workers/WorkerBridge.js +5 -2
  197. package/lib/Cloudflare/Workers/WorkerBridge.js.map +1 -1
  198. package/lib/Cloudflare/Workers/WorkerBundle.d.ts.map +1 -1
  199. package/lib/Cloudflare/Workers/WorkerBundle.js +4 -1
  200. package/lib/Cloudflare/Workers/WorkerBundle.js.map +1 -1
  201. package/lib/Cloudflare/Workers/WorkerRuntimeContext.d.ts.map +1 -1
  202. package/lib/Cloudflare/Workers/WorkerRuntimeContext.js +9 -10
  203. package/lib/Cloudflare/Workers/WorkerRuntimeContext.js.map +1 -1
  204. package/lib/Cloudflare/Workers/Workflow.d.ts +5 -3
  205. package/lib/Cloudflare/Workers/Workflow.d.ts.map +1 -1
  206. package/lib/Cloudflare/Workers/Workflow.js +19 -1
  207. package/lib/Cloudflare/Workers/Workflow.js.map +1 -1
  208. package/lib/Cloudflare/Workers/index.d.ts +2 -0
  209. package/lib/Cloudflare/Workers/index.d.ts.map +1 -1
  210. package/lib/Cloudflare/Workers/index.js +2 -0
  211. package/lib/Cloudflare/Workers/index.js.map +1 -1
  212. package/lib/Cloudflare/index.d.ts +2 -0
  213. package/lib/Cloudflare/index.d.ts.map +1 -1
  214. package/lib/Cloudflare/index.js +2 -0
  215. package/lib/Cloudflare/index.js.map +1 -1
  216. package/lib/Dependencies.d.ts +10 -0
  217. package/lib/Dependencies.d.ts.map +1 -0
  218. package/lib/Dependencies.js +1 -0
  219. package/lib/Dependencies.js.map +1 -0
  220. package/lib/Deploy.d.ts +2 -1
  221. package/lib/Deploy.d.ts.map +1 -1
  222. package/lib/Deploy.js +2 -2
  223. package/lib/Deploy.js.map +1 -1
  224. package/lib/Diff.d.ts +11 -0
  225. package/lib/Diff.d.ts.map +1 -1
  226. package/lib/Diff.js +11 -0
  227. package/lib/Diff.js.map +1 -1
  228. package/lib/Input.d.ts +2 -1
  229. package/lib/Input.d.ts.map +1 -1
  230. package/lib/KeyPair.d.ts +77 -0
  231. package/lib/KeyPair.d.ts.map +1 -0
  232. package/lib/KeyPair.js +102 -0
  233. package/lib/KeyPair.js.map +1 -0
  234. package/lib/Local/RpcProvider.d.ts +3 -1
  235. package/lib/Local/RpcProvider.d.ts.map +1 -1
  236. package/lib/Local/RpcProvider.js +28 -2
  237. package/lib/Local/RpcProvider.js.map +1 -1
  238. package/lib/Local/RpcServerEnvironment.js +1 -1
  239. package/lib/Local/RpcServerEnvironment.js.map +1 -1
  240. package/lib/Neon/Project.d.ts.map +1 -1
  241. package/lib/Neon/Project.js +14 -3
  242. package/lib/Neon/Project.js.map +1 -1
  243. package/lib/Output.d.ts.map +1 -1
  244. package/lib/Output.js +9 -2
  245. package/lib/Output.js.map +1 -1
  246. package/lib/Phase.d.ts +2 -1
  247. package/lib/Phase.d.ts.map +1 -1
  248. package/lib/Phase.js +6 -1
  249. package/lib/Phase.js.map +1 -1
  250. package/lib/Plan.d.ts.map +1 -1
  251. package/lib/Plan.js +14 -3
  252. package/lib/Plan.js.map +1 -1
  253. package/lib/Platform.d.ts +8 -6
  254. package/lib/Platform.d.ts.map +1 -1
  255. package/lib/Platform.js +33 -3
  256. package/lib/Platform.js.map +1 -1
  257. package/lib/Random.d.ts.map +1 -1
  258. package/lib/Random.js +9 -14
  259. package/lib/Random.js.map +1 -1
  260. package/lib/RuntimeContext.d.ts +21 -1
  261. package/lib/RuntimeContext.d.ts.map +1 -1
  262. package/lib/RuntimeContext.js +12 -0
  263. package/lib/RuntimeContext.js.map +1 -1
  264. package/lib/Stack.d.ts +3 -3
  265. package/lib/Stack.d.ts.map +1 -1
  266. package/lib/Stack.js.map +1 -1
  267. package/lib/State/HttpStateApi.d.ts +2 -2
  268. package/lib/State/HttpStateStore.d.ts +4 -0
  269. package/lib/State/HttpStateStore.d.ts.map +1 -1
  270. package/lib/State/HttpStateStore.js +13 -0
  271. package/lib/State/HttpStateStore.js.map +1 -1
  272. package/lib/State/StateEncoding.d.ts +8 -0
  273. package/lib/State/StateEncoding.d.ts.map +1 -1
  274. package/lib/State/StateEncoding.js +55 -5
  275. package/lib/State/StateEncoding.js.map +1 -1
  276. package/lib/Test/Bun.d.ts.map +1 -1
  277. package/lib/Test/Bun.js +0 -2
  278. package/lib/Test/Bun.js.map +1 -1
  279. package/lib/Test/Vitest.d.ts.map +1 -1
  280. package/lib/Test/Vitest.js +0 -2
  281. package/lib/Test/Vitest.js.map +1 -1
  282. package/lib/Util/Duration.d.ts +14 -0
  283. package/lib/Util/Duration.d.ts.map +1 -0
  284. package/lib/Util/Duration.js +18 -0
  285. package/lib/Util/Duration.js.map +1 -0
  286. package/lib/Util/index.d.ts +0 -6
  287. package/lib/Util/index.d.ts.map +1 -1
  288. package/lib/Util/index.js +0 -6
  289. package/lib/Util/index.js.map +1 -1
  290. package/lib/Util/poll.d.ts +30 -0
  291. package/lib/Util/poll.d.ts.map +1 -0
  292. package/lib/Util/poll.js +26 -0
  293. package/lib/Util/poll.js.map +1 -0
  294. package/lib/Util/types.d.ts +3 -1
  295. package/lib/Util/types.d.ts.map +1 -1
  296. package/lib/Util/types.js +5 -1
  297. package/lib/Util/types.js.map +1 -1
  298. package/lib/index.d.ts +2 -3
  299. package/lib/index.d.ts.map +1 -1
  300. package/lib/index.js +1 -3
  301. package/lib/index.js.map +1 -1
  302. package/lib/tsconfig.test.tsbuildinfo +1 -1
  303. package/package.json +20 -19
  304. package/src/AWS/Lambda/Function.ts +87 -34
  305. package/src/AWS/Providers.ts +3 -0
  306. package/src/AlchemyContext.ts +0 -1
  307. package/src/Apply.ts +18 -1
  308. package/src/Auth/AuthProvider.ts +25 -5
  309. package/src/Auth/Credentials.ts +8 -7
  310. package/src/Cli/commands/_shared.ts +47 -4
  311. package/src/Cli/commands/cloudflare.ts +5 -3
  312. package/src/Cli/commands/dev.ts +13 -1
  313. package/src/Cli/commands/login.ts +20 -4
  314. package/src/Cli/commands/profile.ts +24 -34
  315. package/src/Cli/main.ts +0 -3
  316. package/src/Cloudflare/AiGateway/AiGateway.ts +2 -6
  317. package/src/Cloudflare/BrowserRendering/BrowserRendering.ts +132 -0
  318. package/src/Cloudflare/BrowserRendering/BrowserRenderingBinding.ts +137 -0
  319. package/src/Cloudflare/BrowserRendering/index.ts +11 -0
  320. package/src/Cloudflare/Container/Container.ts +3 -3
  321. package/src/Cloudflare/Container/StartContainer.ts +1 -2
  322. package/src/Cloudflare/D1/D1Database.ts +4 -1
  323. package/src/Cloudflare/D1/D1DatabaseBinding.ts +1 -1
  324. package/src/Cloudflare/Fetcher.ts +0 -2
  325. package/src/Cloudflare/Hyperdrive/Hyperdrive.ts +5 -0
  326. package/src/Cloudflare/Hyperdrive/HyperdriveBinding.ts +41 -43
  327. package/src/Cloudflare/KV/KVNamespace.ts +4 -0
  328. package/src/Cloudflare/Local.ts +1 -1
  329. package/src/Cloudflare/Providers.ts +32 -16
  330. package/src/Cloudflare/Queue/Queue.ts +3 -0
  331. package/src/Cloudflare/Queue/QueueConsumer.ts +21 -8
  332. package/src/Cloudflare/Queue/QueueEventSource.ts +33 -5
  333. package/src/Cloudflare/R2/R2Bucket.ts +26 -0
  334. package/src/Cloudflare/SecretsStore/Secret.ts +14 -41
  335. package/src/Cloudflare/SecretsStore/SecretBinding.ts +11 -11
  336. package/src/Cloudflare/StateStore/Api.ts +15 -15
  337. package/src/Cloudflare/StateStore/State.ts +468 -468
  338. package/src/Cloudflare/StateStore/Store.ts +27 -37
  339. package/src/Cloudflare/Vectorize/VectorizeIndex.ts +261 -0
  340. package/src/Cloudflare/Vectorize/VectorizeIndexBinding.ts +103 -0
  341. package/src/Cloudflare/Vectorize/VectorizeMetadataIndex.ts +208 -0
  342. package/src/Cloudflare/Vectorize/index.ts +3 -0
  343. package/src/Cloudflare/VpcService/VpcService.ts +2 -2
  344. package/src/Cloudflare/Website/StaticSite.ts +8 -10
  345. package/src/Cloudflare/Website/Vite.ts +4 -7
  346. package/src/Cloudflare/Workers/Assets.ts +1 -1
  347. package/src/Cloudflare/Workers/DurableObjectBridge.ts +7 -4
  348. package/src/Cloudflare/Workers/DurableObjectNamespace.ts +380 -121
  349. package/src/Cloudflare/Workers/HttpServer.ts +31 -25
  350. package/src/Cloudflare/Workers/InferEnv.ts +15 -8
  351. package/src/Cloudflare/Workers/LocalWorkerProvider.ts +139 -78
  352. package/src/Cloudflare/Workers/Rpc.ts +50 -0
  353. package/src/Cloudflare/Workers/RpcDurableObjectNamespace.ts +502 -0
  354. package/src/Cloudflare/Workers/RpcWorker.ts +562 -0
  355. package/src/Cloudflare/Workers/Vite.ts +2 -0
  356. package/src/Cloudflare/Workers/Worker.ts +274 -93
  357. package/src/Cloudflare/Workers/WorkerAsyncBindings.ts +165 -103
  358. package/src/Cloudflare/Workers/WorkerBinding.ts +12 -0
  359. package/src/Cloudflare/Workers/WorkerBridge.ts +7 -4
  360. package/src/Cloudflare/Workers/WorkerBundle.ts +4 -1
  361. package/src/Cloudflare/Workers/WorkerRuntimeContext.ts +8 -15
  362. package/src/Cloudflare/Workers/Workflow.ts +22 -3
  363. package/src/Cloudflare/Workers/index.ts +2 -0
  364. package/src/Cloudflare/index.ts +2 -0
  365. package/src/Dependencies.ts +10 -0
  366. package/src/Deploy.ts +3 -1
  367. package/src/Diff.ts +13 -0
  368. package/src/Input.ts +2 -0
  369. package/src/KeyPair.ts +146 -0
  370. package/src/Local/RpcProvider.ts +45 -1
  371. package/src/Local/RpcServerEnvironment.ts +1 -1
  372. package/src/Neon/Project.ts +16 -3
  373. package/src/Output.ts +8 -2
  374. package/src/Phase.ts +8 -0
  375. package/src/Plan.ts +16 -3
  376. package/src/Platform.ts +74 -27
  377. package/src/Random.ts +22 -27
  378. package/src/RuntimeContext.ts +23 -1
  379. package/src/Stack.ts +3 -3
  380. package/src/State/HttpStateStore.ts +28 -0
  381. package/src/State/StateEncoding.ts +58 -7
  382. package/src/Test/Bun.ts +0 -3
  383. package/src/Test/Vitest.ts +0 -3
  384. package/src/Util/Duration.ts +21 -0
  385. package/src/Util/index.ts +0 -6
  386. package/src/Util/poll.ts +47 -0
  387. package/src/Util/types.ts +9 -2
  388. package/src/index.ts +2 -3
  389. package/lib/Secret.d.ts +0 -50
  390. package/lib/Secret.d.ts.map +0 -1
  391. package/lib/Secret.js +0 -23
  392. package/lib/Secret.js.map +0 -1
  393. package/lib/Trait.d.ts +0 -43
  394. package/lib/Trait.d.ts.map +0 -1
  395. package/lib/Trait.js +0 -17
  396. package/lib/Trait.js.map +0 -1
  397. package/lib/Util/LocalhostDns.d.ts +0 -23
  398. package/lib/Util/LocalhostDns.d.ts.map +0 -1
  399. package/lib/Util/LocalhostDns.js +0 -46
  400. package/lib/Util/LocalhostDns.js.map +0 -1
  401. package/lib/Util/assert-never.d.ts +0 -12
  402. package/lib/Util/assert-never.d.ts.map +0 -1
  403. package/lib/Util/assert-never.js +0 -11
  404. package/lib/Util/assert-never.js.map +0 -1
  405. package/lib/Util/class.d.ts +0 -3
  406. package/lib/Util/class.d.ts.map +0 -1
  407. package/lib/Util/class.js +0 -1
  408. package/lib/Util/class.js.map +0 -1
  409. package/lib/Util/ignore.d.ts +0 -40
  410. package/lib/Util/ignore.d.ts.map +0 -1
  411. package/lib/Util/ignore.js +0 -591
  412. package/lib/Util/ignore.js.map +0 -1
  413. package/lib/Util/instance.d.ts +0 -4
  414. package/lib/Util/instance.d.ts.map +0 -1
  415. package/lib/Util/instance.js +0 -1
  416. package/lib/Util/instance.js.map +0 -1
  417. package/lib/Util/pointer.d.ts +0 -5
  418. package/lib/Util/pointer.d.ts.map +0 -1
  419. package/lib/Util/pointer.js +0 -1
  420. package/lib/Util/pointer.js.map +0 -1
  421. package/lib/Util/schema-to-type.d.ts +0 -42
  422. package/lib/Util/schema-to-type.d.ts.map +0 -1
  423. package/lib/Util/schema-to-type.js +0 -364
  424. package/lib/Util/schema-to-type.js.map +0 -1
  425. package/lib/Util/todo.d.ts +0 -3
  426. package/lib/Util/todo.d.ts.map +0 -1
  427. package/lib/Util/todo.js +0 -3
  428. package/lib/Util/todo.js.map +0 -1
  429. package/lib/Variable.d.ts +0 -29
  430. package/lib/Variable.d.ts.map +0 -1
  431. package/lib/Variable.js +0 -9
  432. package/lib/Variable.js.map +0 -1
  433. package/src/Secret.ts +0 -87
  434. package/src/Trait.ts +0 -105
  435. package/src/Util/LocalhostDns.ts +0 -52
  436. package/src/Util/assert-never.ts +0 -18
  437. package/src/Util/class.ts +0 -7
  438. package/src/Util/ignore.ts +0 -815
  439. package/src/Util/instance.ts +0 -9
  440. package/src/Util/pointer.ts +0 -5
  441. package/src/Util/schema-to-type.ts +0 -456
  442. package/src/Util/todo.ts +0 -4
  443. package/src/Variable.ts +0 -44
package/src/KeyPair.ts ADDED
@@ -0,0 +1,146 @@
1
+ import * as NodeCrypto from "node:crypto";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Redacted from "effect/Redacted";
4
+ import * as Provider from "./Provider.ts";
5
+ import { Resource } from "./Resource.ts";
6
+
7
+ export type KeyPairAlgorithm = "ed25519" | "rsa" | "ec";
8
+
9
+ export interface KeyPairProps {
10
+ /**
11
+ * Key algorithm used to generate the pair.
12
+ * @default "ed25519"
13
+ */
14
+ algorithm?: KeyPairAlgorithm;
15
+ /**
16
+ * Modulus length in bits. Only used when {@link algorithm} is `"rsa"`.
17
+ * @default 2048
18
+ */
19
+ modulusLength?: number;
20
+ /**
21
+ * Named curve. Only used when {@link algorithm} is `"ec"`.
22
+ * @default "P-256"
23
+ */
24
+ namedCurve?: string;
25
+ }
26
+
27
+ export type KeyPair = Resource<
28
+ "Alchemy.KeyPair",
29
+ KeyPairProps,
30
+ {
31
+ algorithm: KeyPairAlgorithm;
32
+ privateKey: Redacted.Redacted<string>;
33
+ publicKey: string;
34
+ }
35
+ >;
36
+
37
+ /**
38
+ * A deterministic-in-state public/private keypair generator.
39
+ *
40
+ * The keypair is generated once on first reconcile and then persisted in
41
+ * state so subsequent deploys keep the same keys unless the resource is
42
+ * replaced. `privateKey` is PEM-encoded `pkcs8` and `publicKey` is
43
+ * PEM-encoded `spki`.
44
+ *
45
+ * @resource
46
+ *
47
+ * @section Generating a Keypair
48
+ * @example Default ed25519 keypair
49
+ * ```typescript
50
+ * const keys = yield* KeyPair("signing-key");
51
+ * // keys.privateKey: Redacted<string> (PEM pkcs8)
52
+ * // keys.publicKey: string (PEM spki)
53
+ * // keys.algorithm: "ed25519"
54
+ * ```
55
+ *
56
+ * @example RSA keypair
57
+ * ```typescript
58
+ * const keys = yield* KeyPair("rsa-key", {
59
+ * algorithm: "rsa",
60
+ * modulusLength: 2048,
61
+ * });
62
+ * ```
63
+ *
64
+ * @example EC keypair on a named curve
65
+ * ```typescript
66
+ * const keys = yield* KeyPair("ec-key", {
67
+ * algorithm: "ec",
68
+ * namedCurve: "P-256",
69
+ * });
70
+ * ```
71
+ *
72
+ * @section Consuming the Keys
73
+ * @example Pass the private key to a Worker as a secret
74
+ * ```typescript
75
+ * const keys = yield* KeyPair("signing-key");
76
+ * export const Worker = Cloudflare.Worker("Worker", {
77
+ * main: "./src/worker.ts",
78
+ * bindings: {
79
+ * SIGNING_KEY: keys.privateKey,
80
+ * PUBLIC_KEY: keys.publicKey,
81
+ * },
82
+ * });
83
+ * ```
84
+ */
85
+ export const KeyPair = Resource<KeyPair>("Alchemy.KeyPair");
86
+
87
+ const pemEncoding = {
88
+ privateKeyEncoding: { type: "pkcs8", format: "pem" },
89
+ publicKeyEncoding: { type: "spki", format: "pem" },
90
+ } as const;
91
+
92
+ const generate = (
93
+ props: KeyPairProps,
94
+ ): {
95
+ privateKey: string;
96
+ publicKey: string;
97
+ algorithm: KeyPairAlgorithm;
98
+ } => {
99
+ const algorithm = props.algorithm ?? "ed25519";
100
+ if (algorithm === "rsa") {
101
+ const { privateKey, publicKey } = NodeCrypto.generateKeyPairSync("rsa", {
102
+ modulusLength: props.modulusLength ?? 2048,
103
+ ...pemEncoding,
104
+ });
105
+ return { algorithm, privateKey, publicKey };
106
+ }
107
+ if (algorithm === "ec") {
108
+ const { privateKey, publicKey } = NodeCrypto.generateKeyPairSync("ec", {
109
+ namedCurve: props.namedCurve ?? "P-256",
110
+ ...pemEncoding,
111
+ });
112
+ return { algorithm, privateKey, publicKey };
113
+ }
114
+ const { privateKey, publicKey } = NodeCrypto.generateKeyPairSync(
115
+ "ed25519",
116
+ pemEncoding,
117
+ );
118
+ return { algorithm, privateKey, publicKey };
119
+ };
120
+
121
+ export const KeyPairProvider = () =>
122
+ Provider.succeed(KeyPair, {
123
+ reconcile: Effect.fn(function* ({ news = {}, output }) {
124
+ // Observe — there is no remote state. The cached `output` is the
125
+ // authoritative current value; once minted the keypair is preserved
126
+ // across reconciles to keep it stable.
127
+ if (output?.privateKey && output?.publicKey) {
128
+ return output;
129
+ }
130
+
131
+ // Ensure — no observed value: mint a fresh keypair. The next
132
+ // reconcile will see this in `output` and short-circuit above.
133
+ const generated = yield* Effect.sync(() => generate(news));
134
+ return {
135
+ algorithm: generated.algorithm,
136
+ privateKey: Redacted.make(generated.privateKey),
137
+ publicKey: generated.publicKey,
138
+ };
139
+ }),
140
+ delete: Effect.fn(function* () {
141
+ return undefined;
142
+ }),
143
+ read: Effect.fn(function* ({ output }) {
144
+ return output;
145
+ }),
146
+ });
@@ -1,9 +1,16 @@
1
+ import type * as Context from "effect/Context";
1
2
  import * as Effect from "effect/Effect";
2
3
  import * as Layer from "effect/Layer";
4
+ import * as Option from "effect/Option";
5
+ import * as Predicate from "effect/Predicate";
3
6
  import type { Scope } from "effect/Scope";
7
+ import * as Stream from "effect/Stream";
8
+ import { InstanceId } from "../InstanceId.ts";
4
9
  import type { Platform } from "../Platform.ts";
5
10
  import * as Provider from "../Provider.ts";
6
11
  import type { ResourceClass, ResourceLike } from "../Resource.ts";
12
+ import { Stack } from "../Stack.ts";
13
+ import { Stage } from "../Stage.ts";
7
14
  import { RpcProviderProxy } from "./RpcProviderProxy.ts";
8
15
 
9
16
  /**
@@ -69,11 +76,48 @@ export const effect = <
69
76
  cls,
70
77
  Effect.gen(function* () {
71
78
  const client = yield* Effect.serviceOption(RpcProviderProxy);
72
- if (client._tag === "None") return yield* eff;
79
+ const stack = yield* Stack;
80
+
81
+ if (client._tag === "None") {
82
+ const provider = yield* eff;
83
+ return new Proxy(provider, {
84
+ get: (target, prop) => {
85
+ const value = (target as any)[prop];
86
+ if (!Predicate.isFunction(value)) return value;
87
+ return (...args: any[]) => {
88
+ const result = value(...args);
89
+ const services = Layer.mergeAll(
90
+ layerFallback(Stack, stack),
91
+ layerFallback(Stage, stack.stage),
92
+ Predicate.hasProperty(args[0], "instanceId") &&
93
+ Predicate.isString(args[0].instanceId)
94
+ ? layerFallback(InstanceId, args[0].instanceId)
95
+ : Layer.empty,
96
+ );
97
+ return result.pipe(
98
+ Stream.isStream(result)
99
+ ? Stream.provide(services)
100
+ : Effect.provide(services),
101
+ );
102
+ };
103
+ },
104
+ });
105
+ }
73
106
  return yield* client.value.get(serverEntryUrl, cls.Type);
74
107
  }),
75
108
  );
76
109
 
110
+ const layerFallback = <I, S>(
111
+ service: Context.Key<I, S>,
112
+ defaultValue: NoInfer<S>,
113
+ ) =>
114
+ Layer.effect(
115
+ service,
116
+ Effect.serviceOption(service).pipe(
117
+ Effect.map(Option.getOrElse(() => defaultValue)),
118
+ ),
119
+ );
120
+
77
121
  /**
78
122
  * Conditionally constructs a layer for use by an RpcProvider.
79
123
  * If the {@link RpcProviderProxy} is present in context, the layer is empty because it will not be used in this process.
@@ -29,7 +29,7 @@ export const layer = (environment: RpcServerEnvironment) =>
29
29
  CredentialsStoreLive,
30
30
  Layer.succeed(AuthProviders, {}),
31
31
  ConfigProvider.layer(
32
- loadConfigProvider(Option.fromUndefinedOr(environment.envFile)).pipe(
32
+ loadConfigProvider(Option.fromNullishOr(environment.envFile)).pipe(
33
33
  Effect.map((base) => withProfileOverride(base, environment.profile)),
34
34
  ),
35
35
  ),
@@ -136,7 +136,7 @@ const findProjectByName = (name: string) =>
136
136
  Effect.gen(function* () {
137
137
  const matches: ListProjectsOutput["projects"][number][] = [];
138
138
  let cursor: string | undefined;
139
- do {
139
+ while (true) {
140
140
  const page = yield* listProjects({
141
141
  search: name,
142
142
  ...(cursor !== undefined ? { cursor } : {}),
@@ -144,8 +144,21 @@ const findProjectByName = (name: string) =>
144
144
  for (const p of page.projects) {
145
145
  if (p.name === name) matches.push(p);
146
146
  }
147
- cursor = page.pagination?.cursor;
148
- } while (cursor);
147
+ const nextCursor = page.pagination?.cursor;
148
+ // Neon returns a `pagination.cursor` on every response — it's the
149
+ // `created_at` of the last row, not a "has next page" flag — so we
150
+ // can't loop on cursor presence alone or we spin forever re-fetching
151
+ // empty/identical pages. Stop once a page comes back empty or the
152
+ // cursor stops advancing.
153
+ if (
154
+ page.projects.length === 0 ||
155
+ nextCursor === undefined ||
156
+ nextCursor === cursor
157
+ ) {
158
+ break;
159
+ }
160
+ cursor = nextCursor;
161
+ }
149
162
  return matches;
150
163
  });
151
164
 
package/src/Output.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as Data from "effect/Data";
2
+ import * as Duration from "effect/Duration";
2
3
  import * as Effect from "effect/Effect";
3
4
  import { pipe } from "effect/Function";
4
5
  import type { Pipeable } from "effect/Pipeable";
@@ -6,7 +7,7 @@ import * as Redacted from "effect/Redacted";
6
7
  import { SingleShotGen } from "effect/Utils";
7
8
  import { getRefMetadata, isRef, type Ref } from "./Ref.ts";
8
9
  import { isResource, type Resource, type ResourceLike } from "./Resource.ts";
9
- import { RuntimeContext } from "./RuntimeContext.ts";
10
+ import { RuntimeContext, sanitizeKey } from "./RuntimeContext.ts";
10
11
  import { Stack } from "./Stack.ts";
11
12
  import { Stage } from "./Stage.ts";
12
13
  import * as State from "./State/State.ts";
@@ -112,9 +113,11 @@ export abstract class BaseExpr<A = any, Req = any> implements Output<A, Req> {
112
113
  }
113
114
 
114
115
  public bind(id: string): any {
116
+ // `set`/`get` store keys verbatim, so canonicalize here (the caller's job).
117
+ const key = sanitizeKey(id);
115
118
  return RuntimeContext.pipe(
116
119
  Effect.flatMap((ctx) =>
117
- Effect.map(ctx.set(id, this), (key) => ctx.get<A>(key)),
120
+ Effect.map(ctx.set(key, this), (k) => ctx.get<A>(k)),
118
121
  ),
119
122
  );
120
123
  }
@@ -590,6 +593,9 @@ export const evaluate: <A, Req = never>(
590
593
  return yield* Effect.all(expr.map((item) => evaluate(item, upstream)));
591
594
  } else if (Redacted.isRedacted(expr)) {
592
595
  return expr;
596
+ } else if (Duration.isDuration(expr)) {
597
+ // Opaque value — see resolveInput in Plan.ts for rationale.
598
+ return expr;
593
599
  } else if (typeof expr === "object" && expr !== null) {
594
600
  return Object.fromEntries(
595
601
  yield* Effect.all(
package/src/Phase.ts CHANGED
@@ -1,7 +1,15 @@
1
1
  import * as Config from "effect/Config";
2
2
  import * as Effect from "effect/Effect";
3
3
 
4
+ export type AlchemyPhase = "plan" | "runtime";
5
+
4
6
  export const ALCHEMY_PHASE = Config.string("ALCHEMY_PHASE").pipe(
5
7
  Config.withDefault("plan"),
8
+ Config.mapOrFail((value) => {
9
+ if (value !== "plan" && value !== "runtime") {
10
+ return Effect.die(new Error(`Invalid ALCHEMY_PHASE: ${value}`));
11
+ }
12
+ return Effect.succeed(value as AlchemyPhase);
13
+ }),
6
14
  Effect.orDie,
7
15
  );
package/src/Plan.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as Data from "effect/Data";
2
+ import * as Duration from "effect/Duration";
2
3
  import * as Effect from "effect/Effect";
3
4
  import * as Option from "effect/Option";
4
5
  import * as Redacted from "effect/Redacted";
@@ -18,6 +19,7 @@ import {
18
19
  makeScopedArtifacts,
19
20
  } from "./Artifacts.ts";
20
21
  import {
22
+ dedupeBindings,
21
23
  diffBindings,
22
24
  havePropsChanged,
23
25
  isResolved,
@@ -309,7 +311,11 @@ export const make = <A>(
309
311
  : oldState.props;
310
312
 
311
313
  const oldBindings = oldState.bindings ?? [];
312
- const newBindings = stack.bindings[resource.FQN] ?? [];
314
+ // Collapse duplicate bindings by sid so the binding set handed to
315
+ // `diff` matches what `reconcile` receives (see `dedupeBindings`).
316
+ const newBindings = dedupeBindings(
317
+ stack.bindings[resource.FQN] ?? [],
318
+ );
313
319
 
314
320
  const diff = yield* provider.diff
315
321
  ? provider
@@ -375,6 +381,11 @@ export const make = <A>(
375
381
  return yield* resolveOutput(input);
376
382
  } else if (Redacted.isRedacted(input)) {
377
383
  return input;
384
+ } else if (Duration.isDuration(input)) {
385
+ // Duration is an opaque value; walking its internal `.value`
386
+ // would destroy the prototype and produce a plain `{ value: ... }`
387
+ // object that downstream consumers can't interpret.
388
+ return input;
378
389
  } else if (Array.isArray(input)) {
379
390
  return yield* Effect.all(input.map(resolveInput), {
380
391
  concurrency: "unbounded",
@@ -627,8 +638,10 @@ export const make = <A>(
627
638
  const news = yield* resolveInput(resource.Props);
628
639
  const downstream = newDownstreamDependencies[fqn] ?? [];
629
640
 
630
- const newBindings: ResourceBinding[] = yield* resolveInput(
631
- stack.bindings[fqn] ?? [],
641
+ // Collapse duplicate bindings by sid so the binding set handed to
642
+ // `diff` matches what `reconcile` receives (see `dedupeBindings`).
643
+ const newBindings: ResourceBinding[] = dedupeBindings(
644
+ yield* resolveInput(stack.bindings[fqn] ?? []),
632
645
  );
633
646
  const persisted = yield* state.get({
634
647
  stack: stackName,
package/src/Platform.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import * as ConfigError from "effect/Config";
2
+ import * as ConfigProvider from "effect/ConfigProvider";
1
3
  import * as Context from "effect/Context";
2
4
  import * as Effect from "effect/Effect";
3
5
  import { pipe } from "effect/Function";
@@ -7,14 +9,21 @@ import type { Scope } from "effect/Scope";
7
9
  import type { HttpClient } from "effect/unstable/http/HttpClient";
8
10
  import { SingleShotGen } from "effect/Utils";
9
11
  import type { PolicyLike } from "./Binding.ts";
12
+ import type { Dependencies } from "./Dependencies.ts";
10
13
  import type { ExecutionContext } from "./ExecutionContext.ts";
11
14
  import type { HttpEffect } from "./Http.ts";
12
15
  import type { InputProps } from "./Input.ts";
16
+ import * as Output from "./Output.ts";
13
17
  import { ALCHEMY_PHASE } from "./Phase.ts";
14
18
  import type { Provider, ProviderCollectionLike } from "./Provider.ts";
15
19
  import { Resource, type ResourceLike } from "./Resource.ts";
16
20
  import type { Rpc } from "./Rpc.ts";
17
- import { RuntimeContext, type BaseRuntimeContext } from "./RuntimeContext.ts";
21
+ import {
22
+ CurrentRuntimeContext,
23
+ RuntimeContext,
24
+ sanitizeKey,
25
+ type BaseRuntimeContext,
26
+ } from "./RuntimeContext.ts";
18
27
  import { Self } from "./Self.ts";
19
28
  import type { Stack, StackServices } from "./Stack.ts";
20
29
  import type { Stage } from "./Stage.ts";
@@ -65,19 +74,19 @@ export interface Platform<
65
74
  Type: Resource["Type"];
66
75
  Provider: Provider<Resource>;
67
76
 
68
- <Self, Shape>(): {
77
+ <Self, Shape, Deps = never>(): {
69
78
  <PropsReq = never>(
70
79
  id: string,
71
80
  props:
72
81
  | InputProps<Resource["Props"]>
73
82
  | Effect.Effect<InputProps<Resource["Props"]>, never, PropsReq>,
74
83
  ): Effect.Effect<
75
- Resource & Rpc<Self>,
84
+ Resource & Rpc<Self> & Dependencies<Deps>,
76
85
  never,
77
- Self | Resource["Providers"] | PropsReq
86
+ Resource["Providers"] | PropsReq
78
87
  > & {
79
88
  make<InitReq = never>(
80
- impl: Effect.Effect<Shape, never, InitReq>,
89
+ impl: Effect.Effect<Shape, ConfigError.ConfigError, InitReq>,
81
90
  ): Layer.Layer<
82
91
  Self,
83
92
  never,
@@ -98,7 +107,7 @@ export interface Platform<
98
107
  props:
99
108
  | InputProps<Resource["Props"]>
100
109
  | Effect.Effect<Resource["Props"], never, PropsReq>,
101
- impl: Effect.Effect<Shape, never, InitReq>,
110
+ impl: Effect.Effect<Shape, ConfigError.ConfigError, InitReq>,
102
111
  ): Effect.Effect<
103
112
  Resource & Rpc<Self>,
104
113
  never,
@@ -119,7 +128,7 @@ export interface Platform<
119
128
  Resource["Providers"] | PropsReq
120
129
  > & {
121
130
  make<InitReq extends Services | PlatformServices = never>(
122
- impl: Effect.Effect<Shape, never, InitReq>,
131
+ impl: Effect.Effect<Shape, ConfigError.ConfigError, InitReq>,
123
132
  ): Layer.Layer<
124
133
  Self,
125
134
  never,
@@ -158,7 +167,7 @@ export interface Platform<
158
167
  props:
159
168
  | InputProps<Resource["Props"]>
160
169
  | Effect.Effect<InputProps<Resource["Props"]>, never, PropsReq>,
161
- impl: Effect.Effect<Shape, never, InitReq>,
170
+ impl: Effect.Effect<Shape, ConfigError.ConfigError, InitReq>,
162
171
  ): Effect.Effect<
163
172
  Resource & Rpc<Shape>,
164
173
  never,
@@ -343,28 +352,66 @@ export const Platform = <
343
352
  }) ?? Effect.die("No serve handler"))
344
353
  : Effect.void,
345
354
  ),
355
+
346
356
  Effect.provide(
347
- Layer.provideMerge(
348
- Layer.mergeAll(
349
- Layer.succeed(Platform.Platform, runtimeContext),
350
- Layer.succeed(PlatformContext, runtimeContext),
351
- Layer.succeed(RuntimeContext, runtimeContext),
352
- Layer.succeed(resource.Self, instance),
353
- Layer.succeed(Platform.Self, instance),
354
- Layer.succeed(Self, instance),
355
- runtimeContext.planServices
356
- ? Layer.unwrap(
357
- ALCHEMY_PHASE.pipe(
358
- Effect.map((phase) =>
359
- phase === "plan"
360
- ? runtimeContext.planServices!
361
- : Layer.empty,
357
+ Layer.effect(
358
+ ConfigProvider.ConfigProvider,
359
+ Effect.gen(function* () {
360
+ // a Config Provider that we use to intercept config lookups and bind them to the RuntimeContext
361
+ const configProvider =
362
+ yield* ConfigProvider.ConfigProvider;
363
+ const phase = yield* ALCHEMY_PHASE;
364
+
365
+ return ConfigProvider.make(
366
+ Effect.fnUntraced(function* (path) {
367
+ const ctx = yield* CurrentRuntimeContext;
368
+ // `set`/`get` store keys verbatim, so canonicalize the
369
+ // logical config path here (the caller's job) before
370
+ // handing it to the RuntimeContext.
371
+ const key = sanitizeKey(
372
+ path.map((p) => p.toString()).join("_"),
373
+ );
374
+ const node = yield* configProvider.get(path);
375
+ if (phase === "plan" && node) {
376
+ // bind it to the RuntimeContext if running in plan phase
377
+ const output = Output.literal(node.value);
378
+ yield* ctx?.set(key, output) ?? Effect.void;
379
+ return node;
380
+ } else if (phase === "runtime" && ctx) {
381
+ // retrieve from the RuntimeContext if running in runtime phase
382
+ const value = yield* ctx.get<string>(key);
383
+ if (value) {
384
+ return ConfigProvider.makeValue(value as string);
385
+ }
386
+ }
387
+ // fallback to the config provider otherwise
388
+ return node;
389
+ }),
390
+ );
391
+ }),
392
+ ).pipe(
393
+ Layer.provideMerge(
394
+ Layer.mergeAll(
395
+ Layer.succeed(Platform.Platform, runtimeContext),
396
+ Layer.succeed(PlatformContext, runtimeContext),
397
+ Layer.succeed(RuntimeContext, runtimeContext),
398
+ Layer.succeed(resource.Self, instance),
399
+ Layer.succeed(Platform.Self, instance),
400
+ Layer.succeed(Self, instance),
401
+ runtimeContext.planServices
402
+ ? Layer.unwrap(
403
+ ALCHEMY_PHASE.pipe(
404
+ Effect.map((phase) =>
405
+ phase === "plan"
406
+ ? runtimeContext.planServices!
407
+ : Layer.empty,
408
+ ),
362
409
  ),
363
- ),
364
- )
365
- : Layer.empty,
410
+ )
411
+ : Layer.empty,
412
+ ),
366
413
  ),
367
- Layer.succeedContext(outerServices),
414
+ Layer.provideMerge(Layer.succeedContext(outerServices)),
368
415
  ),
369
416
  ),
370
417
  );
package/src/Random.ts CHANGED
@@ -32,34 +32,29 @@ export const Random = Resource<Random>("Alchemy.Random");
32
32
 
33
33
  export const RandomProvider = () =>
34
34
  Provider.succeed(Random, {
35
- reconcile: Effect.fn(function* ({ news = {}, output }) {
36
- // Observe — there is no remote state. The cached `output.text` is
37
- // the authoritative current value; once minted it is preserved
38
- // across reconciles to keep the secret stable.
39
- if (output?.text) {
40
- return output;
41
- }
35
+ reconcile: ({ news = {}, output }) =>
36
+ Effect.sync(() => {
37
+ // Observe — there is no remote state. The cached `output.text` is
38
+ // the authoritative current value; once minted it is preserved
39
+ // across reconciles to keep the secret stable.
40
+ if (output?.text) {
41
+ return output;
42
+ }
42
43
 
43
- // Ensure — no observed value: mint a fresh random secret and
44
- // return it. The next reconcile will see this in `output` and
45
- // short-circuit above.
46
- const byteLength = news.bytes ?? 32;
47
- const text = yield* Effect.sync(() => {
44
+ // Ensure — no observed value: mint a fresh random secret and
45
+ // return it. The next reconcile will see this in `output` and
46
+ // short-circuit above.
47
+ const byteLength = news.bytes ?? 32;
48
48
  const bytes = new Uint8Array(byteLength);
49
49
  crypto.getRandomValues(bytes);
50
- return Redacted.make(
51
- Array.from(bytes)
52
- .map((b) => b.toString(16).padStart(2, "0"))
53
- .join(""),
54
- );
55
- });
56
-
57
- return { text };
58
- }),
59
- delete: Effect.fn(function* () {
60
- return undefined;
61
- }),
62
- read: Effect.fn(function* ({ output }) {
63
- return output;
64
- }),
50
+ return {
51
+ text: Redacted.make(
52
+ Array.from(bytes)
53
+ .map((b) => b.toString(16).padStart(2, "0"))
54
+ .join(""),
55
+ ),
56
+ };
57
+ }),
58
+ delete: () => Effect.void,
59
+ read: ({ output }) => Effect.succeed(output),
65
60
  });
@@ -9,7 +9,15 @@ export interface BaseRuntimeContext {
9
9
  Type: string;
10
10
  id: string;
11
11
  env: Record<string, any>;
12
- get<T>(key: string): Effect.Effect<T>;
12
+ /**
13
+ * Read a value by its (already-canonical) key. The key is used verbatim;
14
+ * callers must {@link sanitizeKey} first. See {@link sanitizeKey}.
15
+ */
16
+ get<T>(key: string): Effect.Effect<T | undefined>;
17
+ /**
18
+ * Store an output under the given (already-canonical) key, returning the key.
19
+ * The key is used verbatim; callers must {@link sanitizeKey} first.
20
+ */
13
21
  set(id: string, output: Output): Effect.Effect<string>;
14
22
  exports?: Effect.Effect<Record<string, any>>;
15
23
  serve?<Req = never>(
@@ -21,6 +29,20 @@ export interface BaseRuntimeContext {
21
29
  planServices?: Layer.Layer<any>;
22
30
  }
23
31
 
32
+ /**
33
+ * Canonicalize a logical key into a key that is safe to use as the name of an
34
+ * environment variable / binding (`[a-zA-Z][a-zA-Z0-9_]*`).
35
+ *
36
+ * `RuntimeContext.set`/`get` are dumb key/value stores: they read and write the
37
+ * key **verbatim**. It is the *caller's* responsibility to hand them a
38
+ * canonical key, since the caller is the one that knows the logical key may
39
+ * contain `.`/`-` (e.g. a dotted config name from `Platform`, or an
40
+ * `Output.toString()` like `"QueueSinkQueue.queueUrl"`). Callers run the key
41
+ * through this before calling `set`/`get` so both sides agree.
42
+ */
43
+ export const sanitizeKey = (key: string): string =>
44
+ key.replaceAll(/[^a-zA-Z0-9]/g, "_");
45
+
24
46
  /**
25
47
  * Context of the runtime environment.
26
48
  *
package/src/Stack.ts CHANGED
@@ -10,6 +10,7 @@ import * as Scope from "effect/Scope";
10
10
  import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient";
11
11
  import type { HttpClient } from "effect/unstable/http/HttpClient";
12
12
  import type { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner";
13
+ import type { ActionLike } from "./Action.ts";
13
14
  import { AlchemyContext, AlchemyContextLive } from "./AlchemyContext.ts";
14
15
  import { provideFreshArtifactStore } from "./Artifacts.ts";
15
16
  import { AuthProviders } from "./Auth/AuthProvider.ts";
@@ -20,7 +21,6 @@ import type { Input, InputProps } from "./Input.ts";
20
21
  import * as Output from "./Output.ts";
21
22
  import type { ResourceBinding, ResourceLike } from "./Resource.ts";
22
23
  import { Stage } from "./Stage.ts";
23
- import type { ActionLike } from "./Action.ts";
24
24
  import type { State } from "./State/State.ts";
25
25
  import { loadConfigProvider } from "./Util/ConfigProvider.ts";
26
26
  import { effectClass, taggedFunction } from "./Util/effect.ts";
@@ -291,8 +291,8 @@ const alchemy = (overrides?: { dev?: boolean }) =>
291
291
  : AlchemyContextLive,
292
292
  );
293
293
 
294
- export const evalStack = <A, B, Err, Req>(
295
- effect: StackEffect<CompiledStack<A>, Stage | AlchemyContext>,
294
+ export const evalStack = <A, B, StackErr, Err, Req>(
295
+ effect: StackEffect<CompiledStack<A>, StackErr, Stage | AlchemyContext>,
296
296
  fn: (stack: CompiledStack<A>) => Effect.Effect<B, Err, Req>,
297
297
  options: {
298
298
  stage: string;