alchemy 2.0.0-beta.34 → 2.0.0-beta.35

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 (356) hide show
  1. package/bin/cli.js +8 -7
  2. package/bin/exec.js +226 -52
  3. package/bin/exec.js.map +1 -1
  4. package/lib/AWS/AuthProvider.d.ts +7 -6
  5. package/lib/AWS/AuthProvider.d.ts.map +1 -1
  6. package/lib/AWS/AuthProvider.js +143 -134
  7. package/lib/AWS/AuthProvider.js.map +1 -1
  8. package/lib/AWS/Bootstrap.d.ts +2 -2
  9. package/lib/AWS/Bootstrap.d.ts.map +1 -1
  10. package/lib/AWS/EC2/hosted.d.ts +1 -1
  11. package/lib/AWS/Environment.d.ts +25 -3
  12. package/lib/AWS/Environment.d.ts.map +1 -1
  13. package/lib/AWS/Environment.js +47 -3
  14. package/lib/AWS/Environment.js.map +1 -1
  15. package/lib/AWS/IAM/OpenIDConnectProvider.d.ts +14 -6
  16. package/lib/AWS/IAM/OpenIDConnectProvider.d.ts.map +1 -1
  17. package/lib/AWS/IAM/OpenIDConnectProvider.js +6 -3
  18. package/lib/AWS/IAM/OpenIDConnectProvider.js.map +1 -1
  19. package/lib/AWS/IAM/Policy.d.ts +1 -1
  20. package/lib/AWS/IAM/Policy.d.ts.map +1 -1
  21. package/lib/AWS/IAM/Policy.js.map +1 -1
  22. package/lib/AWS/Lambda/BucketEventSource.d.ts +1 -1
  23. package/lib/AWS/Lambda/BucketEventSource.d.ts.map +1 -1
  24. package/lib/AWS/Lambda/EventBridgeEventSource.d.ts +1 -1
  25. package/lib/AWS/Lambda/EventBridgeEventSource.d.ts.map +1 -1
  26. package/lib/AWS/Lambda/QueueEventSource.d.ts +1 -1
  27. package/lib/AWS/Lambda/QueueEventSource.d.ts.map +1 -1
  28. package/lib/AWS/Lambda/StreamEventSource.d.ts +1 -1
  29. package/lib/AWS/Lambda/StreamEventSource.d.ts.map +1 -1
  30. package/lib/AWS/Lambda/TableEventSource.d.ts +1 -1
  31. package/lib/AWS/Lambda/TableEventSource.d.ts.map +1 -1
  32. package/lib/AWS/Lambda/TopicEventSource.d.ts +1 -1
  33. package/lib/AWS/Lambda/TopicEventSource.d.ts.map +1 -1
  34. package/lib/AWS/Providers.d.ts +1 -1
  35. package/lib/AWS/Providers.d.ts.map +1 -1
  36. package/lib/AWS/Providers.js +2 -1
  37. package/lib/AWS/Providers.js.map +1 -1
  38. package/lib/Auth/Credentials.d.ts +21 -6
  39. package/lib/Auth/Credentials.d.ts.map +1 -1
  40. package/lib/Auth/Credentials.js +30 -31
  41. package/lib/Auth/Credentials.js.map +1 -1
  42. package/lib/Auth/Profile.d.ts +31 -34
  43. package/lib/Auth/Profile.d.ts.map +1 -1
  44. package/lib/Auth/Profile.js +46 -31
  45. package/lib/Auth/Profile.js.map +1 -1
  46. package/lib/Axiom/AuthProvider.d.ts +2 -1
  47. package/lib/Axiom/AuthProvider.d.ts.map +1 -1
  48. package/lib/Axiom/AuthProvider.js +149 -143
  49. package/lib/Axiom/AuthProvider.js.map +1 -1
  50. package/lib/Axiom/Credentials.d.ts +2 -1
  51. package/lib/Axiom/Credentials.d.ts.map +1 -1
  52. package/lib/Axiom/Credentials.js +4 -4
  53. package/lib/Axiom/Credentials.js.map +1 -1
  54. package/lib/Axiom/Providers.d.ts +1 -1
  55. package/lib/Axiom/Providers.d.ts.map +1 -1
  56. package/lib/Axiom/Providers.js +3 -1
  57. package/lib/Axiom/Providers.js.map +1 -1
  58. package/lib/Cli/LoggingCli.d.ts.map +1 -1
  59. package/lib/Cli/LoggingCli.js +105 -7
  60. package/lib/Cli/LoggingCli.js.map +1 -1
  61. package/lib/Cli/checkVersion.d.ts +13 -0
  62. package/lib/Cli/checkVersion.d.ts.map +1 -0
  63. package/lib/Cli/checkVersion.js +47 -0
  64. package/lib/Cli/checkVersion.js.map +1 -0
  65. package/lib/Cli/commands/_shared.d.ts +2 -2
  66. package/lib/Cli/commands/_shared.d.ts.map +1 -1
  67. package/lib/Cli/commands/_shared.js +3 -3
  68. package/lib/Cli/commands/_shared.js.map +1 -1
  69. package/lib/Cli/commands/aws.d.ts +6 -0
  70. package/lib/Cli/commands/aws.d.ts.map +1 -0
  71. package/lib/Cli/commands/aws.js +63 -0
  72. package/lib/Cli/commands/aws.js.map +1 -0
  73. package/lib/Cli/commands/cloudflare.d.ts +17 -0
  74. package/lib/Cli/commands/cloudflare.d.ts.map +1 -0
  75. package/lib/Cli/commands/cloudflare.js +111 -0
  76. package/lib/Cli/commands/cloudflare.js.map +1 -0
  77. package/lib/Cli/commands/deploy.d.ts +6 -5
  78. package/lib/Cli/commands/deploy.d.ts.map +1 -1
  79. package/lib/Cli/commands/deploy.js +10 -10
  80. package/lib/Cli/commands/deploy.js.map +1 -1
  81. package/lib/Cli/commands/dev.d.ts.map +1 -1
  82. package/lib/Cli/commands/dev.js +16 -16
  83. package/lib/Cli/commands/dev.js.map +1 -1
  84. package/lib/Cli/commands/login.d.ts +2 -1
  85. package/lib/Cli/commands/login.d.ts.map +1 -1
  86. package/lib/Cli/commands/login.js +9 -8
  87. package/lib/Cli/commands/login.js.map +1 -1
  88. package/lib/Cli/commands/logs.d.ts +1 -1
  89. package/lib/Cli/commands/logs.d.ts.map +1 -1
  90. package/lib/Cli/commands/logs.js +7 -7
  91. package/lib/Cli/commands/logs.js.map +1 -1
  92. package/lib/Cli/commands/profile.d.ts +3 -1
  93. package/lib/Cli/commands/profile.d.ts.map +1 -1
  94. package/lib/Cli/commands/profile.js +14 -11
  95. package/lib/Cli/commands/profile.js.map +1 -1
  96. package/lib/Cli/commands/state.d.ts +1 -1
  97. package/lib/Cli/commands/state.d.ts.map +1 -1
  98. package/lib/Cli/commands/state.js +8 -8
  99. package/lib/Cli/commands/state.js.map +1 -1
  100. package/lib/Cli/commands/tail.d.ts +1 -1
  101. package/lib/Cli/commands/tail.d.ts.map +1 -1
  102. package/lib/Cli/commands/tail.js +7 -7
  103. package/lib/Cli/commands/tail.js.map +1 -1
  104. package/lib/Cli/exec.d.ts.map +1 -1
  105. package/lib/Cli/exec.js +5 -3
  106. package/lib/Cli/exec.js.map +1 -1
  107. package/lib/Cli/main.d.ts.map +1 -1
  108. package/lib/Cli/main.js +17 -5
  109. package/lib/Cli/main.js.map +1 -1
  110. package/lib/Cli/selectCli.d.ts +12 -0
  111. package/lib/Cli/selectCli.d.ts.map +1 -0
  112. package/lib/Cli/selectCli.js +32 -0
  113. package/lib/Cli/selectCli.js.map +1 -0
  114. package/lib/Cloudflare/Auth/AuthProvider.d.ts +2 -1
  115. package/lib/Cloudflare/Auth/AuthProvider.d.ts.map +1 -1
  116. package/lib/Cloudflare/Auth/AuthProvider.js +235 -214
  117. package/lib/Cloudflare/Auth/AuthProvider.js.map +1 -1
  118. package/lib/Cloudflare/CloudflareEnvironment.d.ts +2 -1
  119. package/lib/Cloudflare/CloudflareEnvironment.d.ts.map +1 -1
  120. package/lib/Cloudflare/CloudflareEnvironment.js +3 -2
  121. package/lib/Cloudflare/CloudflareEnvironment.js.map +1 -1
  122. package/lib/Cloudflare/Credentials.d.ts +2 -1
  123. package/lib/Cloudflare/Credentials.d.ts.map +1 -1
  124. package/lib/Cloudflare/Credentials.js +4 -4
  125. package/lib/Cloudflare/Credentials.js.map +1 -1
  126. package/lib/Cloudflare/D1/D1Clone.d.ts +2 -1
  127. package/lib/Cloudflare/D1/D1Clone.d.ts.map +1 -1
  128. package/lib/Cloudflare/D1/D1Database.d.ts +2 -1
  129. package/lib/Cloudflare/D1/D1Database.d.ts.map +1 -1
  130. package/lib/Cloudflare/D1/D1Import.d.ts +3 -1
  131. package/lib/Cloudflare/D1/D1Import.d.ts.map +1 -1
  132. package/lib/Cloudflare/Local/Sidecar.d.ts +11 -4
  133. package/lib/Cloudflare/Local/Sidecar.d.ts.map +1 -1
  134. package/lib/Cloudflare/Local/Sidecar.js +8 -6
  135. package/lib/Cloudflare/Local/Sidecar.js.map +1 -1
  136. package/lib/Cloudflare/Local/SidecarHandlers.d.ts.map +1 -1
  137. package/lib/Cloudflare/Local/SidecarHandlers.js +1 -5
  138. package/lib/Cloudflare/Local/SidecarHandlers.js.map +1 -1
  139. package/lib/Cloudflare/Local/SidecarServer.js +5 -2
  140. package/lib/Cloudflare/Local/SidecarServer.js.map +1 -1
  141. package/lib/Cloudflare/Logs.d.ts +5 -0
  142. package/lib/Cloudflare/Logs.d.ts.map +1 -1
  143. package/lib/Cloudflare/Logs.js +70 -1
  144. package/lib/Cloudflare/Logs.js.map +1 -1
  145. package/lib/Cloudflare/Providers.d.ts +1 -1
  146. package/lib/Cloudflare/Providers.d.ts.map +1 -1
  147. package/lib/Cloudflare/Providers.js +4 -1
  148. package/lib/Cloudflare/Providers.js.map +1 -1
  149. package/lib/Cloudflare/Queue/Queue.d.ts +1 -1
  150. package/lib/Cloudflare/Queue/Queue.js +1 -1
  151. package/lib/Cloudflare/Queue/QueueConsumer.d.ts +6 -2
  152. package/lib/Cloudflare/Queue/QueueConsumer.d.ts.map +1 -1
  153. package/lib/Cloudflare/Queue/QueueConsumer.js +194 -53
  154. package/lib/Cloudflare/Queue/QueueConsumer.js.map +1 -1
  155. package/lib/Cloudflare/Queue/QueueEventSource.d.ts +106 -0
  156. package/lib/Cloudflare/Queue/QueueEventSource.d.ts.map +1 -0
  157. package/lib/Cloudflare/Queue/QueueEventSource.js +145 -0
  158. package/lib/Cloudflare/Queue/QueueEventSource.js.map +1 -0
  159. package/lib/Cloudflare/Queue/index.d.ts +1 -0
  160. package/lib/Cloudflare/Queue/index.d.ts.map +1 -1
  161. package/lib/Cloudflare/Queue/index.js +1 -0
  162. package/lib/Cloudflare/Queue/index.js.map +1 -1
  163. package/lib/Cloudflare/R2/R2Bucket.d.ts +94 -0
  164. package/lib/Cloudflare/R2/R2Bucket.d.ts.map +1 -1
  165. package/lib/Cloudflare/R2/R2Bucket.js +186 -2
  166. package/lib/Cloudflare/R2/R2Bucket.js.map +1 -1
  167. package/lib/Cloudflare/StateStore/State.d.ts +4 -3
  168. package/lib/Cloudflare/StateStore/State.d.ts.map +1 -1
  169. package/lib/Cloudflare/StateStore/State.js +16 -8
  170. package/lib/Cloudflare/StateStore/State.js.map +1 -1
  171. package/lib/Cloudflare/VpcService/VpcServiceRef.d.ts +1 -1
  172. package/lib/Cloudflare/VpcService/VpcServiceRef.d.ts.map +1 -1
  173. package/lib/Cloudflare/Website/StaticSite.d.ts.map +1 -1
  174. package/lib/Cloudflare/Website/StaticSite.js +10 -1
  175. package/lib/Cloudflare/Website/StaticSite.js.map +1 -1
  176. package/lib/Cloudflare/Workers/Assets.d.ts +1 -1
  177. package/lib/Cloudflare/Workers/Assets.d.ts.map +1 -1
  178. package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
  179. package/lib/Cloudflare/Workers/LocalWorkerProvider.js +11 -1
  180. package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
  181. package/lib/Cloudflare/Workers/Worker.d.ts +9 -7
  182. package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
  183. package/lib/Cloudflare/Workers/Worker.js +62 -142
  184. package/lib/Cloudflare/Workers/Worker.js.map +1 -1
  185. package/lib/Cloudflare/Workers/WorkerBundle.d.ts +2 -0
  186. package/lib/Cloudflare/Workers/WorkerBundle.d.ts.map +1 -1
  187. package/lib/Cloudflare/Workers/WorkerBundle.js +21 -7
  188. package/lib/Cloudflare/Workers/WorkerBundle.js.map +1 -1
  189. package/lib/Cloudflare/Zone.d.ts +14 -0
  190. package/lib/Cloudflare/Zone.d.ts.map +1 -0
  191. package/lib/Cloudflare/Zone.js +44 -0
  192. package/lib/Cloudflare/Zone.js.map +1 -0
  193. package/lib/Drizzle/Schema.d.ts.map +1 -1
  194. package/lib/Drizzle/Schema.js +20 -5
  195. package/lib/Drizzle/Schema.js.map +1 -1
  196. package/lib/GitHub/AuthProvider.d.ts +3 -1
  197. package/lib/GitHub/AuthProvider.d.ts.map +1 -1
  198. package/lib/GitHub/AuthProvider.js +114 -108
  199. package/lib/GitHub/AuthProvider.js.map +1 -1
  200. package/lib/GitHub/Credentials.d.ts +2 -1
  201. package/lib/GitHub/Credentials.d.ts.map +1 -1
  202. package/lib/GitHub/Credentials.js +4 -4
  203. package/lib/GitHub/Credentials.js.map +1 -1
  204. package/lib/GitHub/Providers.d.ts +1 -1
  205. package/lib/GitHub/Providers.d.ts.map +1 -1
  206. package/lib/GitHub/Providers.js +3 -1
  207. package/lib/GitHub/Providers.js.map +1 -1
  208. package/lib/GitHub/Secrets.d.ts.map +1 -1
  209. package/lib/GitHub/Secrets.js +14 -1
  210. package/lib/GitHub/Secrets.js.map +1 -1
  211. package/lib/GitHub/Variables.d.ts +40 -0
  212. package/lib/GitHub/Variables.d.ts.map +1 -0
  213. package/lib/GitHub/Variables.js +28 -0
  214. package/lib/GitHub/Variables.js.map +1 -0
  215. package/lib/GitHub/index.d.ts +1 -0
  216. package/lib/GitHub/index.d.ts.map +1 -1
  217. package/lib/GitHub/index.js +1 -0
  218. package/lib/GitHub/index.js.map +1 -1
  219. package/lib/Neon/AuthProvider.d.ts +3 -1
  220. package/lib/Neon/AuthProvider.d.ts.map +1 -1
  221. package/lib/Neon/AuthProvider.js +87 -80
  222. package/lib/Neon/AuthProvider.js.map +1 -1
  223. package/lib/Neon/Credentials.d.ts +2 -1
  224. package/lib/Neon/Credentials.d.ts.map +1 -1
  225. package/lib/Neon/Credentials.js +4 -4
  226. package/lib/Neon/Credentials.js.map +1 -1
  227. package/lib/Neon/NeonEnvironment.d.ts +2 -1
  228. package/lib/Neon/NeonEnvironment.d.ts.map +1 -1
  229. package/lib/Neon/NeonEnvironment.js +3 -2
  230. package/lib/Neon/NeonEnvironment.js.map +1 -1
  231. package/lib/Neon/Project.d.ts +16 -0
  232. package/lib/Neon/Project.d.ts.map +1 -1
  233. package/lib/Neon/Project.js +25 -0
  234. package/lib/Neon/Project.js.map +1 -1
  235. package/lib/Neon/Providers.d.ts +1 -1
  236. package/lib/Neon/Providers.d.ts.map +1 -1
  237. package/lib/Neon/Providers.js +3 -1
  238. package/lib/Neon/Providers.js.map +1 -1
  239. package/lib/Neon/api.d.ts +1 -0
  240. package/lib/Neon/api.d.ts.map +1 -1
  241. package/lib/Neon/api.js +1 -0
  242. package/lib/Neon/api.js.map +1 -1
  243. package/lib/Sidecar/RpcClient.d.ts.map +1 -1
  244. package/lib/Sidecar/RpcClient.js +8 -5
  245. package/lib/Sidecar/RpcClient.js.map +1 -1
  246. package/lib/Sidecar/RpcPaths.d.ts +5 -0
  247. package/lib/Sidecar/RpcPaths.d.ts.map +1 -1
  248. package/lib/Sidecar/RpcPaths.js +10 -1
  249. package/lib/Sidecar/RpcPaths.js.map +1 -1
  250. package/lib/Sidecar/RpcServer.d.ts +24 -4
  251. package/lib/Sidecar/RpcServer.d.ts.map +1 -1
  252. package/lib/Sidecar/RpcServer.js +70 -15
  253. package/lib/Sidecar/RpcServer.js.map +1 -1
  254. package/lib/Sidecar/RpcServerBun.d.ts +4 -0
  255. package/lib/Sidecar/RpcServerBun.d.ts.map +1 -0
  256. package/lib/Sidecar/RpcServerBun.js +28 -0
  257. package/lib/Sidecar/RpcServerBun.js.map +1 -0
  258. package/lib/Sidecar/RpcServerNode.d.ts +4 -0
  259. package/lib/Sidecar/RpcServerNode.d.ts.map +1 -0
  260. package/lib/Sidecar/RpcServerNode.js +39 -0
  261. package/lib/Sidecar/RpcServerNode.js.map +1 -0
  262. package/lib/Sidecar/RpcServices.d.ts +6 -0
  263. package/lib/Sidecar/RpcServices.d.ts.map +1 -0
  264. package/lib/Sidecar/RpcServices.js +29 -0
  265. package/lib/Sidecar/RpcServices.js.map +1 -0
  266. package/lib/Stack.d.ts +5 -3
  267. package/lib/Stack.d.ts.map +1 -1
  268. package/lib/Stack.js +3 -1
  269. package/lib/Stack.js.map +1 -1
  270. package/lib/Test/Core.d.ts.map +1 -1
  271. package/lib/Test/Core.js +5 -4
  272. package/lib/Test/Core.js.map +1 -1
  273. package/lib/Util/PlatformServices.js +1 -1
  274. package/lib/tsconfig.test.tsbuildinfo +1 -1
  275. package/package.json +15 -12
  276. package/src/AWS/AuthProvider.ts +269 -259
  277. package/src/AWS/Environment.ts +57 -3
  278. package/src/AWS/IAM/OpenIDConnectProvider.ts +19 -8
  279. package/src/AWS/IAM/Policy.ts +1 -1
  280. package/src/AWS/Providers.ts +2 -0
  281. package/src/Auth/Credentials.ts +82 -46
  282. package/src/Auth/Profile.ts +123 -69
  283. package/src/Axiom/AuthProvider.ts +263 -255
  284. package/src/Axiom/Credentials.ts +3 -4
  285. package/src/Axiom/Providers.ts +4 -0
  286. package/src/Cli/LoggingCli.ts +127 -11
  287. package/src/Cli/checkVersion.ts +57 -0
  288. package/src/Cli/commands/_shared.ts +4 -4
  289. package/src/Cli/commands/aws.ts +127 -0
  290. package/src/Cli/commands/cloudflare.ts +222 -0
  291. package/src/Cli/commands/deploy.ts +11 -10
  292. package/src/Cli/commands/dev.ts +28 -33
  293. package/src/Cli/commands/login.ts +9 -12
  294. package/src/Cli/commands/logs.ts +8 -8
  295. package/src/Cli/commands/profile.ts +14 -16
  296. package/src/Cli/commands/state.ts +8 -8
  297. package/src/Cli/commands/tail.ts +8 -8
  298. package/src/Cli/exec.ts +7 -3
  299. package/src/Cli/main.ts +20 -5
  300. package/src/Cli/selectCli.ts +33 -0
  301. package/src/Cloudflare/Auth/AuthProvider.ts +445 -430
  302. package/src/Cloudflare/CloudflareEnvironment.ts +3 -2
  303. package/src/Cloudflare/Credentials.ts +3 -4
  304. package/src/Cloudflare/Local/Sidecar.ts +13 -10
  305. package/src/Cloudflare/Local/SidecarHandlers.ts +8 -13
  306. package/src/Cloudflare/Local/SidecarServer.ts +6 -1
  307. package/src/Cloudflare/Logs.ts +115 -1
  308. package/src/Cloudflare/Providers.ts +6 -0
  309. package/src/Cloudflare/Queue/Queue.ts +1 -1
  310. package/src/Cloudflare/Queue/QueueConsumer.ts +262 -60
  311. package/src/Cloudflare/Queue/QueueEventSource.ts +234 -0
  312. package/src/Cloudflare/Queue/index.ts +1 -0
  313. package/src/Cloudflare/R2/R2Bucket.ts +337 -2
  314. package/src/Cloudflare/StateStore/State.ts +25 -16
  315. package/src/Cloudflare/Website/StaticSite.ts +11 -1
  316. package/src/Cloudflare/Workers/LocalWorkerProvider.ts +9 -1
  317. package/src/Cloudflare/Workers/Worker.ts +83 -203
  318. package/src/Cloudflare/Workers/WorkerBundle.ts +38 -12
  319. package/src/Cloudflare/Zone.ts +88 -0
  320. package/src/Drizzle/Schema.ts +21 -5
  321. package/src/GitHub/AuthProvider.ts +221 -217
  322. package/src/GitHub/Credentials.ts +3 -4
  323. package/src/GitHub/Providers.ts +4 -0
  324. package/src/GitHub/Secrets.ts +25 -1
  325. package/src/GitHub/Variables.ts +54 -0
  326. package/src/GitHub/index.ts +1 -0
  327. package/src/Neon/AuthProvider.ts +160 -154
  328. package/src/Neon/Credentials.ts +3 -4
  329. package/src/Neon/NeonEnvironment.ts +3 -2
  330. package/src/Neon/Project.ts +42 -0
  331. package/src/Neon/Providers.ts +4 -0
  332. package/src/Neon/api.ts +2 -0
  333. package/src/Sidecar/RpcClient.ts +8 -7
  334. package/src/Sidecar/RpcPaths.ts +11 -1
  335. package/src/Sidecar/RpcServer.ts +97 -24
  336. package/src/Sidecar/RpcServerBun.ts +41 -0
  337. package/src/Sidecar/RpcServerNode.ts +51 -0
  338. package/src/Sidecar/RpcServices.ts +48 -0
  339. package/src/Stack.ts +8 -0
  340. package/src/Test/Core.ts +10 -4
  341. package/src/Util/PlatformServices.ts +1 -1
  342. package/lib/Cli/commands/bootstrap.d.ts +0 -20
  343. package/lib/Cli/commands/bootstrap.d.ts.map +0 -1
  344. package/lib/Cli/commands/bootstrap.js +0 -107
  345. package/lib/Cli/commands/bootstrap.js.map +0 -1
  346. package/lib/Sidecar/RpcTransport.d.ts +0 -22
  347. package/lib/Sidecar/RpcTransport.d.ts.map +0 -1
  348. package/lib/Sidecar/RpcTransport.js +0 -81
  349. package/lib/Sidecar/RpcTransport.js.map +0 -1
  350. package/lib/Test/TestCli.d.ts +0 -19
  351. package/lib/Test/TestCli.d.ts.map +0 -1
  352. package/lib/Test/TestCli.js +0 -175
  353. package/lib/Test/TestCli.js.map +0 -1
  354. package/src/Cli/commands/bootstrap.ts +0 -216
  355. package/src/Sidecar/RpcTransport.ts +0 -85
  356. package/src/Test/TestCli.ts +0 -221
@@ -3,7 +3,6 @@ import * as CfCredentialsModule from "@distilled.cloud/cloudflare/Credentials";
3
3
  import * as Console from "effect/Console";
4
4
  import * as Duration from "effect/Duration";
5
5
  import * as Effect from "effect/Effect";
6
- import * as FileSystem from "effect/FileSystem";
7
6
  import * as Layer from "effect/Layer";
8
7
  import * as Match from "effect/Match";
9
8
  import * as Redacted from "effect/Redacted";
@@ -14,12 +13,7 @@ import {
14
13
  AuthProviderLayer,
15
14
  type ConfigureContext,
16
15
  } from "../../Auth/AuthProvider.ts";
17
- import {
18
- deleteCredentials,
19
- displayRedacted,
20
- readCredentials,
21
- writeCredentials,
22
- } from "../../Auth/Credentials.ts";
16
+ import { CredentialsStore, displayRedacted } from "../../Auth/Credentials.ts";
23
17
  import {
24
18
  getEnv,
25
19
  getEnvRedacted,
@@ -85,390 +79,6 @@ export type CloudflareResolvedCredentials =
85
79
 
86
80
  export const CLOUDFLARE_AUTH_PROVIDER_NAME = "Cloudflare";
87
81
 
88
- /**
89
- * Layer that registers the Cloudflare {@link AuthProvider} into the
90
- * {@link AuthProviders} registry when built. Include this in the Cloudflare
91
- * `providers()` layer so `alchemy login` can discover it.
92
- */
93
- export const CloudflareAuth = AuthProviderLayer<
94
- CloudflareAuthConfig,
95
- CloudflareResolvedCredentials
96
- >()(CLOUDFLARE_AUTH_PROVIDER_NAME, {
97
- configure: (profileName, ctx) => configureCredentials(profileName, ctx),
98
- logout: (profileName, config) => logout(profileName, config),
99
- login: (profileName, config) => login(profileName, config),
100
- prettyPrint: (profileName, config) => prettyPrint(profileName, config),
101
- read: (profileName, config) => resolveCredentials(profileName, config),
102
- });
103
-
104
- const resolveCredentials = (
105
- profileName: string,
106
- config: CloudflareAuthConfig,
107
- ): Effect.Effect<
108
- CloudflareResolvedCredentials,
109
- AuthError,
110
- FileSystem.FileSystem
111
- > =>
112
- Match.value(config).pipe(
113
- Match.when(
114
- { method: "env" },
115
- Effect.fnUntraced(function* () {
116
- const accountId = yield* getEnvRequired("CLOUDFLARE_ACCOUNT_ID");
117
- const apiToken = yield* getEnvRedacted("CLOUDFLARE_API_TOKEN");
118
- if (apiToken) {
119
- return {
120
- type: "apiToken" as const,
121
- apiToken,
122
- accountId,
123
- source: { type: "env" as const },
124
- };
125
- }
126
- const apiKey = yield* getEnvRedacted("CLOUDFLARE_API_KEY");
127
- const email = yield* getEnvRedacted("CLOUDFLARE_EMAIL");
128
- if (apiKey && email) {
129
- return {
130
- type: "apiKey" as const,
131
- apiKey,
132
- email,
133
- accountId,
134
- source: { type: "env" as const },
135
- };
136
- }
137
- return yield* new AuthError({
138
- message:
139
- "Cloudflare env credentials not found. Set CLOUDFLARE_API_TOKEN or CLOUDFLARE_API_KEY + CLOUDFLARE_EMAIL.",
140
- });
141
- }),
142
- ),
143
- Match.when({ method: "stored" }, () =>
144
- readCredentials<CloudflareStoredCredentials>(
145
- profileName,
146
- "cf-stored",
147
- ).pipe(
148
- Effect.flatMap((creds) =>
149
- creds == null
150
- ? Effect.fail(
151
- new AuthError({
152
- message:
153
- "Cloudflare stored credentials not found. Run: alchemy-effect login --configure",
154
- }),
155
- )
156
- : Effect.succeed(
157
- Match.value(creds).pipe(
158
- Match.when({ type: "apiToken" }, (c) => ({
159
- type: "apiToken" as const,
160
- apiToken: Redacted.make(c.apiToken),
161
- accountId: c.accountId,
162
- source: { type: "stored" as const },
163
- })),
164
- Match.when({ type: "apiKey" }, (c) => ({
165
- type: "apiKey" as const,
166
- apiKey: Redacted.make(c.apiKey),
167
- email: Redacted.make(c.email),
168
- accountId: c.accountId,
169
- source: { type: "stored" as const },
170
- })),
171
- Match.exhaustive,
172
- ),
173
- ),
174
- ),
175
- ),
176
- ),
177
- Match.when({ method: "oauth" }, (cfg) =>
178
- Effect.gen(function* () {
179
- const creds = yield* readCredentials<OAuthClient.OAuthCredentials>(
180
- profileName,
181
- "cf-oauth",
182
- );
183
- if (creds == null || creds.type !== "oauth") {
184
- return yield* Effect.fail(
185
- new AuthError({
186
- message:
187
- "Cloudflare OAuth credentials not found. Run: alchemy login",
188
- }),
189
- );
190
- }
191
- // Refresh proactively if the token has expired (or is within
192
- // 10s of expiring). Persist the refreshed creds so subsequent
193
- // resolves don't repeat the round-trip.
194
- const fresh =
195
- creds.expires > Date.now() + 10_000
196
- ? creds
197
- : yield* OAuthClient.refresh(creds).pipe(
198
- Effect.tap((refreshed) =>
199
- writeCredentials(profileName, "cf-oauth", refreshed),
200
- ),
201
- Effect.mapError(
202
- (e) =>
203
- new AuthError({
204
- message:
205
- "Cloudflare OAuth refresh failed. Run: alchemy login",
206
- cause: e,
207
- }),
208
- ),
209
- );
210
- return {
211
- type: "oauth" as const,
212
- accessToken: Redacted.make(fresh.access),
213
- expires: fresh.expires,
214
- accountId: cfg.accountId,
215
- source: { type: "oauth" as const },
216
- };
217
- }),
218
- ),
219
- Match.exhaustive,
220
- );
221
-
222
- const logout = (profileName: string, config: CloudflareAuthConfig) =>
223
- Match.value(config).pipe(
224
- Match.when({ method: "env" }, () => Effect.void),
225
- Match.when({ method: "stored" }, () =>
226
- deleteCredentials(profileName, "cf-stored").pipe(
227
- Effect.andThen(Clank.success("Cloudflare: stored credentials removed")),
228
- ),
229
- ),
230
- Match.when({ method: "oauth" }, () =>
231
- readCredentials<OAuthClient.OAuthCredentials>(
232
- profileName,
233
- "cf-oauth",
234
- ).pipe(
235
- Effect.tap((creds) =>
236
- creds?.type === "oauth"
237
- ? OAuthClient.revoke(creds).pipe(
238
- Effect.catchTag("OAuthError", (err) =>
239
- Clank.warn(
240
- `Cloudflare: could not revoke OAuth token: ${err.errorDescription}`,
241
- ),
242
- ),
243
- )
244
- : Effect.void,
245
- ),
246
- Effect.andThen(deleteCredentials(profileName, "cf-oauth")),
247
- Effect.andThen(Clank.success("Cloudflare: OAuth credentials removed.")),
248
- ),
249
- ),
250
- Match.exhaustive,
251
- );
252
-
253
- const login = (profileName: string, config: CloudflareAuthConfig) =>
254
- Match.value(config)
255
- .pipe(
256
- Match.when({ method: "env" }, () => Effect.void),
257
- Match.when({ method: "stored" }, () =>
258
- readCredentials<CloudflareStoredCredentials>(
259
- profileName,
260
- "cf-stored",
261
- ).pipe(
262
- Effect.flatMap((creds) =>
263
- creds == null ? loginStored(profileName) : Effect.void,
264
- ),
265
- ),
266
- ),
267
- Match.when({ method: "oauth" }, (c) =>
268
- Effect.gen(function* () {
269
- const creds = yield* readCredentials<OAuthClient.OAuthCredentials>(
270
- profileName,
271
- "cf-oauth",
272
- );
273
-
274
- if (creds?.type === "oauth") {
275
- yield* Clank.info("Cloudflare: refreshing OAuth credentials...");
276
- yield* OAuthClient.refresh(creds).pipe(
277
- Effect.flatMap((refreshed) =>
278
- writeCredentials(profileName, "cf-oauth", refreshed).pipe(
279
- Effect.andThen(
280
- Clank.success("Cloudflare: OAuth credentials refreshed."),
281
- ),
282
- ),
283
- ),
284
- Effect.catchTag("OAuthError", () =>
285
- oauthLogin(profileName, c.scopes).pipe(Effect.asVoid),
286
- ),
287
- );
288
- return;
289
- }
290
-
291
- yield* oauthLogin(profileName, c.scopes);
292
- }),
293
- ),
294
- Match.exhaustive,
295
- )
296
- .pipe(
297
- Effect.mapError(
298
- (e) => new AuthError({ message: "login failed", cause: e }),
299
- ),
300
- );
301
-
302
- const configureCredentials = (profileName: string, ctx: ConfigureContext) =>
303
- Effect.gen(function* () {
304
- if (ctx.ci) {
305
- return { method: "env" as const };
306
- }
307
- return yield* configureInteractive(profileName);
308
- }).pipe(
309
- Effect.mapError(
310
- (e) =>
311
- new AuthError({
312
- message: "failed to configure credentials",
313
- cause: e,
314
- }),
315
- ),
316
- );
317
-
318
- const configureInteractive = (profileName: string) =>
319
- Clank.select({
320
- message: "Cloudflare authentication method",
321
- options,
322
- }).pipe(
323
- Effect.flatMap((method) =>
324
- Match.value(method).pipe(
325
- Match.when("env", () => Effect.succeed({ method: "env" as const })),
326
- Match.when("oauth", () => configureOAuth(profileName)),
327
- Match.when("stored", () => loginStored(profileName)),
328
- Match.exhaustive,
329
- ),
330
- ),
331
- );
332
-
333
- const configureOAuth = Effect.fnUntraced(function* (profileName: string) {
334
- const scopes = yield* promptOAuthScopes();
335
-
336
- const oauthCreds = yield* oauthLogin(profileName, scopes);
337
-
338
- const accountId = yield* selectAccount(oauthCreds.access).pipe(
339
- Effect.mapError(
340
- (e) =>
341
- new AuthError({
342
- message: "Cloudflare: could not list accounts",
343
- cause: e,
344
- }),
345
- ),
346
- );
347
-
348
- return {
349
- method: "oauth" as const,
350
- scopes,
351
- accountId,
352
- };
353
- });
354
-
355
- const loginStored = Effect.fnUntraced(function* (profileName: string) {
356
- const credentialType = yield* Clank.select({
357
- message: "Cloudflare credential type",
358
- options: [
359
- { value: "apiToken" as const, label: "API Token", hint: "recommended" },
360
- { value: "apiKey" as const, label: "API Key + Email" },
361
- ],
362
- }).pipe(retryOnce);
363
-
364
- return yield* Match.value(credentialType).pipe(
365
- Match.when("apiToken", () =>
366
- Effect.gen(function* () {
367
- const apiToken = yield* Clank.password({
368
- message: "Cloudflare API Token",
369
- validate: (v) => (v.length === 0 ? "Required" : undefined),
370
- }).pipe(retryOnce);
371
- const accountId = yield* promptAccountId();
372
-
373
- yield* writeCredentials<CloudflareStoredCredentials>(
374
- profileName,
375
- "cf-stored",
376
- { type: "apiToken", apiToken, accountId },
377
- );
378
- yield* Clank.success("Cloudflare: credentials saved.");
379
- return {
380
- method: "stored" as const,
381
- credentialType: "apiToken" as const,
382
- };
383
- }),
384
- ),
385
- Match.when("apiKey", () =>
386
- Effect.gen(function* () {
387
- const apiKey = yield* Clank.text({
388
- message: "Cloudflare API Key",
389
- validate: (v) => (v.length === 0 ? "Required" : undefined),
390
- }).pipe(retryOnce);
391
-
392
- const email = yield* Clank.text({
393
- message: "Cloudflare Email",
394
- validate: (v) => (v.length === 0 ? "Required" : undefined),
395
- }).pipe(retryOnce);
396
- const accountId = yield* promptAccountId();
397
-
398
- yield* writeCredentials<CloudflareStoredCredentials>(
399
- profileName,
400
- "cf-stored",
401
- { type: "apiKey", apiKey, email, accountId },
402
- );
403
- yield* Clank.success("Cloudflare: credentials saved.");
404
- return {
405
- method: "stored" as const,
406
- credentialType: "apiKey" as const,
407
- };
408
- }),
409
- ),
410
- Match.exhaustive,
411
- );
412
- });
413
-
414
- const oauthLogin = (profileName: string, scopes: string[]) =>
415
- Effect.gen(function* () {
416
- const authorization = OAuthClient.authorize([...scopes, "offline_access"]);
417
-
418
- yield* Clank.info("Cloudflare: opening browser for OAuth login...");
419
- yield* Clank.info(authorization.url);
420
- yield* Clank.openUrl(authorization.url).pipe(
421
- Effect.catch(() =>
422
- Clank.warn(
423
- "Cloudflare: could not open browser automatically. Please open the URL above manually.",
424
- ),
425
- ),
426
- );
427
- yield* Clank.info(
428
- "Cloudflare: waiting for authorization (up to 5 minutes)...",
429
- );
430
-
431
- const credentials = yield* OAuthClient.callback(authorization);
432
- yield* writeCredentials(profileName, "cf-oauth", credentials);
433
- yield* Clank.success("Cloudflare: OAuth credentials saved.");
434
- return credentials;
435
- });
436
-
437
- const promptAccountId = () =>
438
- getEnv("CLOUDFLARE_ACCOUNT_ID").pipe(
439
- Effect.flatMap((envAccountId) =>
440
- Clank.text({
441
- message: "Cloudflare Account ID (Enter to skip)",
442
- placeholder: envAccountId ?? "",
443
- defaultValue: envAccountId ?? "",
444
- }).pipe(retryOnce),
445
- ),
446
- );
447
-
448
- const promptOAuthScopes = () =>
449
- Clank.confirm({
450
- message: "Customize OAuth scopes? (default covers typical use cases)",
451
- initialValue: false,
452
- }).pipe(
453
- retryOnce,
454
- Effect.flatMap((customize) => {
455
- if (!customize) return Effect.succeed([...DEFAULT_SCOPES]);
456
- return Clank.multiselect({
457
- message: "Select OAuth scopes",
458
- initialValues: DEFAULT_SCOPES as string[],
459
- options: Object.entries(ALL_SCOPES).map(([value, hint]) => ({
460
- value: value as string,
461
- label: value,
462
- hint,
463
- })),
464
- required: true,
465
- }).pipe(
466
- Effect.map((s) => s as string[]),
467
- retryOnce,
468
- );
469
- }),
470
- );
471
-
472
82
  const withOAuthCredentials = <A, E>(
473
83
  accessToken: string,
474
84
  effect: Effect.Effect<
@@ -516,49 +126,452 @@ const selectAccount = (accessToken: string) =>
516
126
  }).pipe(retryOnce);
517
127
  }).pipe((e) => withOAuthCredentials(accessToken, e));
518
128
 
519
- const prettyPrint = (profileName: string, config: CloudflareAuthConfig) =>
520
- resolveCredentials(profileName, config).pipe(
521
- Effect.tap((creds) => {
522
- const sourceStr = creds.source.details
523
- ? `${creds.source.type} - ${creds.source.details}`
524
- : creds.source.type;
525
- return Match.value(creds).pipe(
526
- Match.when({ type: "apiToken" }, (c) =>
527
- Effect.all([
528
- Console.log(` apiToken: ${displayRedacted(c.apiToken, 9)}`),
529
- Console.log(` accountId: ${c.accountId}`),
530
- Console.log(` source: ${sourceStr}`),
531
- ]),
129
+ const promptAccountId = () =>
130
+ getEnv("CLOUDFLARE_ACCOUNT_ID").pipe(
131
+ Effect.flatMap((envAccountId) =>
132
+ Clank.text({
133
+ message: "Cloudflare Account ID (Enter to skip)",
134
+ placeholder: envAccountId ?? "",
135
+ defaultValue: envAccountId ?? "",
136
+ }).pipe(retryOnce),
137
+ ),
138
+ );
139
+
140
+ const promptOAuthScopes = () =>
141
+ Clank.confirm({
142
+ message: "Customize OAuth scopes? (default covers typical use cases)",
143
+ initialValue: false,
144
+ }).pipe(
145
+ retryOnce,
146
+ Effect.flatMap((customize) => {
147
+ if (!customize) return Effect.succeed([...DEFAULT_SCOPES]);
148
+ return Clank.multiselect({
149
+ message: "Select OAuth scopes",
150
+ initialValues: DEFAULT_SCOPES as string[],
151
+ options: Object.entries(ALL_SCOPES).map(([value, hint]) => ({
152
+ value: value as string,
153
+ label: value,
154
+ hint,
155
+ })),
156
+ required: true,
157
+ }).pipe(
158
+ Effect.map((s) => s as string[]),
159
+ retryOnce,
160
+ );
161
+ }),
162
+ );
163
+
164
+ /**
165
+ * Layer that registers the Cloudflare {@link AuthProvider} into the
166
+ * {@link AuthProviders} registry when built. Include this in the Cloudflare
167
+ * `providers()` layer so `alchemy login` can discover it.
168
+ */
169
+ export const CloudflareAuth = AuthProviderLayer<
170
+ CloudflareAuthConfig,
171
+ CloudflareResolvedCredentials
172
+ >()(
173
+ CLOUDFLARE_AUTH_PROVIDER_NAME,
174
+ Effect.gen(function* () {
175
+ const store = yield* CredentialsStore;
176
+
177
+ const oauthLogin = (profileName: string, scopes: string[]) =>
178
+ Effect.gen(function* () {
179
+ const authorization = OAuthClient.authorize([
180
+ ...scopes,
181
+ "offline_access",
182
+ ]);
183
+
184
+ yield* Clank.info("Cloudflare: opening browser for OAuth login...");
185
+ yield* Clank.info(authorization.url);
186
+ yield* Clank.openUrl(authorization.url).pipe(
187
+ Effect.catch(() =>
188
+ Clank.warn(
189
+ "Cloudflare: could not open browser automatically. Please open the URL above manually.",
190
+ ),
191
+ ),
192
+ );
193
+ yield* Clank.info(
194
+ "Cloudflare: waiting for authorization (up to 5 minutes)...",
195
+ );
196
+
197
+ const credentials = yield* OAuthClient.callback(authorization);
198
+ yield* store.write(profileName, "cf-oauth", credentials);
199
+ yield* Clank.success("Cloudflare: OAuth credentials saved.");
200
+ return credentials;
201
+ });
202
+
203
+ const loginStored = Effect.fnUntraced(function* (profileName: string) {
204
+ const credentialType = yield* Clank.select({
205
+ message: "Cloudflare credential type",
206
+ options: [
207
+ {
208
+ value: "apiToken" as const,
209
+ label: "API Token",
210
+ hint: "recommended",
211
+ },
212
+ { value: "apiKey" as const, label: "API Key + Email" },
213
+ ],
214
+ }).pipe(retryOnce);
215
+
216
+ return yield* Match.value(credentialType).pipe(
217
+ Match.when("apiToken", () =>
218
+ Effect.gen(function* () {
219
+ const apiToken = yield* Clank.password({
220
+ message: "Cloudflare API Token",
221
+ validate: (v) => (v.length === 0 ? "Required" : undefined),
222
+ }).pipe(retryOnce);
223
+ const accountId = yield* promptAccountId();
224
+
225
+ yield* store.write<CloudflareStoredCredentials>(
226
+ profileName,
227
+ "cf-stored",
228
+ { type: "apiToken", apiToken, accountId },
229
+ );
230
+ yield* Clank.success("Cloudflare: credentials saved.");
231
+ return {
232
+ method: "stored" as const,
233
+ credentialType: "apiToken" as const,
234
+ };
235
+ }),
532
236
  ),
533
- Match.when({ type: "apiKey" }, (c) =>
534
- Effect.all([
535
- Console.log(` apiKey: ${displayRedacted(c.apiKey)}`),
536
- Console.log(` email: ${displayRedacted(c.email)}`),
537
- Console.log(` accountId: ${c.accountId}`),
538
- Console.log(` source: ${sourceStr}`),
539
- ]),
237
+ Match.when("apiKey", () =>
238
+ Effect.gen(function* () {
239
+ const apiKey = yield* Clank.text({
240
+ message: "Cloudflare API Key",
241
+ validate: (v) => (v.length === 0 ? "Required" : undefined),
242
+ }).pipe(retryOnce);
243
+
244
+ const email = yield* Clank.text({
245
+ message: "Cloudflare Email",
246
+ validate: (v) => (v.length === 0 ? "Required" : undefined),
247
+ }).pipe(retryOnce);
248
+ const accountId = yield* promptAccountId();
249
+
250
+ yield* store.write<CloudflareStoredCredentials>(
251
+ profileName,
252
+ "cf-stored",
253
+ { type: "apiKey", apiKey, email, accountId },
254
+ );
255
+ yield* Clank.success("Cloudflare: credentials saved.");
256
+ return {
257
+ method: "stored" as const,
258
+ credentialType: "apiKey" as const,
259
+ };
260
+ }),
540
261
  ),
541
- Match.when({ type: "oauth" }, (c) => {
542
- const remainingMs = c.expires - Date.now();
543
- const expiresAt = new Date(c.expires).toISOString();
544
- const expiresStr =
545
- remainingMs <= 0
546
- ? `expired (${expiresAt})`
547
- : `in ${Duration.format(Duration.millis(remainingMs))} (${expiresAt})`;
548
- return Effect.all([
549
- Console.log(` accessToken: ${displayRedacted(c.accessToken)}`),
550
- Console.log(` expires: ${expiresStr}`),
551
- Console.log(` accountId: ${c.accountId}`),
552
- Console.log(` source: ${sourceStr}`),
553
- ]);
554
- }),
555
262
  Match.exhaustive,
556
263
  );
557
- }),
558
- Effect.catch((e) =>
559
- Console.error(` Failed to retrieve credentials: ${e}`),
560
- ),
561
- );
264
+ });
265
+
266
+ const configureOAuth = Effect.fnUntraced(function* (profileName: string) {
267
+ const scopes = yield* promptOAuthScopes();
268
+
269
+ const oauthCreds = yield* oauthLogin(profileName, scopes);
270
+
271
+ const accountId = yield* selectAccount(oauthCreds.access).pipe(
272
+ Effect.mapError(
273
+ (e) =>
274
+ new AuthError({
275
+ message: "Cloudflare: could not list accounts",
276
+ cause: e,
277
+ }),
278
+ ),
279
+ );
280
+
281
+ return {
282
+ method: "oauth" as const,
283
+ scopes,
284
+ accountId,
285
+ };
286
+ });
287
+
288
+ const configureInteractive = (profileName: string) =>
289
+ Clank.select({
290
+ message: "Cloudflare authentication method",
291
+ options,
292
+ }).pipe(
293
+ Effect.flatMap((method) =>
294
+ Match.value(method).pipe(
295
+ Match.when("env", () => Effect.succeed({ method: "env" as const })),
296
+ Match.when("oauth", () => configureOAuth(profileName)),
297
+ Match.when("stored", () => loginStored(profileName)),
298
+ Match.exhaustive,
299
+ ),
300
+ ),
301
+ );
302
+
303
+ const configureCredentials = (profileName: string, ctx: ConfigureContext) =>
304
+ Effect.gen(function* () {
305
+ if (ctx.ci) {
306
+ return { method: "env" as const };
307
+ }
308
+ return yield* configureInteractive(profileName);
309
+ }).pipe(
310
+ Effect.mapError(
311
+ (e) =>
312
+ new AuthError({
313
+ message: "failed to configure credentials",
314
+ cause: e,
315
+ }),
316
+ ),
317
+ );
318
+
319
+ const resolveCredentials = (
320
+ profileName: string,
321
+ config: CloudflareAuthConfig,
322
+ ): Effect.Effect<CloudflareResolvedCredentials, AuthError> =>
323
+ Match.value(config).pipe(
324
+ Match.when(
325
+ { method: "env" },
326
+ Effect.fnUntraced(function* () {
327
+ const accountId = yield* getEnvRequired("CLOUDFLARE_ACCOUNT_ID");
328
+ const apiToken = yield* getEnvRedacted("CLOUDFLARE_API_TOKEN");
329
+ if (apiToken) {
330
+ return {
331
+ type: "apiToken" as const,
332
+ apiToken,
333
+ accountId,
334
+ source: { type: "env" as const },
335
+ };
336
+ }
337
+ const apiKey = yield* getEnvRedacted("CLOUDFLARE_API_KEY");
338
+ const email = yield* getEnvRedacted("CLOUDFLARE_EMAIL");
339
+ if (apiKey && email) {
340
+ return {
341
+ type: "apiKey" as const,
342
+ apiKey,
343
+ email,
344
+ accountId,
345
+ source: { type: "env" as const },
346
+ };
347
+ }
348
+ return yield* new AuthError({
349
+ message:
350
+ "Cloudflare env credentials not found. Set CLOUDFLARE_API_TOKEN or CLOUDFLARE_API_KEY + CLOUDFLARE_EMAIL.",
351
+ });
352
+ }),
353
+ ),
354
+ Match.when({ method: "stored" }, () =>
355
+ store
356
+ .read<CloudflareStoredCredentials>(profileName, "cf-stored")
357
+ .pipe(
358
+ Effect.flatMap((creds) =>
359
+ creds == null
360
+ ? Effect.fail(
361
+ new AuthError({
362
+ message:
363
+ "Cloudflare stored credentials not found. Run: alchemy-effect login --configure",
364
+ }),
365
+ )
366
+ : Effect.succeed(
367
+ Match.value(creds).pipe(
368
+ Match.when({ type: "apiToken" }, (c) => ({
369
+ type: "apiToken" as const,
370
+ apiToken: Redacted.make(c.apiToken),
371
+ accountId: c.accountId,
372
+ source: { type: "stored" as const },
373
+ })),
374
+ Match.when({ type: "apiKey" }, (c) => ({
375
+ type: "apiKey" as const,
376
+ apiKey: Redacted.make(c.apiKey),
377
+ email: Redacted.make(c.email),
378
+ accountId: c.accountId,
379
+ source: { type: "stored" as const },
380
+ })),
381
+ Match.exhaustive,
382
+ ),
383
+ ),
384
+ ),
385
+ ),
386
+ ),
387
+ Match.when({ method: "oauth" }, (cfg) =>
388
+ Effect.gen(function* () {
389
+ const creds = yield* store.read<OAuthClient.OAuthCredentials>(
390
+ profileName,
391
+ "cf-oauth",
392
+ );
393
+ if (creds == null || creds.type !== "oauth") {
394
+ return yield* Effect.fail(
395
+ new AuthError({
396
+ message:
397
+ "Cloudflare OAuth credentials not found. Run: alchemy login",
398
+ }),
399
+ );
400
+ }
401
+ // Refresh proactively if the token has expired (or is within
402
+ // 10s of expiring). Persist the refreshed creds so subsequent
403
+ // resolves don't repeat the round-trip.
404
+ const fresh =
405
+ creds.expires > Date.now() + 10_000
406
+ ? creds
407
+ : yield* OAuthClient.refresh(creds).pipe(
408
+ Effect.tap((refreshed) =>
409
+ store.write(profileName, "cf-oauth", refreshed),
410
+ ),
411
+ Effect.mapError(
412
+ (e) =>
413
+ new AuthError({
414
+ message:
415
+ "Cloudflare OAuth refresh failed. Run: alchemy login",
416
+ cause: e,
417
+ }),
418
+ ),
419
+ );
420
+ return {
421
+ type: "oauth" as const,
422
+ accessToken: Redacted.make(fresh.access),
423
+ expires: fresh.expires,
424
+ accountId: cfg.accountId,
425
+ source: { type: "oauth" as const },
426
+ };
427
+ }),
428
+ ),
429
+ Match.exhaustive,
430
+ );
431
+
432
+ const logout = (profileName: string, config: CloudflareAuthConfig) =>
433
+ Match.value(config).pipe(
434
+ Match.when({ method: "env" }, () => Effect.void),
435
+ Match.when({ method: "stored" }, () =>
436
+ store
437
+ .delete(profileName, "cf-stored")
438
+ .pipe(
439
+ Effect.andThen(
440
+ Clank.success("Cloudflare: stored credentials removed"),
441
+ ),
442
+ ),
443
+ ),
444
+ Match.when({ method: "oauth" }, () =>
445
+ store
446
+ .read<OAuthClient.OAuthCredentials>(profileName, "cf-oauth")
447
+ .pipe(
448
+ Effect.tap((creds) =>
449
+ creds?.type === "oauth"
450
+ ? OAuthClient.revoke(creds).pipe(
451
+ Effect.catchTag("OAuthError", (err) =>
452
+ Clank.warn(
453
+ `Cloudflare: could not revoke OAuth token: ${err.errorDescription}`,
454
+ ),
455
+ ),
456
+ )
457
+ : Effect.void,
458
+ ),
459
+ Effect.andThen(store.delete(profileName, "cf-oauth")),
460
+ Effect.andThen(
461
+ Clank.success("Cloudflare: OAuth credentials removed."),
462
+ ),
463
+ ),
464
+ ),
465
+ Match.exhaustive,
466
+ );
467
+
468
+ const login = (profileName: string, config: CloudflareAuthConfig) =>
469
+ Match.value(config)
470
+ .pipe(
471
+ Match.when({ method: "env" }, () => Effect.void),
472
+ Match.when({ method: "stored" }, () =>
473
+ store
474
+ .read<CloudflareStoredCredentials>(profileName, "cf-stored")
475
+ .pipe(
476
+ Effect.flatMap((creds) =>
477
+ creds == null ? loginStored(profileName) : Effect.void,
478
+ ),
479
+ ),
480
+ ),
481
+ Match.when({ method: "oauth" }, (c) =>
482
+ Effect.gen(function* () {
483
+ const creds = yield* store.read<OAuthClient.OAuthCredentials>(
484
+ profileName,
485
+ "cf-oauth",
486
+ );
487
+
488
+ if (creds?.type === "oauth") {
489
+ yield* Clank.info(
490
+ "Cloudflare: refreshing OAuth credentials...",
491
+ );
492
+ yield* OAuthClient.refresh(creds).pipe(
493
+ Effect.flatMap((refreshed) =>
494
+ store
495
+ .write(profileName, "cf-oauth", refreshed)
496
+ .pipe(
497
+ Effect.andThen(
498
+ Clank.success(
499
+ "Cloudflare: OAuth credentials refreshed.",
500
+ ),
501
+ ),
502
+ ),
503
+ ),
504
+ Effect.catchTag("OAuthError", () =>
505
+ oauthLogin(profileName, c.scopes).pipe(Effect.asVoid),
506
+ ),
507
+ );
508
+ return;
509
+ }
510
+
511
+ yield* oauthLogin(profileName, c.scopes);
512
+ }),
513
+ ),
514
+ Match.exhaustive,
515
+ )
516
+ .pipe(
517
+ Effect.mapError(
518
+ (e) => new AuthError({ message: "login failed", cause: e }),
519
+ ),
520
+ );
521
+
522
+ const prettyPrint = (profileName: string, config: CloudflareAuthConfig) =>
523
+ resolveCredentials(profileName, config).pipe(
524
+ Effect.tap((creds) => {
525
+ const sourceStr = creds.source.details
526
+ ? `${creds.source.type} - ${creds.source.details}`
527
+ : creds.source.type;
528
+ return Match.value(creds).pipe(
529
+ Match.when({ type: "apiToken" }, (c) =>
530
+ Effect.all([
531
+ Console.log(` apiToken: ${displayRedacted(c.apiToken, 9)}`),
532
+ Console.log(` accountId: ${c.accountId}`),
533
+ Console.log(` source: ${sourceStr}`),
534
+ ]),
535
+ ),
536
+ Match.when({ type: "apiKey" }, (c) =>
537
+ Effect.all([
538
+ Console.log(` apiKey: ${displayRedacted(c.apiKey)}`),
539
+ Console.log(` email: ${displayRedacted(c.email)}`),
540
+ Console.log(` accountId: ${c.accountId}`),
541
+ Console.log(` source: ${sourceStr}`),
542
+ ]),
543
+ ),
544
+ Match.when({ type: "oauth" }, (c) => {
545
+ const remainingMs = c.expires - Date.now();
546
+ const expiresAt = new Date(c.expires).toISOString();
547
+ const expiresStr =
548
+ remainingMs <= 0
549
+ ? `expired (${expiresAt})`
550
+ : `in ${Duration.format(Duration.millis(remainingMs))} (${expiresAt})`;
551
+ return Effect.all([
552
+ Console.log(` accessToken: ${displayRedacted(c.accessToken)}`),
553
+ Console.log(` expires: ${expiresStr}`),
554
+ Console.log(` accountId: ${c.accountId}`),
555
+ Console.log(` source: ${sourceStr}`),
556
+ ]);
557
+ }),
558
+ Match.exhaustive,
559
+ );
560
+ }),
561
+ Effect.catch((e) =>
562
+ Console.error(` Failed to retrieve credentials: ${e}`),
563
+ ),
564
+ );
565
+
566
+ return {
567
+ configure: configureCredentials,
568
+ logout,
569
+ login,
570
+ prettyPrint,
571
+ read: resolveCredentials,
572
+ };
573
+ }),
574
+ );
562
575
 
563
576
  export const ALL_SCOPES = {
564
577
  "access:read":
@@ -680,6 +693,8 @@ export const DEFAULT_SCOPES = [
680
693
  "user:read",
681
694
  "vectorize:write",
682
695
  "workers_kv:write",
696
+ "workers_observability:read",
697
+ "workers_observability_telemetry:write",
683
698
  "workers_routes:write",
684
699
  "workers_scripts:write",
685
700
  "workers_tail:read",