@alchemy.run/fly 0.0.0 → 2.0.0-beta.85

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 (499) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +57 -4
  3. package/lib/App.d.ts +230 -0
  4. package/lib/App.d.ts.map +1 -0
  5. package/lib/App.js +338 -0
  6. package/lib/App.js.map +1 -0
  7. package/lib/AuthProvider.d.ts +22 -0
  8. package/lib/AuthProvider.d.ts.map +1 -0
  9. package/lib/AuthProvider.js +48 -0
  10. package/lib/AuthProvider.js.map +1 -0
  11. package/lib/BindService.d.ts +159 -0
  12. package/lib/BindService.d.ts.map +1 -0
  13. package/lib/BindService.js +222 -0
  14. package/lib/BindService.js.map +1 -0
  15. package/lib/Bootstrap.d.ts +8 -0
  16. package/lib/Bootstrap.d.ts.map +1 -0
  17. package/lib/Bootstrap.js +41 -0
  18. package/lib/Bootstrap.js.map +1 -0
  19. package/lib/Bucket.d.ts +278 -0
  20. package/lib/Bucket.d.ts.map +1 -0
  21. package/lib/Bucket.js +658 -0
  22. package/lib/Bucket.js.map +1 -0
  23. package/lib/BucketBinding.d.ts +33 -0
  24. package/lib/BucketBinding.d.ts.map +1 -0
  25. package/lib/BucketBinding.js +70 -0
  26. package/lib/BucketBinding.js.map +1 -0
  27. package/lib/Catalog.d.ts +28 -0
  28. package/lib/Catalog.d.ts.map +1 -0
  29. package/lib/Catalog.js +31 -0
  30. package/lib/Catalog.js.map +1 -0
  31. package/lib/Certificate.d.ts +189 -0
  32. package/lib/Certificate.d.ts.map +1 -0
  33. package/lib/Certificate.js +380 -0
  34. package/lib/Certificate.js.map +1 -0
  35. package/lib/Checkpoint.d.ts +55 -0
  36. package/lib/Checkpoint.d.ts.map +1 -0
  37. package/lib/Checkpoint.js +3 -0
  38. package/lib/Checkpoint.js.map +1 -0
  39. package/lib/CheckpointHttp.d.ts +22 -0
  40. package/lib/CheckpointHttp.d.ts.map +1 -0
  41. package/lib/CheckpointHttp.js +53 -0
  42. package/lib/CheckpointHttp.js.map +1 -0
  43. package/lib/ConnectPostgres.d.ts +58 -0
  44. package/lib/ConnectPostgres.d.ts.map +1 -0
  45. package/lib/ConnectPostgres.js +13 -0
  46. package/lib/ConnectPostgres.js.map +1 -0
  47. package/lib/ConnectPostgresHttp.d.ts +26 -0
  48. package/lib/ConnectPostgresHttp.d.ts.map +1 -0
  49. package/lib/ConnectPostgresHttp.js +57 -0
  50. package/lib/ConnectPostgresHttp.js.map +1 -0
  51. package/lib/Contributions.d.ts +7 -0
  52. package/lib/Contributions.d.ts.map +1 -0
  53. package/lib/Contributions.js +6 -0
  54. package/lib/Contributions.js.map +1 -0
  55. package/lib/Credentials.d.ts +33 -0
  56. package/lib/Credentials.d.ts.map +1 -0
  57. package/lib/Credentials.js +55 -0
  58. package/lib/Credentials.js.map +1 -0
  59. package/lib/Decrypt.d.ts +52 -0
  60. package/lib/Decrypt.d.ts.map +1 -0
  61. package/lib/Decrypt.js +3 -0
  62. package/lib/Decrypt.js.map +1 -0
  63. package/lib/DecryptHttp.d.ts +22 -0
  64. package/lib/DecryptHttp.d.ts.map +1 -0
  65. package/lib/DecryptHttp.js +43 -0
  66. package/lib/DecryptHttp.js.map +1 -0
  67. package/lib/DeleteObject.d.ts +29 -0
  68. package/lib/DeleteObject.d.ts.map +1 -0
  69. package/lib/DeleteObject.js +3 -0
  70. package/lib/DeleteObject.js.map +1 -0
  71. package/lib/DeleteObjectHttp.d.ts +12 -0
  72. package/lib/DeleteObjectHttp.d.ts.map +1 -0
  73. package/lib/DeleteObjectHttp.js +17 -0
  74. package/lib/DeleteObjectHttp.js.map +1 -0
  75. package/lib/Deployment.d.ts +51 -0
  76. package/lib/Deployment.d.ts.map +1 -0
  77. package/lib/Deployment.js +62 -0
  78. package/lib/Deployment.js.map +1 -0
  79. package/lib/DeploymentImages.d.ts +18 -0
  80. package/lib/DeploymentImages.d.ts.map +1 -0
  81. package/lib/DeploymentImages.js +61 -0
  82. package/lib/DeploymentImages.js.map +1 -0
  83. package/lib/DeploymentState.d.ts +17 -0
  84. package/lib/DeploymentState.d.ts.map +1 -0
  85. package/lib/DeploymentState.js +87 -0
  86. package/lib/DeploymentState.js.map +1 -0
  87. package/lib/Encrypt.d.ts +50 -0
  88. package/lib/Encrypt.d.ts.map +1 -0
  89. package/lib/Encrypt.js +3 -0
  90. package/lib/Encrypt.js.map +1 -0
  91. package/lib/EncryptHttp.d.ts +22 -0
  92. package/lib/EncryptHttp.d.ts.map +1 -0
  93. package/lib/EncryptHttp.js +39 -0
  94. package/lib/EncryptHttp.js.map +1 -0
  95. package/lib/Environment.d.ts +45 -0
  96. package/lib/Environment.d.ts.map +1 -0
  97. package/lib/Environment.js +43 -0
  98. package/lib/Environment.js.map +1 -0
  99. package/lib/Errors.d.ts +18 -0
  100. package/lib/Errors.d.ts.map +1 -0
  101. package/lib/Errors.js +13 -0
  102. package/lib/Errors.js.map +1 -0
  103. package/lib/Exec.d.ts +41 -0
  104. package/lib/Exec.d.ts.map +1 -0
  105. package/lib/Exec.js +3 -0
  106. package/lib/Exec.js.map +1 -0
  107. package/lib/ExecHttp.d.ts +22 -0
  108. package/lib/ExecHttp.d.ts.map +1 -0
  109. package/lib/ExecHttp.js +39 -0
  110. package/lib/ExecHttp.js.map +1 -0
  111. package/lib/GetObject.d.ts +34 -0
  112. package/lib/GetObject.d.ts.map +1 -0
  113. package/lib/GetObject.js +3 -0
  114. package/lib/GetObject.js.map +1 -0
  115. package/lib/GetObjectHttp.d.ts +12 -0
  116. package/lib/GetObjectHttp.d.ts.map +1 -0
  117. package/lib/GetObjectHttp.js +17 -0
  118. package/lib/GetObjectHttp.js.map +1 -0
  119. package/lib/GetSecret.d.ts +44 -0
  120. package/lib/GetSecret.d.ts.map +1 -0
  121. package/lib/GetSecret.js +3 -0
  122. package/lib/GetSecret.js.map +1 -0
  123. package/lib/GetSecretHttp.d.ts +22 -0
  124. package/lib/GetSecretHttp.d.ts.map +1 -0
  125. package/lib/GetSecretHttp.js +50 -0
  126. package/lib/GetSecretHttp.js.map +1 -0
  127. package/lib/HeadObject.d.ts +29 -0
  128. package/lib/HeadObject.d.ts.map +1 -0
  129. package/lib/HeadObject.js +3 -0
  130. package/lib/HeadObject.js.map +1 -0
  131. package/lib/HeadObjectHttp.d.ts +12 -0
  132. package/lib/HeadObjectHttp.d.ts.map +1 -0
  133. package/lib/HeadObjectHttp.js +17 -0
  134. package/lib/HeadObjectHttp.js.map +1 -0
  135. package/lib/IpAssignment.d.ts +258 -0
  136. package/lib/IpAssignment.d.ts.map +1 -0
  137. package/lib/IpAssignment.js +376 -0
  138. package/lib/IpAssignment.js.map +1 -0
  139. package/lib/ListObjectsV2.d.ts +29 -0
  140. package/lib/ListObjectsV2.d.ts.map +1 -0
  141. package/lib/ListObjectsV2.js +3 -0
  142. package/lib/ListObjectsV2.js.map +1 -0
  143. package/lib/ListObjectsV2Http.d.ts +12 -0
  144. package/lib/ListObjectsV2Http.d.ts.map +1 -0
  145. package/lib/ListObjectsV2Http.js +17 -0
  146. package/lib/ListObjectsV2Http.js.map +1 -0
  147. package/lib/ListSecrets.d.ts +53 -0
  148. package/lib/ListSecrets.d.ts.map +1 -0
  149. package/lib/ListSecrets.js +3 -0
  150. package/lib/ListSecrets.js.map +1 -0
  151. package/lib/ListSecretsHttp.d.ts +22 -0
  152. package/lib/ListSecretsHttp.d.ts.map +1 -0
  153. package/lib/ListSecretsHttp.js +35 -0
  154. package/lib/ListSecretsHttp.js.map +1 -0
  155. package/lib/Machine.d.ts +802 -0
  156. package/lib/Machine.d.ts.map +1 -0
  157. package/lib/Machine.js +773 -0
  158. package/lib/Machine.js.map +1 -0
  159. package/lib/MachineContainers.d.ts +44 -0
  160. package/lib/MachineContainers.d.ts.map +1 -0
  161. package/lib/MachineContainers.js +115 -0
  162. package/lib/MachineContainers.js.map +1 -0
  163. package/lib/Metadata.d.ts +109 -0
  164. package/lib/Metadata.d.ts.map +1 -0
  165. package/lib/Metadata.js +159 -0
  166. package/lib/Metadata.js.map +1 -0
  167. package/lib/MountVolume.d.ts +295 -0
  168. package/lib/MountVolume.d.ts.map +1 -0
  169. package/lib/MountVolume.js +20 -0
  170. package/lib/MountVolume.js.map +1 -0
  171. package/lib/Postgres.d.ts +298 -0
  172. package/lib/Postgres.d.ts.map +1 -0
  173. package/lib/Postgres.js +508 -0
  174. package/lib/Postgres.js.map +1 -0
  175. package/lib/PostgresMigrations.d.ts +20 -0
  176. package/lib/PostgresMigrations.d.ts.map +1 -0
  177. package/lib/PostgresMigrations.js +58 -0
  178. package/lib/PostgresMigrations.js.map +1 -0
  179. package/lib/Providers.d.ts +38 -0
  180. package/lib/Providers.d.ts.map +1 -0
  181. package/lib/Providers.js +95 -0
  182. package/lib/Providers.js.map +1 -0
  183. package/lib/PutObject.d.ts +35 -0
  184. package/lib/PutObject.d.ts.map +1 -0
  185. package/lib/PutObject.js +3 -0
  186. package/lib/PutObject.js.map +1 -0
  187. package/lib/PutObjectHttp.d.ts +12 -0
  188. package/lib/PutObjectHttp.d.ts.map +1 -0
  189. package/lib/PutObjectHttp.js +17 -0
  190. package/lib/PutObjectHttp.js.map +1 -0
  191. package/lib/ReadRedis.d.ts +26 -0
  192. package/lib/ReadRedis.d.ts.map +1 -0
  193. package/lib/ReadRedis.js +3 -0
  194. package/lib/ReadRedis.js.map +1 -0
  195. package/lib/ReadRedisHttp.d.ts +11 -0
  196. package/lib/ReadRedisHttp.d.ts.map +1 -0
  197. package/lib/ReadRedisHttp.js +15 -0
  198. package/lib/ReadRedisHttp.js.map +1 -0
  199. package/lib/ReadWriteRedis.d.ts +29 -0
  200. package/lib/ReadWriteRedis.d.ts.map +1 -0
  201. package/lib/ReadWriteRedis.js +3 -0
  202. package/lib/ReadWriteRedis.js.map +1 -0
  203. package/lib/ReadWriteRedisHttp.d.ts +11 -0
  204. package/lib/ReadWriteRedisHttp.d.ts.map +1 -0
  205. package/lib/ReadWriteRedisHttp.js +15 -0
  206. package/lib/ReadWriteRedisHttp.js.map +1 -0
  207. package/lib/Redis.d.ts +252 -0
  208. package/lib/Redis.d.ts.map +1 -0
  209. package/lib/Redis.js +611 -0
  210. package/lib/Redis.js.map +1 -0
  211. package/lib/RedisBinding.d.ts +7 -0
  212. package/lib/RedisBinding.d.ts.map +1 -0
  213. package/lib/RedisBinding.js +53 -0
  214. package/lib/RedisBinding.js.map +1 -0
  215. package/lib/RedisHttp.d.ts +8 -0
  216. package/lib/RedisHttp.d.ts.map +1 -0
  217. package/lib/RedisHttp.js +11 -0
  218. package/lib/RedisHttp.js.map +1 -0
  219. package/lib/Region.d.ts +16 -0
  220. package/lib/Region.d.ts.map +1 -0
  221. package/lib/Region.js +13 -0
  222. package/lib/Region.js.map +1 -0
  223. package/lib/Secret.d.ts +190 -0
  224. package/lib/Secret.d.ts.map +1 -0
  225. package/lib/Secret.js +310 -0
  226. package/lib/Secret.js.map +1 -0
  227. package/lib/SecretHttp.d.ts +54 -0
  228. package/lib/SecretHttp.d.ts.map +1 -0
  229. package/lib/SecretHttp.js +66 -0
  230. package/lib/SecretHttp.js.map +1 -0
  231. package/lib/SecretKey.d.ts +164 -0
  232. package/lib/SecretKey.d.ts.map +1 -0
  233. package/lib/SecretKey.js +277 -0
  234. package/lib/SecretKey.js.map +1 -0
  235. package/lib/SecretKeyHttp.d.ts +14 -0
  236. package/lib/SecretKeyHttp.d.ts.map +1 -0
  237. package/lib/SecretKeyHttp.js +5 -0
  238. package/lib/SecretKeyHttp.js.map +1 -0
  239. package/lib/Service.d.ts +1017 -0
  240. package/lib/Service.d.ts.map +1 -0
  241. package/lib/Service.js +1430 -0
  242. package/lib/Service.js.map +1 -0
  243. package/lib/Sign.d.ts +36 -0
  244. package/lib/Sign.d.ts.map +1 -0
  245. package/lib/Sign.js +3 -0
  246. package/lib/Sign.js.map +1 -0
  247. package/lib/SignHttp.d.ts +22 -0
  248. package/lib/SignHttp.d.ts.map +1 -0
  249. package/lib/SignHttp.js +36 -0
  250. package/lib/SignHttp.js.map +1 -0
  251. package/lib/Sprite.d.ts +283 -0
  252. package/lib/Sprite.d.ts.map +1 -0
  253. package/lib/Sprite.js +471 -0
  254. package/lib/Sprite.js.map +1 -0
  255. package/lib/SpriteHttp.d.ts +25 -0
  256. package/lib/SpriteHttp.d.ts.map +1 -0
  257. package/lib/SpriteHttp.js +33 -0
  258. package/lib/SpriteHttp.js.map +1 -0
  259. package/lib/Verify.d.ts +37 -0
  260. package/lib/Verify.d.ts.map +1 -0
  261. package/lib/Verify.js +3 -0
  262. package/lib/Verify.js.map +1 -0
  263. package/lib/VerifyHttp.d.ts +22 -0
  264. package/lib/VerifyHttp.d.ts.map +1 -0
  265. package/lib/VerifyHttp.js +38 -0
  266. package/lib/VerifyHttp.js.map +1 -0
  267. package/lib/Volume.d.ts +53 -0
  268. package/lib/Volume.d.ts.map +1 -0
  269. package/lib/Volume.js +188 -0
  270. package/lib/Volume.js.map +1 -0
  271. package/lib/VolumeSnapshot.d.ts +135 -0
  272. package/lib/VolumeSnapshot.d.ts.map +1 -0
  273. package/lib/VolumeSnapshot.js +213 -0
  274. package/lib/VolumeSnapshot.js.map +1 -0
  275. package/lib/Website/AssetDeployment.d.ts +43 -0
  276. package/lib/Website/AssetDeployment.d.ts.map +1 -0
  277. package/lib/Website/AssetDeployment.js +162 -0
  278. package/lib/Website/AssetDeployment.js.map +1 -0
  279. package/lib/Website/Astro.d.ts +89 -0
  280. package/lib/Website/Astro.d.ts.map +1 -0
  281. package/lib/Website/Astro.js +54 -0
  282. package/lib/Website/Astro.js.map +1 -0
  283. package/lib/Website/Foldkit.d.ts +52 -0
  284. package/lib/Website/Foldkit.d.ts.map +1 -0
  285. package/lib/Website/Foldkit.js +45 -0
  286. package/lib/Website/Foldkit.js.map +1 -0
  287. package/lib/Website/FrameworkSite.d.ts +212 -0
  288. package/lib/Website/FrameworkSite.d.ts.map +1 -0
  289. package/lib/Website/FrameworkSite.js +205 -0
  290. package/lib/Website/FrameworkSite.js.map +1 -0
  291. package/lib/Website/Nextjs.d.ts +54 -0
  292. package/lib/Website/Nextjs.d.ts.map +1 -0
  293. package/lib/Website/Nextjs.js +46 -0
  294. package/lib/Website/Nextjs.js.map +1 -0
  295. package/lib/Website/Nuxt.d.ts +51 -0
  296. package/lib/Website/Nuxt.d.ts.map +1 -0
  297. package/lib/Website/Nuxt.js +36 -0
  298. package/lib/Website/Nuxt.js.map +1 -0
  299. package/lib/Website/Octane.d.ts +49 -0
  300. package/lib/Website/Octane.d.ts.map +1 -0
  301. package/lib/Website/Octane.js +39 -0
  302. package/lib/Website/Octane.js.map +1 -0
  303. package/lib/Website/ReactRouter.d.ts +80 -0
  304. package/lib/Website/ReactRouter.d.ts.map +1 -0
  305. package/lib/Website/ReactRouter.js +70 -0
  306. package/lib/Website/ReactRouter.js.map +1 -0
  307. package/lib/Website/SolidStart.d.ts +93 -0
  308. package/lib/Website/SolidStart.d.ts.map +1 -0
  309. package/lib/Website/SolidStart.js +71 -0
  310. package/lib/Website/SolidStart.js.map +1 -0
  311. package/lib/Website/StaticSite.d.ts +162 -0
  312. package/lib/Website/StaticSite.d.ts.map +1 -0
  313. package/lib/Website/StaticSite.js +180 -0
  314. package/lib/Website/StaticSite.js.map +1 -0
  315. package/lib/Website/SvelteKit.d.ts +52 -0
  316. package/lib/Website/SvelteKit.d.ts.map +1 -0
  317. package/lib/Website/SvelteKit.js +37 -0
  318. package/lib/Website/SvelteKit.js.map +1 -0
  319. package/lib/Website/TanStackStart.d.ts +76 -0
  320. package/lib/Website/TanStackStart.d.ts.map +1 -0
  321. package/lib/Website/TanStackStart.js +66 -0
  322. package/lib/Website/TanStackStart.js.map +1 -0
  323. package/lib/Website/Vinext.d.ts +73 -0
  324. package/lib/Website/Vinext.d.ts.map +1 -0
  325. package/lib/Website/Vinext.js +67 -0
  326. package/lib/Website/Vinext.js.map +1 -0
  327. package/lib/Website/Vite.d.ts +112 -0
  328. package/lib/Website/Vite.d.ts.map +1 -0
  329. package/lib/Website/Vite.js +100 -0
  330. package/lib/Website/Vite.js.map +1 -0
  331. package/lib/Website/Vocs.d.ts +52 -0
  332. package/lib/Website/Vocs.d.ts.map +1 -0
  333. package/lib/Website/Vocs.js +38 -0
  334. package/lib/Website/Vocs.js.map +1 -0
  335. package/lib/Website/Waku.d.ts +64 -0
  336. package/lib/Website/Waku.d.ts.map +1 -0
  337. package/lib/Website/Waku.js +39 -0
  338. package/lib/Website/Waku.js.map +1 -0
  339. package/lib/Website/index.d.ts +17 -0
  340. package/lib/Website/index.d.ts.map +1 -0
  341. package/lib/Website/index.js +17 -0
  342. package/lib/Website/index.js.map +1 -0
  343. package/lib/WriteCertificates.d.ts +63 -0
  344. package/lib/WriteCertificates.d.ts.map +1 -0
  345. package/lib/WriteCertificates.js +3 -0
  346. package/lib/WriteCertificates.js.map +1 -0
  347. package/lib/WriteCertificatesHttp.d.ts +25 -0
  348. package/lib/WriteCertificatesHttp.d.ts.map +1 -0
  349. package/lib/WriteCertificatesHttp.js +67 -0
  350. package/lib/WriteCertificatesHttp.js.map +1 -0
  351. package/lib/WriteRedis.d.ts +26 -0
  352. package/lib/WriteRedis.d.ts.map +1 -0
  353. package/lib/WriteRedis.js +3 -0
  354. package/lib/WriteRedis.js.map +1 -0
  355. package/lib/WriteRedisHttp.d.ts +11 -0
  356. package/lib/WriteRedisHttp.d.ts.map +1 -0
  357. package/lib/WriteRedisHttp.js +15 -0
  358. package/lib/WriteRedisHttp.js.map +1 -0
  359. package/lib/WriteSecret.d.ts +68 -0
  360. package/lib/WriteSecret.d.ts.map +1 -0
  361. package/lib/WriteSecret.js +4 -0
  362. package/lib/WriteSecret.js.map +1 -0
  363. package/lib/WriteSecretHttp.d.ts +26 -0
  364. package/lib/WriteSecretHttp.d.ts.map +1 -0
  365. package/lib/WriteSecretHttp.js +54 -0
  366. package/lib/WriteSecretHttp.js.map +1 -0
  367. package/lib/bluegreen.d.ts +36 -0
  368. package/lib/bluegreen.d.ts.map +1 -0
  369. package/lib/bluegreen.js +460 -0
  370. package/lib/bluegreen.js.map +1 -0
  371. package/lib/hosted.d.ts +171 -0
  372. package/lib/hosted.d.ts.map +1 -0
  373. package/lib/hosted.js +458 -0
  374. package/lib/hosted.js.map +1 -0
  375. package/lib/index.d.ts +65 -0
  376. package/lib/index.d.ts.map +1 -0
  377. package/lib/index.js +63 -0
  378. package/lib/index.js.map +1 -0
  379. package/lib/internal/RemoteBuilder.d.ts +28 -0
  380. package/lib/internal/RemoteBuilder.d.ts.map +1 -0
  381. package/lib/internal/RemoteBuilder.js +158 -0
  382. package/lib/internal/RemoteBuilder.js.map +1 -0
  383. package/lib/leases.d.ts +53 -0
  384. package/lib/leases.d.ts.map +1 -0
  385. package/lib/leases.js +279 -0
  386. package/lib/leases.js.map +1 -0
  387. package/lib/ports.d.ts +51 -0
  388. package/lib/ports.d.ts.map +1 -0
  389. package/lib/ports.js +123 -0
  390. package/lib/ports.js.map +1 -0
  391. package/lib/replicas.d.ts +270 -0
  392. package/lib/replicas.d.ts.map +1 -0
  393. package/lib/replicas.js +969 -0
  394. package/lib/replicas.js.map +1 -0
  395. package/lib/rpc.d.ts +35 -0
  396. package/lib/rpc.d.ts.map +1 -0
  397. package/lib/rpc.js +113 -0
  398. package/lib/rpc.js.map +1 -0
  399. package/package.json +83 -3
  400. package/src/App.ts +514 -0
  401. package/src/AuthProvider.ts +68 -0
  402. package/src/BindService.ts +303 -0
  403. package/src/Bootstrap.ts +66 -0
  404. package/src/Bucket.ts +918 -0
  405. package/src/BucketBinding.ts +128 -0
  406. package/src/Catalog.ts +43 -0
  407. package/src/Certificate.ts +548 -0
  408. package/src/Checkpoint.ts +69 -0
  409. package/src/CheckpointHttp.ts +66 -0
  410. package/src/ConnectPostgres.ts +68 -0
  411. package/src/ConnectPostgresHttp.ts +77 -0
  412. package/src/Contributions.ts +9 -0
  413. package/src/Credentials.ts +75 -0
  414. package/src/Decrypt.ts +62 -0
  415. package/src/DecryptHttp.ts +52 -0
  416. package/src/DeleteObject.ts +43 -0
  417. package/src/DeleteObjectHttp.ts +20 -0
  418. package/src/Deployment.ts +121 -0
  419. package/src/DeploymentImages.ts +84 -0
  420. package/src/DeploymentState.ts +104 -0
  421. package/src/Encrypt.ts +60 -0
  422. package/src/EncryptHttp.ts +48 -0
  423. package/src/Environment.ts +81 -0
  424. package/src/Errors.ts +14 -0
  425. package/src/Exec.ts +50 -0
  426. package/src/ExecHttp.ts +47 -0
  427. package/src/GetObject.ts +48 -0
  428. package/src/GetObjectHttp.ts +20 -0
  429. package/src/GetSecret.ts +48 -0
  430. package/src/GetSecretHttp.ts +60 -0
  431. package/src/HeadObject.ts +43 -0
  432. package/src/HeadObjectHttp.ts +20 -0
  433. package/src/IpAssignment.ts +522 -0
  434. package/src/ListObjectsV2.ts +43 -0
  435. package/src/ListObjectsV2Http.ts +20 -0
  436. package/src/ListSecrets.ts +57 -0
  437. package/src/ListSecretsHttp.ts +43 -0
  438. package/src/Machine.ts +1270 -0
  439. package/src/MachineContainers.ts +152 -0
  440. package/src/Metadata.ts +195 -0
  441. package/src/MountVolume.ts +315 -0
  442. package/src/Postgres.ts +777 -0
  443. package/src/PostgresMigrations.ts +93 -0
  444. package/src/Providers.ts +155 -0
  445. package/src/PutObject.ts +49 -0
  446. package/src/PutObjectHttp.ts +20 -0
  447. package/src/ReadRedis.ts +31 -0
  448. package/src/ReadRedisHttp.ts +18 -0
  449. package/src/ReadWriteRedis.ts +33 -0
  450. package/src/ReadWriteRedisHttp.ts +18 -0
  451. package/src/Redis.ts +823 -0
  452. package/src/RedisBinding.ts +64 -0
  453. package/src/RedisHttp.ts +14 -0
  454. package/src/Region.ts +44 -0
  455. package/src/Secret.ts +405 -0
  456. package/src/SecretHttp.ts +149 -0
  457. package/src/SecretKey.ts +389 -0
  458. package/src/SecretKeyHttp.ts +23 -0
  459. package/src/Service.ts +1968 -0
  460. package/src/Sign.ts +46 -0
  461. package/src/SignHttp.ts +44 -0
  462. package/src/Sprite.ts +673 -0
  463. package/src/SpriteHttp.ts +50 -0
  464. package/src/Verify.ts +47 -0
  465. package/src/VerifyHttp.ts +46 -0
  466. package/src/Volume.ts +264 -0
  467. package/src/VolumeSnapshot.ts +321 -0
  468. package/src/Website/AssetDeployment.ts +292 -0
  469. package/src/Website/Astro.ts +92 -0
  470. package/src/Website/Foldkit.ts +54 -0
  471. package/src/Website/FrameworkSite.ts +449 -0
  472. package/src/Website/Nextjs.ts +50 -0
  473. package/src/Website/Nuxt.ts +48 -0
  474. package/src/Website/Octane.ts +44 -0
  475. package/src/Website/ReactRouter.ts +76 -0
  476. package/src/Website/SolidStart.ts +90 -0
  477. package/src/Website/StaticSite.ts +295 -0
  478. package/src/Website/SvelteKit.ts +49 -0
  479. package/src/Website/TanStackStart.ts +72 -0
  480. package/src/Website/Vinext.ts +79 -0
  481. package/src/Website/Vite.ts +121 -0
  482. package/src/Website/Vocs.ts +50 -0
  483. package/src/Website/Waku.ts +65 -0
  484. package/src/Website/index.ts +16 -0
  485. package/src/WriteCertificates.ts +90 -0
  486. package/src/WriteCertificatesHttp.ts +93 -0
  487. package/src/WriteRedis.ts +31 -0
  488. package/src/WriteRedisHttp.ts +18 -0
  489. package/src/WriteSecret.ts +86 -0
  490. package/src/WriteSecretHttp.ts +71 -0
  491. package/src/bluegreen.ts +711 -0
  492. package/src/globals.d.ts +2 -0
  493. package/src/hosted.ts +667 -0
  494. package/src/index.ts +64 -0
  495. package/src/internal/RemoteBuilder.ts +242 -0
  496. package/src/leases.ts +437 -0
  497. package/src/ports.ts +177 -0
  498. package/src/replicas.ts +1480 -0
  499. package/src/rpc.ts +136 -0
@@ -0,0 +1,64 @@
1
+ import type { Url } from "@alchemy.run/redis";
2
+ import * as Binding from "alchemy/Binding";
3
+ import type { Resource } from "alchemy/Resource";
4
+ import * as Config from "effect/Config";
5
+ import * as Effect from "effect/Effect";
6
+ import * as Redacted from "effect/Redacted";
7
+ import type { ServiceBinding } from "./MountVolume.ts";
8
+ import { REDIS_URL_ENV, RedisUrlMissing, type Redis } from "./Redis.ts";
9
+
10
+ /**
11
+ * Shared scaffolding for Upstash Redis bindings.
12
+ *
13
+ * Each `{Op}Http.ts` is a thin `Layer.effect` over {@link makeRedisBinding}.
14
+ * Deploy-time registers the Redis add-on on the host so Service reconcile
15
+ * can attach it. The URL travels as `yield* redis.url` (RuntimeContext
16
+ * set/get). `REDIS_URL` written as an App secret is a fallback, not the
17
+ * primary path.
18
+ *
19
+ * The RESP client lives in `@alchemy.run/redis`. This file only wires the
20
+ * Fly host binding.
21
+ *
22
+ * NOT exported from `index.ts`.
23
+ */
24
+
25
+ const isFlyHost = (value: unknown): value is Resource<string, any, any, ServiceBinding> =>
26
+ typeof value === "object" &&
27
+ value !== null &&
28
+ ((value as { Type?: string }).Type === "Fly.Service" ||
29
+ (value as { Type?: string }).Type === "Fly.Machine");
30
+
31
+ const asPlain = (value: unknown): string | undefined => {
32
+ if (typeof value === "string" && value.length > 0) return value;
33
+ if (Redacted.isRedacted(value)) return value.pipe(Redacted.value, asPlain);
34
+ return undefined;
35
+ };
36
+
37
+ const redisUrlFromEnv = Config.Redacted(REDIS_URL_ENV).pipe(
38
+ Effect.map((value) => Redacted.value(value)),
39
+ );
40
+
41
+ export const makeRedisBinding = <Client>(options: { makeClient: (url: Url) => Client }) =>
42
+ Effect.succeed(
43
+ Effect.fn(function* (redis: Redis) {
44
+ if (!globalThis.__ALCHEMY_RUNTIME__) {
45
+ const host = yield* Binding.Host;
46
+ if (isFlyHost(host)) {
47
+ yield* host.bind`${redis}`({
48
+ redis: { name: redis.name, id: redis.redisId },
49
+ });
50
+ }
51
+ }
52
+
53
+ const urlFromResource = yield* redis.url;
54
+ const missing = new RedisUrlMissing({
55
+ resourceName: asPlain(redis.name) ?? redis.LogicalId,
56
+ });
57
+ const url: Url = Effect.gen(function* () {
58
+ const fromOutput = asPlain(yield* urlFromResource);
59
+ if (fromOutput !== undefined) return fromOutput;
60
+ return yield* redisUrlFromEnv.pipe(Effect.mapError(() => missing));
61
+ });
62
+ return options.makeClient(url);
63
+ }),
64
+ );
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Shared Redis command-client builders. NOT exported from `index.ts`.
3
+ *
4
+ * The RESP client lives in `@alchemy.run/redis`. These aliases keep the
5
+ * `{Op}Http.ts` layers stable.
6
+ */
7
+ // Re-export from the defining module, not the `@alchemy.run/redis` barrel:
8
+ // rolldown's lazyBarrel rejects an unused re-export from an `export *` barrel
9
+ // (https://github.com/rolldown/rolldown/issues/11344).
10
+ export {
11
+ makeRead as makeReadRedisClient,
12
+ makeReadWrite as makeReadWriteRedisClient,
13
+ makeWrite as makeWriteRedisClient,
14
+ } from "@alchemy.run/redis/Client";
package/src/Region.ts ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * A Fly.io region code. The literal codes are the regions Fly listed in
3
+ * September 2026 and give editor completion; any other string is accepted
4
+ * so new regions work without an Alchemy release. `bom` is deprecated by
5
+ * Fly. See [Regions](/fly/compute/regions).
6
+ */
7
+ export type Region =
8
+ | "ams"
9
+ | "arn"
10
+ | "bom"
11
+ | "cdg"
12
+ | "dfw"
13
+ | "ewr"
14
+ | "fra"
15
+ | "gru"
16
+ | "iad"
17
+ | "jnb"
18
+ | "lax"
19
+ | "lhr"
20
+ | "nrt"
21
+ | "ord"
22
+ | "sin"
23
+ | "sjc"
24
+ | "syd"
25
+ | "yyz"
26
+ | (string & {});
27
+
28
+ /** Normalize a `Region | Region[]` prop into a de-duplicated list. */
29
+ export const regionList = (
30
+ region: Region | readonly Region[] | undefined,
31
+ fallback: string,
32
+ ): string[] => {
33
+ const list = region === undefined ? [fallback] : [region].flat();
34
+ const unique = [...new Set(list)];
35
+ return unique.length === 0 ? [fallback] : unique;
36
+ };
37
+
38
+ /**
39
+ * Region of replica `index` when `count` replicas run in each of
40
+ * `regions`. Replicas are spread round-robin, so growing `count` keeps
41
+ * every existing replica in its region.
42
+ */
43
+ export const regionOfReplica = (regions: readonly string[], index: number) =>
44
+ regions[index % regions.length]!;
package/src/Secret.ts ADDED
@@ -0,0 +1,405 @@
1
+ import { createHash } from "node:crypto";
2
+ import type { AppSecret } from "@distilled.cloud/fly-io/machines";
3
+ import * as machines from "@distilled.cloud/fly-io/machines";
4
+ import { Unowned } from "alchemy/AdoptPolicy";
5
+ import { isResolved } from "alchemy/Diff";
6
+ import * as Provider from "alchemy/Provider";
7
+ import { Resource } from "alchemy/Resource";
8
+ import * as Data from "effect/Data";
9
+ import * as Effect from "effect/Effect";
10
+ import * as Redacted from "effect/Redacted";
11
+ import * as Schedule from "effect/Schedule";
12
+ import { App, listOwnedApps } from "./App.ts";
13
+ import { createFlyVolumeName, matchesAlchemyPhysicalName } from "./Metadata.ts";
14
+ import type { Providers } from "./Providers.ts";
15
+
16
+ /**
17
+ * A resource-valued prop: the resource itself, or an Effect that produces
18
+ * it (so `yield* App(...)` and `App(...)` both type-check).
19
+ */
20
+ type Ref<T> = T | Effect.Effect<T, never, Providers>;
21
+
22
+ export interface SecretProps {
23
+ /**
24
+ * Parent Fly App. Changing it replaces the secret.
25
+ */
26
+ app: Ref<App>;
27
+ /**
28
+ * Secret name. Used as the Machine env-var name when set by the user
29
+ * (case-sensitive, stored as-is). If omitted, a unique name is generated
30
+ * from the stack, stage and logical ID (the ownership stamp). Changing
31
+ * it replaces the secret.
32
+ */
33
+ name?: string;
34
+ /**
35
+ * Secret value. Wrap with `Redacted.make(...)` so it is never logged.
36
+ * Updated in place via `updateSecrets`. Never persisted in attributes.
37
+ */
38
+ value: Redacted.Redacted<string> | string;
39
+ }
40
+
41
+ export type Secret = Resource<
42
+ "Fly.Secret",
43
+ SecretProps,
44
+ {
45
+ /** Parent Fly App name. */
46
+ appName: string;
47
+ /** Secret name (unique per App). */
48
+ name: string;
49
+ /** Fly digest of the current value. Not the plaintext. */
50
+ digest: string | undefined;
51
+ /** RFC3339 creation timestamp. */
52
+ createdAt: string | undefined;
53
+ /** RFC3339 last-update timestamp. */
54
+ updatedAt: string | undefined;
55
+ },
56
+ never,
57
+ Providers
58
+ >;
59
+
60
+ const resolveSecretProps = (
61
+ props: SecretProps | Effect.Effect<SecretProps, never, Providers>,
62
+ ): Effect.Effect<SecretProps, never, Providers> =>
63
+ Effect.gen(function* () {
64
+ const resolved = Effect.isEffect(props) ? yield* props : props;
65
+ if (globalThis.__ALCHEMY_RUNTIME__) return resolved;
66
+ const app = Effect.isEffect(resolved.app)
67
+ ? yield* resolved.app as Effect.Effect<App, never, Providers>
68
+ : resolved.app;
69
+ return { ...resolved, app };
70
+ });
71
+
72
+ const SecretResource = Resource<Secret>("Fly.Secret");
73
+
74
+ /**
75
+ * A Fly.Secret is an App vault entry. Fly injects it as an environment
76
+ * variable on every Machine. Use it when the value is shared and
77
+ * managed in one place by Fly.
78
+ *
79
+ * For a secret only this {@link Service} reads from `.env` at deploy
80
+ * time, yield `Config.Redacted` instead. Do not pass `env: { ... }` on
81
+ * a Service.
82
+ *
83
+ * @see https://fly.io/docs/apps/secrets/
84
+ *
85
+ * ### Config.Redacted on a Service
86
+ * Most secrets in a Service come from your `.env`. Yield
87
+ * `Config.Redacted` in init. Alchemy binds the value onto the Machine.
88
+ *
89
+ * **Example:** Bind from .env
90
+ * ```typescript
91
+ * import * as Config from "effect/Config";
92
+ * import * as Redacted from "effect/Redacted";
93
+ *
94
+ * export default class Api extends Fly.Service<Api>()(
95
+ * "Api",
96
+ * { app: Site, main: import.meta.url, port: 3000 },
97
+ * Effect.gen(function* () {
98
+ * const apiKey = yield* Config.Redacted("API_KEY");
99
+ *
100
+ * return {
101
+ * fetch: Effect.gen(function* () {
102
+ * const token = Redacted.value(apiKey);
103
+ * return HttpServerResponse.text("ok");
104
+ * }),
105
+ * };
106
+ * }),
107
+ * ) {}
108
+ * ```
109
+ *
110
+ * ### Create a Secret
111
+ * Wrap the value with `Redacted.make` so it is never logged. The
112
+ * plaintext is never stored in attributes. Omit `name` and Alchemy
113
+ * generates an ownership-stamped name.
114
+ *
115
+ * **Example:** Generated name
116
+ * ```typescript
117
+ * const dbUrl = yield* Fly.Secret("DatabaseUrl", {
118
+ * app: Site,
119
+ * value: Redacted.make("postgres://…"),
120
+ * });
121
+ * ```
122
+ *
123
+ * :::caution[Changing `app` replaces the Secret]
124
+ * The value is created on the new App. The old name is deleted.
125
+ * :::
126
+ *
127
+ * ### Env-var name
128
+ * `name` is the env-var Machines see. It is stored as-is
129
+ * (case-sensitive).
130
+ *
131
+ * **Example:** Explicit name
132
+ * ```typescript
133
+ * export const ApiToken = Fly.Secret("ApiToken", {
134
+ * app: Site,
135
+ * name: "API_TOKEN",
136
+ * value: Redacted.make("sk_live_…"),
137
+ * });
138
+ * ```
139
+ *
140
+ * :::caution[Changing `name` replaces the Secret]
141
+ * Fly cannot rename a secret. Alchemy creates the new name, then
142
+ * deletes the old one.
143
+ * :::
144
+ *
145
+ * ### Rotate the value
146
+ * Updating `value` is in place via `updateSecrets`.
147
+ *
148
+ * **Example:** New value
149
+ * ```typescript
150
+ * export const ApiToken = Fly.Secret("ApiToken", {
151
+ * app: Site,
152
+ * name: "API_TOKEN",
153
+ * value: Redacted.make("sk_live_rotated"),
154
+ * });
155
+ * ```
156
+ *
157
+ * ### Get a secret at runtime
158
+ * {@link GetSecret} is bound to one Secret. Provide
159
+ * {@link GetSecretHttp}. Fly only returns plaintext from a Machine in
160
+ * the same App. From a deploy-time Action you get metadata (name,
161
+ * digest, timestamps).
162
+ *
163
+ * **Example:** GetSecret
164
+ * ```typescript
165
+ * const get = yield* Fly.GetSecret(ApiToken);
166
+ * const got = yield* get();
167
+ * ```
168
+ *
169
+ * ### List secrets
170
+ * {@link ListSecrets} is bound to an {@link App}. From an Action, the
171
+ * org token can list any App in the org. From a Machine, deploy tokens
172
+ * are per-App. Mixing Apps on one Machine shares one `FLY_API_TOKEN`
173
+ * and is not supported.
174
+ *
175
+ * **Example:** ListSecrets
176
+ * ```typescript
177
+ * const list = yield* Fly.ListSecrets(Site);
178
+ * const { secrets } = yield* list();
179
+ * ```
180
+ *
181
+ * ### Write secrets
182
+ * {@link WriteSecret} creates, updates, and deletes by name. Provide
183
+ * {@link WriteSecretHttp} on the Action or Service Effect.
184
+ *
185
+ * **Example:** Rotate from an Action
186
+ * ```typescript
187
+ * const Seed = Alchemy.Action(
188
+ * "Seed",
189
+ * Effect.gen(function* () {
190
+ * const secrets = yield* Fly.WriteSecret(ApiToken);
191
+ *
192
+ * return Effect.fn(function* () {
193
+ * yield* secrets.update("API_TOKEN", Redacted.make("sk_live_rotated"));
194
+ * });
195
+ * }).pipe(Effect.provide(Fly.WriteSecretHttp)),
196
+ * );
197
+ * ```
198
+ *
199
+ * @resource
200
+ * @product Secret
201
+ */
202
+ export const Secret: typeof SecretResource = Object.assign(
203
+ (id: string, props: SecretProps | Effect.Effect<SecretProps, never, Providers>) =>
204
+ SecretResource(id, resolveSecretProps(props)),
205
+ SecretResource,
206
+ );
207
+
208
+ export class SecretNotCreated extends Data.TaggedError("Fly.SecretNotCreated")<{
209
+ appName: string;
210
+ secretName: string;
211
+ }> {}
212
+
213
+ export class SecretAppRequired extends Data.TaggedError("Fly.SecretAppRequired")<{
214
+ message: string;
215
+ }> {}
216
+
217
+ const appNameOf = (value: unknown): string | undefined => {
218
+ if (value === null || typeof value !== "object") return undefined;
219
+ const rec = value as { appName?: unknown };
220
+ return typeof rec.appName === "string" && rec.appName.length > 0 ? rec.appName : undefined;
221
+ };
222
+
223
+ const unwrapSecret = (value: Redacted.Redacted<string> | string): string =>
224
+ Redacted.isRedacted(value) ? Redacted.value(value) : value;
225
+
226
+ const resolveName = (id: string, name: string | undefined, existing?: string) =>
227
+ Effect.gen(function* () {
228
+ // User env-var names are stored as-is (case-sensitive). Generated
229
+ // names use the Volume underscore shape — Fly rejects hyphens.
230
+ if (name !== undefined) return name;
231
+ if (existing !== undefined) return existing;
232
+ return yield* createFlyVolumeName(id);
233
+ });
234
+
235
+ const toAttrs = (
236
+ appName: string,
237
+ secret: AppSecret,
238
+ fallbackName: string,
239
+ ): Secret["Attributes"] => ({
240
+ appName,
241
+ name: secret.name ?? fallbackName,
242
+ digest: secret.digest,
243
+ createdAt: secret.created_at,
244
+ updatedAt: secret.updated_at,
245
+ });
246
+
247
+ const getByName = (appName: string, secretName: string) =>
248
+ machines
249
+ .getSecret({
250
+ app_name: appName,
251
+ secret_name: secretName,
252
+ show_secrets: false,
253
+ })
254
+ .pipe(Effect.catchTag("NotFound", () => Effect.undefined));
255
+
256
+ const listSecrets = (appName: string) =>
257
+ machines
258
+ .listSecrets({
259
+ app_name: appName,
260
+ show_secrets: false,
261
+ })
262
+ .pipe(
263
+ Effect.map((res) => res.secrets ?? []),
264
+ Effect.catchTag(["NotFound", "Forbidden"], () => Effect.succeed([])),
265
+ );
266
+
267
+ const flyDigestCandidates = (plain: string) =>
268
+ Effect.sync(() => {
269
+ const utf8 = Buffer.from(plain, "utf8");
270
+ return [
271
+ createHash("md5").update(utf8).digest("hex"),
272
+ createHash("sha256").update(utf8).digest("hex"),
273
+ ];
274
+ });
275
+
276
+ export const SecretProvider = () =>
277
+ Provider.succeed(Secret, {
278
+ stables: ["appName", "name", "createdAt"],
279
+ nuke: { dependsOn: ["Fly.App"] },
280
+
281
+ diff: Effect.fn(function* ({ news, output }) {
282
+ if (news === undefined || !isResolved(news)) return undefined;
283
+ if (output === undefined) return undefined;
284
+ const desiredName = news.name !== undefined ? news.name : output.name;
285
+ const nameChanged = desiredName !== output.name;
286
+ const nextApp = appNameOf(news.app);
287
+ const appChanged = nextApp !== undefined && nextApp !== output.appName;
288
+ if (nameChanged || appChanged) {
289
+ return {
290
+ action: "replace" as const,
291
+ // Same (app, name) cannot exist twice — delete the old secret first.
292
+ deleteFirst: nameChanged && !appChanged,
293
+ };
294
+ }
295
+ return undefined;
296
+ }),
297
+
298
+ read: Effect.fn(function* ({ id, olds, output }) {
299
+ const appName = output?.appName ?? (olds !== undefined ? appNameOf(olds.app) : undefined);
300
+ if (appName === undefined) return undefined;
301
+ const name = yield* resolveName(id, olds?.name, output?.name);
302
+ const found = yield* getByName(appName, name);
303
+ if (found === undefined) return undefined;
304
+ const attrs = toAttrs(appName, found, name);
305
+ if (output !== undefined) return attrs;
306
+ return matchesAlchemyPhysicalName(name) ? attrs : Unowned(attrs);
307
+ }),
308
+
309
+ list: Effect.fn(function* () {
310
+ const apps = yield* listOwnedApps();
311
+ const rows = yield* Effect.forEach(
312
+ apps,
313
+ (app) =>
314
+ listSecrets(app.appName).pipe(
315
+ Effect.map((secrets) =>
316
+ secrets.flatMap((secret) => {
317
+ const name = secret.name;
318
+ if (!matchesAlchemyPhysicalName(name)) return [];
319
+ return [toAttrs(app.appName, secret, name ?? "")];
320
+ }),
321
+ ),
322
+ ),
323
+ { concurrency: 8 },
324
+ );
325
+ return rows.flat();
326
+ }),
327
+
328
+ reconcile: Effect.fn(function* ({ id, news, olds, output }) {
329
+ const props = news ?? ({} as SecretProps);
330
+ const appName = appNameOf(props.app) ?? output?.appName;
331
+ if (appName === undefined) {
332
+ return yield* new SecretAppRequired({
333
+ message: "Secret requires a resolved Fly.App",
334
+ });
335
+ }
336
+ const name = yield* resolveName(id, props.name, output?.name);
337
+ const desiredPlain = unwrapSecret(props.value);
338
+
339
+ // Observe by cached identity, then the desired (app, name).
340
+ let current =
341
+ output !== undefined ? yield* getByName(output.appName, output.name) : undefined;
342
+ if (
343
+ current === undefined &&
344
+ (output === undefined || output.appName !== appName || output.name !== name)
345
+ ) {
346
+ current = yield* getByName(appName, name);
347
+ }
348
+
349
+ let createdThisRun = false;
350
+ if (current === undefined) {
351
+ yield* machines
352
+ .createSecret({
353
+ app_name: appName,
354
+ secret_name: name,
355
+ value: desiredPlain,
356
+ })
357
+ .pipe(Effect.catchTag("Conflict", () => Effect.void));
358
+ current = yield* getByName(appName, name);
359
+ createdThisRun = true;
360
+ }
361
+
362
+ if (current === undefined) {
363
+ return yield* new SecretNotCreated({ appName, secretName: name });
364
+ }
365
+
366
+ // Sync — skip if we just created. Prefer observed digest vs hash of
367
+ // desired; otherwise re-put when olds is absent (adoption) or the
368
+ // previous value differs. Never log the plaintext.
369
+ if (!createdThisRun) {
370
+ const candidates = yield* flyDigestCandidates(desiredPlain);
371
+ const digestMatches = current.digest !== undefined && candidates.includes(current.digest);
372
+ const previousPlain = olds?.value !== undefined ? unwrapSecret(olds.value) : undefined;
373
+ const valueChanged = previousPlain === undefined || previousPlain !== desiredPlain;
374
+ if (!digestMatches && valueChanged) {
375
+ yield* machines
376
+ .updateSecrets({
377
+ app_name: appName,
378
+ values: { [name]: desiredPlain },
379
+ })
380
+ .pipe(Effect.catchTag("Conflict", () => Effect.void));
381
+ current = (yield* getByName(appName, name)) ?? current;
382
+ }
383
+ }
384
+
385
+ return toAttrs(appName, current, name);
386
+ }),
387
+
388
+ delete: Effect.fn(function* ({ output }) {
389
+ if (output.appName.length === 0 || output.name.length === 0) return;
390
+ yield* machines
391
+ .deleteSecret({
392
+ app_name: output.appName,
393
+ secret_name: output.name,
394
+ })
395
+ .pipe(Effect.catchTag("NotFound", () => Effect.void));
396
+ yield* getByName(output.appName, output.name).pipe(
397
+ Effect.map((secret) => secret === undefined),
398
+ Effect.repeat({
399
+ schedule: Schedule.spaced("1 second"),
400
+ until: (gone) => gone,
401
+ times: 8,
402
+ }),
403
+ );
404
+ }),
405
+ });
@@ -0,0 +1,149 @@
1
+ import {
2
+ Credentials,
3
+ CredentialsFromEnv,
4
+ credentials,
5
+ MachineIdentity,
6
+ } from "@distilled.cloud/fly-io";
7
+ import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient";
8
+ import type { RuntimeContext } from "alchemy/RuntimeContext";
9
+ import type * as Context from "effect/Context";
10
+ import * as Effect from "effect/Effect";
11
+ import * as FetchHttpClient from "effect/http/FetchHttpClient";
12
+ import * as HttpClient from "effect/http/HttpClient";
13
+ import * as Layer from "effect/Layer";
14
+ import * as Redacted from "effect/Redacted";
15
+ import type { App } from "./App.ts";
16
+ import { bindFlyApiToken } from "./Credentials.ts";
17
+ import type { Secret } from "./Secret.ts";
18
+ import type { SecretKey } from "./SecretKey.ts";
19
+
20
+ /**
21
+ * Shared scaffolding for the HTTP-backed Fly Secret bindings.
22
+ *
23
+ * Fly has no native Worker-style binding. This layer captures the ambient
24
+ * org token during stack-eval (so Actions work in-process) and `yield*`s
25
+ * it plus `appName` / secret `name` so RuntimeContext.set runs. Platform
26
+ * copies those Outputs into host env; runtime `yield*` gets them back.
27
+ * {@link CredentialsFromEnv} still reads `FLY_API_TOKEN` after that copy.
28
+ *
29
+ * NOT exported from `index.ts`.
30
+ */
31
+ export type AppNamed = Secret | SecretKey;
32
+
33
+ export const makeHttpSecretBinding = <Target extends AppNamed, Client>(options: {
34
+ makeClient: (
35
+ auth: SecretAuth,
36
+ appName: Effect.Effect<string>,
37
+ secretName: Effect.Effect<string>,
38
+ ) => Client;
39
+ /**
40
+ * PetSem encrypt/sign/decrypt/verify only work from a Machine over
41
+ * `/.fly/api` (implicit machine identity). Org tokens return Forbidden.
42
+ */
43
+ kms?: boolean;
44
+ }) =>
45
+ Effect.gen(function* () {
46
+ const context = yield* Effect.context<Credentials | HttpClient.HttpClient>();
47
+ const auth = options.kms === true ? makeKmsAuth(context) : makeSecretAuth(context);
48
+
49
+ return Effect.fn(function* (resource: Target) {
50
+ yield* bindFlyApiToken().pipe(Effect.provideContext(context));
51
+ const appName = yield* resource.appName;
52
+ const secretName = yield* resource.name;
53
+ return options.makeClient(auth, appName, secretName);
54
+ });
55
+ });
56
+
57
+ /**
58
+ * Same scaffolding as {@link makeHttpSecretBinding}, but the target is
59
+ * an {@link App} (no secret name). Used by ListSecrets.
60
+ */
61
+ export const makeHttpAppBinding = <Client>(options: {
62
+ makeClient: (auth: SecretAuth, appName: Effect.Effect<string>) => Client;
63
+ }) =>
64
+ Effect.gen(function* () {
65
+ const context = yield* Effect.context<Credentials | HttpClient.HttpClient>();
66
+
67
+ return Effect.fn(function* (app: App) {
68
+ yield* bindFlyApiToken().pipe(Effect.provideContext(context));
69
+ const appName = yield* app.appName;
70
+ return options.makeClient(makeSecretAuth(context), appName);
71
+ });
72
+ });
73
+
74
+ /**
75
+ * Injectable auth for the Secret HTTP client builders. Supplies an
76
+ * `authorize` that provides `Credentials` + `HttpClient` to a raw SDK op.
77
+ */
78
+ export interface SecretAuth {
79
+ authorize: <A, E>(
80
+ eff: Effect.Effect<A, E, Credentials | HttpClient.HttpClient>,
81
+ ) => Effect.Effect<A, E, RuntimeContext>;
82
+ }
83
+
84
+ /** Build auth that uses ambient stack creds, or env creds inside a host. */
85
+ export const makeSecretAuth = (
86
+ ambient: Context.Context<Credentials | HttpClient.HttpClient>,
87
+ ): SecretAuth => ({
88
+ authorize: <A, E>(
89
+ eff: Effect.Effect<A, E, Credentials | HttpClient.HttpClient>,
90
+ ): Effect.Effect<A, E, RuntimeContext> => {
91
+ if (globalThis.__ALCHEMY_RUNTIME__) {
92
+ // oxlint-disable-next-line effecttsgo/unsafe-effect-type-assertion -- TimeoutError/env-credential errors surface untyped; widening SecretAuth would ripple through every Fly secret client
93
+ return eff.pipe(
94
+ Effect.provide(Layer.mergeAll(CredentialsFromEnv, FetchHttpClient.layer)),
95
+ Effect.timeout("8 seconds"),
96
+ ) as Effect.Effect<A, E, RuntimeContext>;
97
+ }
98
+ return eff.pipe(Effect.provideContext(ambient)) as Effect.Effect<A, E, RuntimeContext>;
99
+ },
100
+ });
101
+
102
+ const FLY_MACHINE_API_SOCKET = "/.fly/api";
103
+
104
+ /** Distilled machines client over `/.fly/api`. URL host is unused. */
105
+ const flyMachineApiHttp: Layer.Layer<HttpClient.HttpClient> =
106
+ NodeHttpClient.layerNodeHttpNoAgent.pipe(
107
+ Layer.provide(
108
+ NodeHttpClient.layerAgentOptions({
109
+ socketPath: FLY_MACHINE_API_SOCKET,
110
+ keepAlive: false,
111
+ }),
112
+ ),
113
+ );
114
+
115
+ /**
116
+ * PetSem encrypt/sign/decrypt/verify from a Machine. Org API tokens are
117
+ * Forbidden; the machine identity is the unix socket at `/.fly/api`.
118
+ * {@link MachineIdentity} is the protocol signal (no Authorization,
119
+ * Connection: close). GetSecret in the same process keeps Bearer.
120
+ */
121
+ export const makeKmsAuth = (
122
+ ambient: Context.Context<Credentials | HttpClient.HttpClient>,
123
+ ): SecretAuth => ({
124
+ authorize: <A, E>(
125
+ eff: Effect.Effect<A, E, Credentials | HttpClient.HttpClient>,
126
+ ): Effect.Effect<A, E, RuntimeContext> => {
127
+ if (globalThis.__ALCHEMY_RUNTIME__) {
128
+ // oxlint-disable-next-line effecttsgo/unsafe-effect-type-assertion -- TimeoutError surfaces untyped; widening SecretAuth would ripple through every Fly secret client
129
+ return Effect.scoped(
130
+ eff.pipe(
131
+ Effect.provide(
132
+ Layer.mergeAll(
133
+ Layer.succeed(MachineIdentity, true),
134
+ flyMachineApiHttp,
135
+ credentials({
136
+ apiKey: Redacted.make("unused"),
137
+ apiBaseUrl: "http://localhost/v1",
138
+ }),
139
+ ),
140
+ ),
141
+ ),
142
+ ).pipe(Effect.timeout("8 seconds")) as Effect.Effect<A, E, RuntimeContext>;
143
+ }
144
+ return eff.pipe(Effect.provideContext(ambient)) as Effect.Effect<A, E, RuntimeContext>;
145
+ },
146
+ });
147
+
148
+ export const unwrapSecretValue = (value: Redacted.Redacted<string> | string): string =>
149
+ Redacted.isRedacted(value) ? Redacted.value(value) : value;