alchemy 2.0.0-beta.34 → 2.0.0-beta.36

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 (390) hide show
  1. package/bin/cli.js +8 -7
  2. package/bin/exec.js +253 -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 +19 -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/Images/Images.d.ts +103 -0
  133. package/lib/Cloudflare/Images/Images.d.ts.map +1 -0
  134. package/lib/Cloudflare/Images/Images.js +82 -0
  135. package/lib/Cloudflare/Images/Images.js.map +1 -0
  136. package/lib/Cloudflare/Images/ImagesBinding.d.ts +73 -0
  137. package/lib/Cloudflare/Images/ImagesBinding.d.ts.map +1 -0
  138. package/lib/Cloudflare/Images/ImagesBinding.js +83 -0
  139. package/lib/Cloudflare/Images/ImagesBinding.js.map +1 -0
  140. package/lib/Cloudflare/Images/index.d.ts +3 -0
  141. package/lib/Cloudflare/Images/index.d.ts.map +1 -0
  142. package/lib/Cloudflare/Images/index.js +3 -0
  143. package/lib/Cloudflare/Images/index.js.map +1 -0
  144. package/lib/Cloudflare/Local/Sidecar.d.ts +11 -4
  145. package/lib/Cloudflare/Local/Sidecar.d.ts.map +1 -1
  146. package/lib/Cloudflare/Local/Sidecar.js +8 -6
  147. package/lib/Cloudflare/Local/Sidecar.js.map +1 -1
  148. package/lib/Cloudflare/Local/SidecarHandlers.d.ts.map +1 -1
  149. package/lib/Cloudflare/Local/SidecarHandlers.js +1 -5
  150. package/lib/Cloudflare/Local/SidecarHandlers.js.map +1 -1
  151. package/lib/Cloudflare/Local/SidecarServer.js +5 -2
  152. package/lib/Cloudflare/Local/SidecarServer.js.map +1 -1
  153. package/lib/Cloudflare/Logs.d.ts +5 -0
  154. package/lib/Cloudflare/Logs.d.ts.map +1 -1
  155. package/lib/Cloudflare/Logs.js +70 -1
  156. package/lib/Cloudflare/Logs.js.map +1 -1
  157. package/lib/Cloudflare/Providers.d.ts +1 -1
  158. package/lib/Cloudflare/Providers.d.ts.map +1 -1
  159. package/lib/Cloudflare/Providers.js +6 -1
  160. package/lib/Cloudflare/Providers.js.map +1 -1
  161. package/lib/Cloudflare/Queue/Queue.d.ts +1 -1
  162. package/lib/Cloudflare/Queue/Queue.js +1 -1
  163. package/lib/Cloudflare/Queue/QueueConsumer.d.ts +6 -2
  164. package/lib/Cloudflare/Queue/QueueConsumer.d.ts.map +1 -1
  165. package/lib/Cloudflare/Queue/QueueConsumer.js +194 -53
  166. package/lib/Cloudflare/Queue/QueueConsumer.js.map +1 -1
  167. package/lib/Cloudflare/Queue/QueueEventSource.d.ts +106 -0
  168. package/lib/Cloudflare/Queue/QueueEventSource.d.ts.map +1 -0
  169. package/lib/Cloudflare/Queue/QueueEventSource.js +145 -0
  170. package/lib/Cloudflare/Queue/QueueEventSource.js.map +1 -0
  171. package/lib/Cloudflare/Queue/index.d.ts +1 -0
  172. package/lib/Cloudflare/Queue/index.d.ts.map +1 -1
  173. package/lib/Cloudflare/Queue/index.js +1 -0
  174. package/lib/Cloudflare/Queue/index.js.map +1 -1
  175. package/lib/Cloudflare/R2/R2Bucket.d.ts +229 -0
  176. package/lib/Cloudflare/R2/R2Bucket.d.ts.map +1 -1
  177. package/lib/Cloudflare/R2/R2Bucket.js +309 -2
  178. package/lib/Cloudflare/R2/R2Bucket.js.map +1 -1
  179. package/lib/Cloudflare/StateStore/State.d.ts +4 -3
  180. package/lib/Cloudflare/StateStore/State.d.ts.map +1 -1
  181. package/lib/Cloudflare/StateStore/State.js +16 -8
  182. package/lib/Cloudflare/StateStore/State.js.map +1 -1
  183. package/lib/Cloudflare/VpcService/VpcServiceRef.d.ts +1 -1
  184. package/lib/Cloudflare/VpcService/VpcServiceRef.d.ts.map +1 -1
  185. package/lib/Cloudflare/Website/StaticSite.d.ts.map +1 -1
  186. package/lib/Cloudflare/Website/StaticSite.js +10 -1
  187. package/lib/Cloudflare/Website/StaticSite.js.map +1 -1
  188. package/lib/Cloudflare/Workers/Assets.d.ts +1 -1
  189. package/lib/Cloudflare/Workers/Assets.d.ts.map +1 -1
  190. package/lib/Cloudflare/Workers/InferEnv.d.ts +1 -1
  191. package/lib/Cloudflare/Workers/InferEnv.d.ts.map +1 -1
  192. package/lib/Cloudflare/Workers/LocalWorkerProvider.d.ts.map +1 -1
  193. package/lib/Cloudflare/Workers/LocalWorkerProvider.js +11 -1
  194. package/lib/Cloudflare/Workers/LocalWorkerProvider.js.map +1 -1
  195. package/lib/Cloudflare/Workers/Worker.d.ts +14 -12
  196. package/lib/Cloudflare/Workers/Worker.d.ts.map +1 -1
  197. package/lib/Cloudflare/Workers/Worker.js +96 -165
  198. package/lib/Cloudflare/Workers/Worker.js.map +1 -1
  199. package/lib/Cloudflare/Workers/WorkerBundle.d.ts +2 -0
  200. package/lib/Cloudflare/Workers/WorkerBundle.d.ts.map +1 -1
  201. package/lib/Cloudflare/Workers/WorkerBundle.js +21 -7
  202. package/lib/Cloudflare/Workers/WorkerBundle.js.map +1 -1
  203. package/lib/Cloudflare/Zone.d.ts +14 -0
  204. package/lib/Cloudflare/Zone.d.ts.map +1 -0
  205. package/lib/Cloudflare/Zone.js +44 -0
  206. package/lib/Cloudflare/Zone.js.map +1 -0
  207. package/lib/Cloudflare/index.d.ts +1 -0
  208. package/lib/Cloudflare/index.d.ts.map +1 -1
  209. package/lib/Cloudflare/index.js +1 -0
  210. package/lib/Cloudflare/index.js.map +1 -1
  211. package/lib/Drizzle/Schema.d.ts.map +1 -1
  212. package/lib/Drizzle/Schema.js +20 -5
  213. package/lib/Drizzle/Schema.js.map +1 -1
  214. package/lib/GitHub/AuthProvider.d.ts +3 -1
  215. package/lib/GitHub/AuthProvider.d.ts.map +1 -1
  216. package/lib/GitHub/AuthProvider.js +114 -108
  217. package/lib/GitHub/AuthProvider.js.map +1 -1
  218. package/lib/GitHub/Credentials.d.ts +2 -1
  219. package/lib/GitHub/Credentials.d.ts.map +1 -1
  220. package/lib/GitHub/Credentials.js +4 -4
  221. package/lib/GitHub/Credentials.js.map +1 -1
  222. package/lib/GitHub/Providers.d.ts +1 -1
  223. package/lib/GitHub/Providers.d.ts.map +1 -1
  224. package/lib/GitHub/Providers.js +3 -1
  225. package/lib/GitHub/Providers.js.map +1 -1
  226. package/lib/GitHub/Secrets.d.ts.map +1 -1
  227. package/lib/GitHub/Secrets.js +14 -1
  228. package/lib/GitHub/Secrets.js.map +1 -1
  229. package/lib/GitHub/Variables.d.ts +40 -0
  230. package/lib/GitHub/Variables.d.ts.map +1 -0
  231. package/lib/GitHub/Variables.js +28 -0
  232. package/lib/GitHub/Variables.js.map +1 -0
  233. package/lib/GitHub/index.d.ts +1 -0
  234. package/lib/GitHub/index.d.ts.map +1 -1
  235. package/lib/GitHub/index.js +1 -0
  236. package/lib/GitHub/index.js.map +1 -1
  237. package/lib/Neon/AuthProvider.d.ts +3 -1
  238. package/lib/Neon/AuthProvider.d.ts.map +1 -1
  239. package/lib/Neon/AuthProvider.js +87 -80
  240. package/lib/Neon/AuthProvider.js.map +1 -1
  241. package/lib/Neon/Credentials.d.ts +2 -1
  242. package/lib/Neon/Credentials.d.ts.map +1 -1
  243. package/lib/Neon/Credentials.js +4 -4
  244. package/lib/Neon/Credentials.js.map +1 -1
  245. package/lib/Neon/NeonEnvironment.d.ts +2 -1
  246. package/lib/Neon/NeonEnvironment.d.ts.map +1 -1
  247. package/lib/Neon/NeonEnvironment.js +3 -2
  248. package/lib/Neon/NeonEnvironment.js.map +1 -1
  249. package/lib/Neon/Project.d.ts +16 -0
  250. package/lib/Neon/Project.d.ts.map +1 -1
  251. package/lib/Neon/Project.js +25 -0
  252. package/lib/Neon/Project.js.map +1 -1
  253. package/lib/Neon/Providers.d.ts +1 -1
  254. package/lib/Neon/Providers.d.ts.map +1 -1
  255. package/lib/Neon/Providers.js +3 -1
  256. package/lib/Neon/Providers.js.map +1 -1
  257. package/lib/Neon/api.d.ts +1 -0
  258. package/lib/Neon/api.d.ts.map +1 -1
  259. package/lib/Neon/api.js +1 -0
  260. package/lib/Neon/api.js.map +1 -1
  261. package/lib/Sidecar/RpcClient.d.ts.map +1 -1
  262. package/lib/Sidecar/RpcClient.js +8 -5
  263. package/lib/Sidecar/RpcClient.js.map +1 -1
  264. package/lib/Sidecar/RpcPaths.d.ts +5 -0
  265. package/lib/Sidecar/RpcPaths.d.ts.map +1 -1
  266. package/lib/Sidecar/RpcPaths.js +10 -1
  267. package/lib/Sidecar/RpcPaths.js.map +1 -1
  268. package/lib/Sidecar/RpcServer.d.ts +24 -4
  269. package/lib/Sidecar/RpcServer.d.ts.map +1 -1
  270. package/lib/Sidecar/RpcServer.js +70 -15
  271. package/lib/Sidecar/RpcServer.js.map +1 -1
  272. package/lib/Sidecar/RpcServerBun.d.ts +4 -0
  273. package/lib/Sidecar/RpcServerBun.d.ts.map +1 -0
  274. package/lib/Sidecar/RpcServerBun.js +28 -0
  275. package/lib/Sidecar/RpcServerBun.js.map +1 -0
  276. package/lib/Sidecar/RpcServerNode.d.ts +4 -0
  277. package/lib/Sidecar/RpcServerNode.d.ts.map +1 -0
  278. package/lib/Sidecar/RpcServerNode.js +39 -0
  279. package/lib/Sidecar/RpcServerNode.js.map +1 -0
  280. package/lib/Sidecar/RpcServices.d.ts +6 -0
  281. package/lib/Sidecar/RpcServices.d.ts.map +1 -0
  282. package/lib/Sidecar/RpcServices.js +29 -0
  283. package/lib/Sidecar/RpcServices.js.map +1 -0
  284. package/lib/Stack.d.ts +5 -3
  285. package/lib/Stack.d.ts.map +1 -1
  286. package/lib/Stack.js +3 -1
  287. package/lib/Stack.js.map +1 -1
  288. package/lib/Test/Core.d.ts.map +1 -1
  289. package/lib/Test/Core.js +5 -4
  290. package/lib/Test/Core.js.map +1 -1
  291. package/lib/Test/Vitest.d.ts.map +1 -1
  292. package/lib/Test/Vitest.js +2 -0
  293. package/lib/Test/Vitest.js.map +1 -1
  294. package/lib/Util/LocalhostDns.d.ts +19 -0
  295. package/lib/Util/LocalhostDns.d.ts.map +1 -0
  296. package/lib/Util/LocalhostDns.js +55 -0
  297. package/lib/Util/LocalhostDns.js.map +1 -0
  298. package/lib/Util/PlatformServices.d.ts.map +1 -1
  299. package/lib/Util/PlatformServices.js +3 -1
  300. package/lib/Util/PlatformServices.js.map +1 -1
  301. package/lib/tsconfig.test.tsbuildinfo +1 -1
  302. package/package.json +16 -12
  303. package/src/AWS/AuthProvider.ts +269 -259
  304. package/src/AWS/Environment.ts +57 -3
  305. package/src/AWS/IAM/OpenIDConnectProvider.ts +19 -8
  306. package/src/AWS/IAM/Policy.ts +1 -1
  307. package/src/AWS/Providers.ts +2 -0
  308. package/src/Auth/Credentials.ts +82 -46
  309. package/src/Auth/Profile.ts +123 -69
  310. package/src/Axiom/AuthProvider.ts +263 -255
  311. package/src/Axiom/Credentials.ts +3 -4
  312. package/src/Axiom/Providers.ts +4 -0
  313. package/src/Cli/LoggingCli.ts +127 -11
  314. package/src/Cli/checkVersion.ts +57 -0
  315. package/src/Cli/commands/_shared.ts +4 -4
  316. package/src/Cli/commands/aws.ts +127 -0
  317. package/src/Cli/commands/cloudflare.ts +222 -0
  318. package/src/Cli/commands/deploy.ts +11 -10
  319. package/src/Cli/commands/dev.ts +28 -33
  320. package/src/Cli/commands/login.ts +9 -12
  321. package/src/Cli/commands/logs.ts +8 -8
  322. package/src/Cli/commands/profile.ts +14 -16
  323. package/src/Cli/commands/state.ts +8 -8
  324. package/src/Cli/commands/tail.ts +8 -8
  325. package/src/Cli/exec.ts +7 -3
  326. package/src/Cli/main.ts +23 -5
  327. package/src/Cli/selectCli.ts +33 -0
  328. package/src/Cloudflare/Auth/AuthProvider.ts +445 -430
  329. package/src/Cloudflare/CloudflareEnvironment.ts +3 -2
  330. package/src/Cloudflare/Credentials.ts +3 -4
  331. package/src/Cloudflare/Images/Images.ts +121 -0
  332. package/src/Cloudflare/Images/ImagesBinding.ts +192 -0
  333. package/src/Cloudflare/Images/index.ts +2 -0
  334. package/src/Cloudflare/Local/Sidecar.ts +13 -10
  335. package/src/Cloudflare/Local/SidecarHandlers.ts +8 -13
  336. package/src/Cloudflare/Local/SidecarServer.ts +6 -1
  337. package/src/Cloudflare/Logs.ts +115 -1
  338. package/src/Cloudflare/Providers.ts +9 -0
  339. package/src/Cloudflare/Queue/Queue.ts +1 -1
  340. package/src/Cloudflare/Queue/QueueConsumer.ts +262 -60
  341. package/src/Cloudflare/Queue/QueueEventSource.ts +234 -0
  342. package/src/Cloudflare/Queue/index.ts +1 -0
  343. package/src/Cloudflare/R2/R2Bucket.ts +570 -2
  344. package/src/Cloudflare/StateStore/State.ts +25 -16
  345. package/src/Cloudflare/Website/StaticSite.ts +11 -1
  346. package/src/Cloudflare/Workers/InferEnv.ts +7 -3
  347. package/src/Cloudflare/Workers/LocalWorkerProvider.ts +9 -1
  348. package/src/Cloudflare/Workers/Worker.ts +130 -231
  349. package/src/Cloudflare/Workers/WorkerBundle.ts +38 -12
  350. package/src/Cloudflare/Zone.ts +88 -0
  351. package/src/Cloudflare/index.ts +1 -0
  352. package/src/Drizzle/Schema.ts +21 -5
  353. package/src/GitHub/AuthProvider.ts +221 -217
  354. package/src/GitHub/Credentials.ts +3 -4
  355. package/src/GitHub/Providers.ts +4 -0
  356. package/src/GitHub/Secrets.ts +25 -1
  357. package/src/GitHub/Variables.ts +54 -0
  358. package/src/GitHub/index.ts +1 -0
  359. package/src/Neon/AuthProvider.ts +160 -154
  360. package/src/Neon/Credentials.ts +3 -4
  361. package/src/Neon/NeonEnvironment.ts +3 -2
  362. package/src/Neon/Project.ts +42 -0
  363. package/src/Neon/Providers.ts +4 -0
  364. package/src/Neon/api.ts +2 -0
  365. package/src/Sidecar/RpcClient.ts +8 -7
  366. package/src/Sidecar/RpcPaths.ts +11 -1
  367. package/src/Sidecar/RpcServer.ts +97 -24
  368. package/src/Sidecar/RpcServerBun.ts +41 -0
  369. package/src/Sidecar/RpcServerNode.ts +51 -0
  370. package/src/Sidecar/RpcServices.ts +48 -0
  371. package/src/Stack.ts +8 -0
  372. package/src/Test/Core.ts +10 -4
  373. package/src/Test/Vitest.ts +3 -0
  374. package/src/Util/LocalhostDns.ts +58 -0
  375. package/src/Util/PlatformServices.ts +3 -1
  376. package/lib/Cli/commands/bootstrap.d.ts +0 -20
  377. package/lib/Cli/commands/bootstrap.d.ts.map +0 -1
  378. package/lib/Cli/commands/bootstrap.js +0 -107
  379. package/lib/Cli/commands/bootstrap.js.map +0 -1
  380. package/lib/Sidecar/RpcTransport.d.ts +0 -22
  381. package/lib/Sidecar/RpcTransport.d.ts.map +0 -1
  382. package/lib/Sidecar/RpcTransport.js +0 -81
  383. package/lib/Sidecar/RpcTransport.js.map +0 -1
  384. package/lib/Test/TestCli.d.ts +0 -19
  385. package/lib/Test/TestCli.d.ts.map +0 -1
  386. package/lib/Test/TestCli.js +0 -175
  387. package/lib/Test/TestCli.js.map +0 -1
  388. package/src/Cli/commands/bootstrap.ts +0 -216
  389. package/src/Sidecar/RpcTransport.ts +0 -85
  390. package/src/Test/TestCli.ts +0 -221
@@ -1,16 +1,101 @@
1
1
  import * as r2 from "@distilled.cloud/cloudflare/r2";
2
2
  import * as Effect from "effect/Effect";
3
+ import * as Schedule from "effect/Schedule";
3
4
 
4
- import { isResolved } from "../../Diff.ts";
5
+ import { deepEqual, isResolved } from "../../Diff.ts";
5
6
  import { createPhysicalName } from "../../PhysicalName.ts";
6
7
  import * as Provider from "../../Provider.ts";
7
8
  import { Resource } from "../../Resource.ts";
8
9
  import { CloudflareEnvironment } from "../CloudflareEnvironment.ts";
9
10
  import type * as Cloudflare from "../Providers.ts";
11
+ import * as Zone from "../Zone.ts";
10
12
  import { R2BucketBinding } from "./R2BucketBinding.ts";
11
13
 
12
14
  export type R2BucketName = string;
13
15
 
16
+ export type R2BucketCustomDomainZone = Zone.ZoneReference;
17
+
18
+ export type R2BucketCustomDomain = {
19
+ /**
20
+ * Custom domain name to attach to the bucket.
21
+ */
22
+ name: string;
23
+ /**
24
+ * Zone that contains the custom domain. If omitted, the zone is inferred
25
+ * from `domain`. Pass a zone ID string, a hostname in the zone, or any object
26
+ * with a `zoneId` attribute such as `Cloudflare.Zone`.
27
+ */
28
+ zone?: R2BucketCustomDomainZone;
29
+ /**
30
+ * Whether public bucket access is enabled at this custom domain.
31
+ * @default true
32
+ */
33
+ enabled?: boolean;
34
+ /**
35
+ * Allowlist of TLS ciphers in BoringSSL format.
36
+ */
37
+ ciphers?: string[];
38
+ /**
39
+ * Minimum TLS version accepted by the custom domain.
40
+ * @default "1.0"
41
+ */
42
+ minTLS?: "1.0" | "1.1" | "1.2" | "1.3";
43
+ };
44
+
45
+ export type R2BucketLifecycleCondition =
46
+ | {
47
+ type: "Age";
48
+ /**
49
+ * Maximum age of an object, in seconds, before the rule's action applies.
50
+ */
51
+ maxAge: number;
52
+ }
53
+ | {
54
+ type: "Date";
55
+ /**
56
+ * Absolute date (ISO 8601) at which the rule's action applies.
57
+ */
58
+ date: string;
59
+ };
60
+
61
+ export type R2BucketLifecycleRule = {
62
+ /**
63
+ * Unique identifier for the rule within the bucket.
64
+ */
65
+ id: string;
66
+ /**
67
+ * Whether the rule is enabled.
68
+ * @default true
69
+ */
70
+ enabled?: boolean;
71
+ /**
72
+ * Object key prefix the rule applies to. Use `""` (or omit) to match all
73
+ * objects in the bucket.
74
+ * @default ""
75
+ */
76
+ prefix?: string;
77
+ /**
78
+ * Abort incomplete multipart uploads after the configured age.
79
+ */
80
+ abortMultipartUploadsTransition?: {
81
+ condition?: { type: "Age"; maxAge: number };
82
+ };
83
+ /**
84
+ * Delete matching objects after the configured age or on a specific date.
85
+ */
86
+ deleteObjectsTransition?: {
87
+ condition?: R2BucketLifecycleCondition;
88
+ };
89
+ /**
90
+ * Transition matching objects to a different storage class. Cloudflare R2
91
+ * only supports transitioning to `InfrequentAccess` today.
92
+ */
93
+ storageClassTransitions?: {
94
+ condition: R2BucketLifecycleCondition;
95
+ storageClass: "InfrequentAccess";
96
+ }[];
97
+ };
98
+
14
99
  export type R2BucketProps = {
15
100
  /**
16
101
  * Name of the bucket. If omitted, a unique name will be generated.
@@ -31,6 +116,17 @@ export type R2BucketProps = {
31
116
  * Location hint for the bucket.
32
117
  */
33
118
  locationHint?: R2Bucket.Location;
119
+ /**
120
+ * Custom domains to attach to the bucket. Pass an empty array (or omit)
121
+ * to remove all custom domains.
122
+ */
123
+ domains?: R2BucketCustomDomain[];
124
+ /**
125
+ * Object lifecycle rules applied to the bucket. Pass an empty array (or
126
+ * omit) to clear all lifecycle rules. See the Cloudflare R2 docs for
127
+ * supported transitions.
128
+ */
129
+ lifecycleRules?: R2BucketLifecycleRule[];
34
130
  };
35
131
 
36
132
  export type R2Bucket = Resource<
@@ -42,6 +138,8 @@ export type R2Bucket = Resource<
42
138
  jurisdiction: R2Bucket.Jurisdiction;
43
139
  location: R2Bucket.Location | undefined;
44
140
  accountId: string;
141
+ domains: R2Bucket.CustomDomain[];
142
+ lifecycleRules: R2Bucket.LifecycleRule[];
45
143
  },
46
144
  never,
47
145
  Cloudflare.Providers
@@ -89,6 +187,112 @@ export type R2Bucket = Resource<
89
187
  * contentLength: Number(request.headers["content-length"] ?? 0),
90
188
  * });
91
189
  * ```
190
+ *
191
+ * @section Custom Domains
192
+ *
193
+ * Attach one or more custom domains to serve bucket objects from a hostname
194
+ * you control. The domain's zone must already exist in your Cloudflare
195
+ * account; the zone is inferred from the hostname when omitted, or you can
196
+ * pass a `Cloudflare.Zone` resource, a zone ID, or any hostname inside the
197
+ * zone via the `zone` field.
198
+ *
199
+ * @example Single custom domain
200
+ * ```typescript
201
+ * const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
202
+ * domains: [{ name: "assets.example.com" }],
203
+ * });
204
+ * ```
205
+ *
206
+ * @example Multiple custom domains
207
+ * ```typescript
208
+ * const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
209
+ * domains: [
210
+ * { name: "assets.example.com" },
211
+ * { name: "static.example.com" },
212
+ * ],
213
+ * });
214
+ * ```
215
+ *
216
+ * @example Disable a custom domain without removing it
217
+ * ```typescript
218
+ * const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
219
+ * domains: [{ name: "assets.example.com", enabled: false }],
220
+ * });
221
+ * ```
222
+ *
223
+ * @example Custom domain with explicit zone and TLS settings
224
+ * ```typescript
225
+ * const zone = yield* Cloudflare.Zone("ExampleZone", {
226
+ * name: "example.com",
227
+ * });
228
+ *
229
+ * const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
230
+ * domains: [
231
+ * {
232
+ * name: "assets.example.com",
233
+ * zone,
234
+ * minTLS: "1.2",
235
+ * },
236
+ * ],
237
+ * });
238
+ * ```
239
+ *
240
+ * @section Object Lifecycle Rules
241
+ *
242
+ * Configure lifecycle rules to automatically delete objects, abort
243
+ * incomplete multipart uploads, or transition objects to InfrequentAccess
244
+ * storage. Pass an empty array (or omit) to clear all rules. See the
245
+ * [Cloudflare R2 docs](https://developers.cloudflare.com/r2/buckets/object-lifecycles/)
246
+ * for details and limits (max 1000 rules per bucket).
247
+ *
248
+ * @example Delete objects 30 days after upload
249
+ * ```typescript
250
+ * const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
251
+ * lifecycleRules: [
252
+ * {
253
+ * id: "expire-old-objects",
254
+ * deleteObjectsTransition: {
255
+ * condition: { type: "Age", maxAge: 60 * 60 * 24 * 30 },
256
+ * },
257
+ * },
258
+ * ],
259
+ * });
260
+ * ```
261
+ *
262
+ * @example Transition to InfrequentAccess after 60 days, delete after 365
263
+ * ```typescript
264
+ * const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
265
+ * lifecycleRules: [
266
+ * {
267
+ * id: "archive-then-delete",
268
+ * prefix: "logs/",
269
+ * storageClassTransitions: [
270
+ * {
271
+ * condition: { type: "Age", maxAge: 60 * 60 * 24 * 60 },
272
+ * storageClass: "InfrequentAccess",
273
+ * },
274
+ * ],
275
+ * deleteObjectsTransition: {
276
+ * condition: { type: "Age", maxAge: 60 * 60 * 24 * 365 },
277
+ * },
278
+ * },
279
+ * ],
280
+ * });
281
+ * ```
282
+ *
283
+ * @example Abort incomplete multipart uploads after 7 days
284
+ * ```typescript
285
+ * const bucket = yield* Cloudflare.R2Bucket("MyBucket", {
286
+ * lifecycleRules: [
287
+ * {
288
+ * id: "abort-stale-uploads",
289
+ * abortMultipartUploadsTransition: {
290
+ * condition: { type: "Age", maxAge: 60 * 60 * 24 * 7 },
291
+ * },
292
+ * },
293
+ * ],
294
+ * });
295
+ * ```
92
296
  */
93
297
  export const R2Bucket = Resource<R2Bucket>("Cloudflare.R2Bucket")({
94
298
  bind: R2BucketBinding.bind,
@@ -98,6 +302,48 @@ export declare namespace R2Bucket {
98
302
  export type StorageClass = "Standard" | "InfrequentAccess";
99
303
  export type Jurisdiction = "default" | "eu" | "fedramp";
100
304
  export type Location = "apac" | "eeur" | "enam" | "weur" | "wnam" | "oc";
305
+ export type LifecycleRule = {
306
+ id: string;
307
+ enabled: boolean;
308
+ prefix: string;
309
+ abortMultipartUploadsTransition:
310
+ | { condition: { type: "Age"; maxAge: number } | undefined }
311
+ | undefined;
312
+ deleteObjectsTransition:
313
+ | { condition: R2BucketLifecycleCondition | undefined }
314
+ | undefined;
315
+ storageClassTransitions:
316
+ | {
317
+ condition: R2BucketLifecycleCondition;
318
+ storageClass: "InfrequentAccess";
319
+ }[]
320
+ | undefined;
321
+ };
322
+ export type CustomDomain = {
323
+ domain: string;
324
+ zoneId: string | undefined;
325
+ enabled: boolean;
326
+ ciphers: string[] | undefined;
327
+ minTLS: "1.0" | "1.1" | "1.2" | "1.3" | undefined;
328
+ status:
329
+ | {
330
+ ownership:
331
+ | "pending"
332
+ | "active"
333
+ | "deactivated"
334
+ | "blocked"
335
+ | "error"
336
+ | "unknown";
337
+ ssl:
338
+ | "initializing"
339
+ | "pending"
340
+ | "active"
341
+ | "deactivated"
342
+ | "error"
343
+ | "unknown";
344
+ }
345
+ | undefined;
346
+ };
101
347
  }
102
348
 
103
349
  export const R2BucketProvider = () =>
@@ -109,6 +355,12 @@ export const R2BucketProvider = () =>
109
355
  const patchBucket = yield* r2.patchBucket;
110
356
  const deleteBucket = yield* r2.deleteBucket;
111
357
  const getBucket = yield* r2.getBucket;
358
+ const listBucketDomainCustoms = yield* r2.listBucketDomainCustoms;
359
+ const createBucketDomainCustom = yield* r2.createBucketDomainCustom;
360
+ const updateBucketDomainCustom = yield* r2.updateBucketDomainCustom;
361
+ const deleteBucketDomainCustom = yield* r2.deleteBucketDomainCustom;
362
+ const getBucketLifecycle = yield* r2.getBucketLifecycle;
363
+ const putBucketLifecycle = yield* r2.putBucketLifecycle;
112
364
 
113
365
  const createBucketName = (id: string, name: string | undefined) =>
114
366
  Effect.gen(function* () {
@@ -126,6 +378,187 @@ export const R2BucketProvider = () =>
126
378
  return location.toLowerCase() as R2Bucket.Location;
127
379
  };
128
380
 
381
+ const listCustomDomains = (
382
+ bucketName: string,
383
+ jurisdiction: R2Bucket.Jurisdiction,
384
+ ) =>
385
+ listBucketDomainCustoms({
386
+ accountId,
387
+ bucketName,
388
+ jurisdiction,
389
+ }).pipe(
390
+ Effect.retry({
391
+ while: isNoSuchBucket,
392
+ schedule: r2BucketEndpointConsistencySchedule,
393
+ }),
394
+ Effect.map((response) =>
395
+ response.domains.map(toCustomDomainAttributes),
396
+ ),
397
+ Effect.catchTag("NoSuchBucket", () => Effect.succeed(undefined)),
398
+ );
399
+
400
+ const reconcileCustomDomains = (
401
+ bucketName: string,
402
+ jurisdiction: R2Bucket.Jurisdiction,
403
+ desired: R2BucketCustomDomain[],
404
+ previous: R2Bucket.CustomDomain[],
405
+ ) =>
406
+ Effect.gen(function* () {
407
+ const observed = yield* listCustomDomains(bucketName, jurisdiction);
408
+ if (!observed) {
409
+ return yield* Effect.fail(
410
+ new Error(
411
+ `Cannot reconcile custom domains for missing R2 bucket "${bucketName}"`,
412
+ ),
413
+ );
414
+ }
415
+ const observedByDomain = new Map(
416
+ observed.map((domain) => [domain.domain, domain]),
417
+ );
418
+ const desiredDomains = new Set(desired.map((domain) => domain.name));
419
+
420
+ // Remove domains that are no longer desired. Domains that keep the
421
+ // same hostname but move zones are intentionally skipped here and
422
+ // handled in the per-domain flow below.
423
+ yield* Effect.forEach(
424
+ previous,
425
+ (previousDomain) =>
426
+ desiredDomains.has(previousDomain.domain)
427
+ ? Effect.void
428
+ : deleteBucketDomainCustom({
429
+ accountId,
430
+ bucketName,
431
+ domain: previousDomain.domain,
432
+ jurisdiction,
433
+ }).pipe(
434
+ Effect.catchIf(
435
+ isMissingCustomDomainOrBucket,
436
+ () => Effect.void,
437
+ ),
438
+ ),
439
+ { concurrency: "unbounded" },
440
+ );
441
+
442
+ const applied = yield* Effect.forEach(
443
+ desired,
444
+ (domain) =>
445
+ Effect.gen(function* () {
446
+ const zoneId = yield* Zone.resolveZoneId({
447
+ accountId,
448
+ zone: domain.zone,
449
+ hostname: domain.name,
450
+ });
451
+ const observedDomain = observedByDomain.get(domain.name);
452
+
453
+ if (
454
+ observedDomain &&
455
+ sameCustomDomainConfig(observedDomain, domain, zoneId)
456
+ ) {
457
+ return observedDomain;
458
+ }
459
+
460
+ if (observedDomain && observedDomain.zoneId !== zoneId) {
461
+ // Cloudflare does not mutate the zone for an existing custom
462
+ // domain. This is not a duplicate of the stale-domain prune
463
+ // above: the hostname is still desired, so that prune skips it
464
+ // and this branch deletes only to recreate it in the new zone.
465
+ yield* deleteBucketDomainCustom({
466
+ accountId,
467
+ bucketName,
468
+ domain: domain.name,
469
+ jurisdiction,
470
+ }).pipe(
471
+ Effect.catchIf(
472
+ isMissingCustomDomainOrBucket,
473
+ () => Effect.void,
474
+ ),
475
+ );
476
+ }
477
+
478
+ if (!observedDomain || observedDomain.zoneId !== zoneId) {
479
+ const created = yield* createBucketDomainCustom({
480
+ accountId,
481
+ bucketName,
482
+ jurisdiction,
483
+ domain: domain.name,
484
+ enabled: domain.enabled ?? true,
485
+ zoneId,
486
+ ciphers: domain.ciphers,
487
+ minTLS: domain.minTLS,
488
+ }).pipe(
489
+ Effect.retry({
490
+ while: isNoSuchBucket,
491
+ schedule: r2BucketEndpointConsistencySchedule,
492
+ }),
493
+ );
494
+ return toCustomDomainAttributes({ ...created, zoneId });
495
+ }
496
+
497
+ const updated = yield* updateBucketDomainCustom({
498
+ accountId,
499
+ bucketName,
500
+ domain: domain.name,
501
+ jurisdiction,
502
+ enabled: domain.enabled ?? true,
503
+ ciphers: domain.ciphers,
504
+ minTLS: domain.minTLS,
505
+ }).pipe(
506
+ Effect.retry({
507
+ while: isNoSuchBucket,
508
+ schedule: r2BucketEndpointConsistencySchedule,
509
+ }),
510
+ );
511
+ return toCustomDomainAttributes({
512
+ ...updated,
513
+ enabled: updated.enabled ?? domain.enabled ?? true,
514
+ zoneId,
515
+ });
516
+ }),
517
+ { concurrency: "unbounded" },
518
+ );
519
+
520
+ return applied.sort((a, b) => a.domain.localeCompare(b.domain));
521
+ });
522
+
523
+ const reconcileLifecycleRules = (
524
+ bucketName: string,
525
+ jurisdiction: R2Bucket.Jurisdiction,
526
+ desired: R2BucketLifecycleRule[],
527
+ ) =>
528
+ Effect.gen(function* () {
529
+ const observed = yield* getBucketLifecycle({
530
+ accountId,
531
+ bucketName,
532
+ jurisdiction,
533
+ }).pipe(
534
+ Effect.retry({
535
+ while: isNoSuchBucket,
536
+ schedule: r2BucketEndpointConsistencySchedule,
537
+ }),
538
+ );
539
+
540
+ const observedRules = (observed.rules ?? []).map(toLifecycleRule);
541
+ const desiredRules = desired.map(normalizeLifecycleRule);
542
+
543
+ if (deepEqual(observedRules, desiredRules)) {
544
+ return desiredRules;
545
+ }
546
+
547
+ yield* putBucketLifecycle({
548
+ accountId,
549
+ bucketName,
550
+ jurisdiction,
551
+ rules: desired.map(toLifecyclePutPayload),
552
+ }).pipe(
553
+ Effect.retry({
554
+ while: isNoSuchBucket,
555
+ schedule: r2BucketEndpointConsistencySchedule,
556
+ }),
557
+ );
558
+
559
+ return desiredRules;
560
+ });
561
+
129
562
  return {
130
563
  stables: ["bucketName", "accountId"],
131
564
  diff: Effect.fn(function* ({ id, olds = {}, news = {}, output }) {
@@ -152,6 +585,12 @@ export const R2BucketProvider = () =>
152
585
  stables: oldName === name ? ["bucketName"] : undefined,
153
586
  } as const;
154
587
  }
588
+ if (!deepEqual(olds.domains, news.domains)) {
589
+ return { action: "update" } as const;
590
+ }
591
+ if (!deepEqual(olds.lifecycleRules, news.lifecycleRules)) {
592
+ return { action: "update" } as const;
593
+ }
155
594
  }),
156
595
  reconcile: Effect.fn(function* ({ id, news = {}, output }) {
157
596
  const name = yield* createBucketName(id, news.name);
@@ -206,15 +645,44 @@ export const R2BucketProvider = () =>
206
645
  });
207
646
  }
208
647
 
209
- return {
648
+ const attrs = {
210
649
  bucketName: observed.name!,
211
650
  storageClass: observed.storageClass ?? "Standard",
212
651
  jurisdiction: observed.jurisdiction ?? "default",
213
652
  location: normalizeLocation(observed.location),
214
653
  accountId: acct,
215
654
  };
655
+
656
+ const domains = yield* reconcileCustomDomains(
657
+ attrs.bucketName,
658
+ attrs.jurisdiction,
659
+ news.domains ?? [],
660
+ output?.domains ?? [],
661
+ );
662
+
663
+ const lifecycleRules = yield* reconcileLifecycleRules(
664
+ attrs.bucketName,
665
+ attrs.jurisdiction,
666
+ news.lifecycleRules ?? [],
667
+ );
668
+
669
+ return {
670
+ ...attrs,
671
+ domains,
672
+ lifecycleRules,
673
+ };
216
674
  }),
217
675
  delete: Effect.fn(function* ({ output }) {
676
+ for (const domain of output.domains ?? []) {
677
+ yield* deleteBucketDomainCustom({
678
+ accountId: output.accountId,
679
+ bucketName: output.bucketName,
680
+ domain: domain.domain,
681
+ jurisdiction: output.jurisdiction,
682
+ }).pipe(
683
+ Effect.catchIf(isMissingCustomDomainOrBucket, () => Effect.void),
684
+ );
685
+ }
218
686
  yield* deleteBucket({
219
687
  accountId: output.accountId,
220
688
  bucketName: output.bucketName,
@@ -236,6 +704,8 @@ export const R2BucketProvider = () =>
236
704
  jurisdiction: bucket.jurisdiction ?? "default",
237
705
  location: normalizeLocation(bucket.location),
238
706
  accountId: acct,
707
+ domains: output?.domains ?? [],
708
+ lifecycleRules: output?.lifecycleRules ?? [],
239
709
  })),
240
710
  Effect.catchTag("NoSuchBucket", () => Effect.succeed(undefined)),
241
711
  );
@@ -243,3 +713,101 @@ export const R2BucketProvider = () =>
243
713
  };
244
714
  }),
245
715
  );
716
+
717
+ // R2 can make a newly-created bucket visible to `getBucket` before its
718
+ // sub-resource endpoints (custom domains, lifecycle) accept it. Retry only
719
+ // that narrow `NoSuchBucket` lag here; not-found sub-resources are still
720
+ // treated as terminal for idempotent deletes.
721
+ const r2BucketEndpointConsistencySchedule = Schedule.exponential(100).pipe(
722
+ Schedule.both(Schedule.recurs(5)),
723
+ );
724
+
725
+ type CustomDomainResponse = {
726
+ domain: string;
727
+ zoneId?: string | null;
728
+ enabled?: boolean | null;
729
+ ciphers?: string[] | null;
730
+ minTLS?: "1.0" | "1.1" | "1.2" | "1.3" | null;
731
+ status?: R2Bucket.CustomDomain["status"];
732
+ };
733
+
734
+ const toCustomDomainAttributes = (
735
+ domain: CustomDomainResponse,
736
+ ): R2Bucket.CustomDomain => ({
737
+ domain: domain.domain,
738
+ zoneId: domain.zoneId ?? undefined,
739
+ enabled: domain.enabled ?? true,
740
+ ciphers: domain.ciphers ?? undefined,
741
+ minTLS: domain.minTLS ?? undefined,
742
+ status: domain.status,
743
+ });
744
+
745
+ const sameCustomDomainConfig = (
746
+ observed: R2Bucket.CustomDomain | undefined,
747
+ desired: R2BucketCustomDomain,
748
+ zoneId: string,
749
+ ): boolean =>
750
+ observed !== undefined &&
751
+ observed.zoneId === zoneId &&
752
+ observed.enabled === (desired.enabled ?? true) &&
753
+ deepEqual(observed.ciphers, desired.ciphers) &&
754
+ observed.minTLS === desired.minTLS;
755
+
756
+ const isMissingCustomDomainOrBucket = (error: unknown): boolean =>
757
+ typeof error === "object" &&
758
+ error !== null &&
759
+ (("status" in error && (error as { status: unknown }).status === 404) ||
760
+ ("_tag" in error &&
761
+ ((error as { _tag: unknown })._tag === "DomainNotFound" ||
762
+ (error as { _tag: unknown })._tag === "NoSuchBucket")));
763
+
764
+ type LifecycleRuleResponse = NonNullable<
765
+ r2.GetBucketLifecycleResponse["rules"]
766
+ >[number];
767
+
768
+ const toLifecycleRule = (
769
+ rule: LifecycleRuleResponse,
770
+ ): R2Bucket.LifecycleRule => ({
771
+ id: rule.id,
772
+ enabled: rule.enabled,
773
+ prefix: rule.conditions.prefix ?? "",
774
+ abortMultipartUploadsTransition: rule.abortMultipartUploadsTransition
775
+ ? { condition: rule.abortMultipartUploadsTransition.condition ?? undefined }
776
+ : undefined,
777
+ deleteObjectsTransition: rule.deleteObjectsTransition
778
+ ? { condition: rule.deleteObjectsTransition.condition ?? undefined }
779
+ : undefined,
780
+ storageClassTransitions: rule.storageClassTransitions ?? undefined,
781
+ });
782
+
783
+ const normalizeLifecycleRule = (
784
+ rule: R2BucketLifecycleRule,
785
+ ): R2Bucket.LifecycleRule => ({
786
+ id: rule.id,
787
+ enabled: rule.enabled ?? true,
788
+ prefix: rule.prefix ?? "",
789
+ abortMultipartUploadsTransition: rule.abortMultipartUploadsTransition
790
+ ? { condition: rule.abortMultipartUploadsTransition.condition }
791
+ : undefined,
792
+ deleteObjectsTransition: rule.deleteObjectsTransition
793
+ ? { condition: rule.deleteObjectsTransition.condition }
794
+ : undefined,
795
+ storageClassTransitions: rule.storageClassTransitions,
796
+ });
797
+
798
+ const toLifecyclePutPayload = (
799
+ rule: R2BucketLifecycleRule,
800
+ ): NonNullable<r2.PutBucketLifecycleRequest["rules"]>[number] => ({
801
+ id: rule.id,
802
+ enabled: rule.enabled ?? true,
803
+ conditions: { prefix: rule.prefix ?? "" },
804
+ abortMultipartUploadsTransition: rule.abortMultipartUploadsTransition,
805
+ deleteObjectsTransition: rule.deleteObjectsTransition,
806
+ storageClassTransitions: rule.storageClassTransitions,
807
+ });
808
+
809
+ const isNoSuchBucket = (error: unknown): boolean =>
810
+ typeof error === "object" &&
811
+ error !== null &&
812
+ "_tag" in error &&
813
+ (error as { _tag: unknown })._tag === "NoSuchBucket";