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

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 +340 -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 +59 -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 +35 -0
  176. package/lib/PostgresMigrations.d.ts.map +1 -0
  177. package/lib/PostgresMigrations.js +110 -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 +608 -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 +8 -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 +1022 -0
  240. package/lib/Service.d.ts.map +1 -0
  241. package/lib/Service.js +1397 -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 +469 -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 +87 -0
  280. package/lib/Website/Astro.d.ts.map +1 -0
  281. package/lib/Website/Astro.js +55 -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 +175 -0
  288. package/lib/Website/FrameworkSite.d.ts.map +1 -0
  289. package/lib/Website/FrameworkSite.js +162 -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 +155 -0
  312. package/lib/Website/StaticSite.d.ts.map +1 -0
  313. package/lib/Website/StaticSite.js +168 -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 +103 -0
  328. package/lib/Website/Vite.d.ts.map +1 -0
  329. package/lib/Website/Vite.js +91 -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 +458 -0
  370. package/lib/bluegreen.js.map +1 -0
  371. package/lib/hosted.d.ts +172 -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 +145 -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 +516 -0
  401. package/src/AuthProvider.ts +68 -0
  402. package/src/BindService.ts +304 -0
  403. package/src/Bootstrap.ts +66 -0
  404. package/src/Bucket.ts +916 -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 +102 -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 +1268 -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 +153 -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 +820 -0
  452. package/src/RedisBinding.ts +64 -0
  453. package/src/RedisHttp.ts +11 -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 +1934 -0
  460. package/src/Sign.ts +46 -0
  461. package/src/SignHttp.ts +44 -0
  462. package/src/Sprite.ts +671 -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 +294 -0
  469. package/src/Website/Astro.ts +87 -0
  470. package/src/Website/Foldkit.ts +54 -0
  471. package/src/Website/FrameworkSite.ts +363 -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 +275 -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 +112 -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 +708 -0
  492. package/src/globals.d.ts +2 -0
  493. package/src/hosted.ts +668 -0
  494. package/src/index.ts +64 -0
  495. package/src/internal/RemoteBuilder.ts +224 -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
package/src/Redis.ts ADDED
@@ -0,0 +1,820 @@
1
+ import type {
2
+ AddOnPlansResponseEdgesItemNode,
3
+ AddOnsResponseEdgesItemNode,
4
+ CreateAddOnResponseAddOn,
5
+ } from "@distilled.cloud/fly-io/addons";
6
+ import * as addons from "@distilled.cloud/fly-io/addons";
7
+ import * as machines from "@distilled.cloud/fly-io/machines";
8
+ import { Unowned } from "alchemy/AdoptPolicy";
9
+ import { deepEqual, isResolved } from "alchemy/Diff";
10
+ import * as Provider from "alchemy/Provider";
11
+ import { Resource } from "alchemy/Resource";
12
+ import * as Data from "effect/Data";
13
+ import * as Duration from "effect/Duration";
14
+ import * as Effect from "effect/Effect";
15
+ import * as Redacted from "effect/Redacted";
16
+ import * as Result from "effect/Result";
17
+ import * as Schedule from "effect/Schedule";
18
+ import { resolveOrgSlug } from "./Environment.ts";
19
+ import { createFlyAppName, matchesAlchemyPhysicalName, sanitizeFlyAppName } from "./Metadata.ts";
20
+ import type { Providers } from "./Providers.ts";
21
+
22
+ export const DEFAULT_REDIS_REGION = "iad";
23
+ export const REDIS_ADDON_TYPE = "upstash_redis";
24
+ export const REDIS_PROVIDER = "upstash_redis";
25
+ export const REDIS_URL_ENV = "REDIS_URL";
26
+
27
+ export {
28
+ CommandError as RedisCommandError,
29
+ UrlMissing as RedisUrlMissing,
30
+ } from "@alchemy.run/redis";
31
+
32
+ export interface RedisProps {
33
+ /**
34
+ * Upstash Redis database name. Globally unique in the org. If omitted,
35
+ * a unique name is generated from the stack, stage and logical ID.
36
+ * Changing it replaces the database.
37
+ */
38
+ name?: string;
39
+ /**
40
+ * Primary region (`iad`, `ord`, `sjc`, …). Fly cannot move a primary.
41
+ * Changing it replaces the database.
42
+ *
43
+ * @default "iad"
44
+ */
45
+ primaryRegion?: string;
46
+ /**
47
+ * Organization slug. Defaults to the current token's org. Changing it
48
+ * replaces the database.
49
+ */
50
+ orgSlug?: string;
51
+ /**
52
+ * Add-on plan id, name, or display name from `addOnPlans`. Default is
53
+ * the cheapest listed plan (free or pay-as-you-go). Fixed plans are
54
+ * billed. Default tests use the cheapest listed plan.
55
+ */
56
+ plan?: string;
57
+ /**
58
+ * Read-replica regions. Updated in place. Must not include the
59
+ * primary region.
60
+ */
61
+ readRegions?: string[];
62
+ /**
63
+ * Evict keys when memory is full (cache workload). Updated in place.
64
+ */
65
+ eviction?: boolean;
66
+ /**
67
+ * Automatically upgrade a fixed plan when hitting resource limits.
68
+ * Ignored on pay-as-you-go.
69
+ */
70
+ autoUpgrade?: boolean;
71
+ /**
72
+ * ProdPack add-on ($200/mo). Paid. Not enabled in default tests.
73
+ */
74
+ prodPack?: boolean;
75
+ }
76
+
77
+ export type Redis = Resource<
78
+ "Fly.Redis",
79
+ RedisProps,
80
+ {
81
+ /** Fly GraphQL add-on id. */
82
+ redisId: string;
83
+ /** Physical Upstash Redis name. */
84
+ name: string;
85
+ /** Primary region code. */
86
+ primaryRegion: string;
87
+ /** Observed read-replica regions. */
88
+ readRegions: string[];
89
+ /** Observed status (`ready`, `provisioning`, …). */
90
+ status: string | undefined;
91
+ /** Selected plan id, if the API returned one. */
92
+ planId: string | undefined;
93
+ /** Observed plan name (`Pay-as-you-go`, `Fixed 250MB`, …). */
94
+ planName: string | undefined;
95
+ /** Private 6PN address, if the API returned one. */
96
+ privateIp: string | undefined;
97
+ /** Organization slug. */
98
+ orgSlug: string | undefined;
99
+ /** Whether eviction is enabled. */
100
+ eviction: boolean | undefined;
101
+ /**
102
+ * Redacted Upstash connection URL. Bindings transport it to the
103
+ * runtime automatically. Service attachments also set `REDIS_URL`.
104
+ */
105
+ url: Redacted.Redacted<string> | undefined;
106
+ },
107
+ never,
108
+ Providers
109
+ >;
110
+
111
+ /**
112
+ * Managed Upstash Redis in a Fly org. Bind {@link ReadRedis},
113
+ * {@link WriteRedis}, or {@link ReadWriteRedis} on a {@link Service}.
114
+ * Alchemy transports the redacted `url` Output to the runtime client
115
+ * and also writes `REDIS_URL` as an App secret for compatibility.
116
+ * Redis is not reachable from CI — drive it over HTTP.
117
+ *
118
+ * @see https://fly.io/docs/upstash/redis/
119
+ *
120
+ * ### Create Redis
121
+ * Alchemy generates a unique name unless you pass one. Default region is
122
+ * `iad`. Default plan is the cheapest `addOnPlans` row (free or
123
+ * pay-as-you-go).
124
+ *
125
+ * **Example:** Generated name
126
+ * ```typescript
127
+ * const cache = yield* Fly.Redis("Cache");
128
+ * ```
129
+ *
130
+ * :::note
131
+ * Prefer omitting `name` in tests and CI so names stay unique and
132
+ * reclaimable.
133
+ * :::
134
+ *
135
+ * ### A stable name
136
+ * Pass `name` when you want a stable Upstash database name.
137
+ *
138
+ * **Example:** Explicit name
139
+ * ```typescript
140
+ * const cache = yield* Fly.Redis("Cache", {
141
+ * name: "my-cache",
142
+ * primaryRegion: "iad",
143
+ * });
144
+ * ```
145
+ *
146
+ * :::caution[Changing `name` replaces Redis]
147
+ * Fly cannot rename an add-on. Alchemy deletes the old database first,
148
+ * then creates the new one.
149
+ * :::
150
+ *
151
+ * :::caution[Changing `primaryRegion` replaces Redis]
152
+ * The primary region is immutable. The old database is deleted first
153
+ * because the name cannot exist twice.
154
+ * :::
155
+ *
156
+ * ### Bind from a Service
157
+ * Yield {@link ReadWriteRedis} (or {@link ReadRedis} / {@link WriteRedis})
158
+ * in Service init. Provide the matching `*Http` layer.
159
+ *
160
+ * **Example:** Read and write
161
+ * ```typescript
162
+ * import * as HttpServerResponse from "effect/http/HttpServerResponse";
163
+ *
164
+ * const Cache = Fly.Redis("Cache");
165
+ *
166
+ * export default class Api extends Fly.Service<Api>()(
167
+ * "Api",
168
+ * { app: Site, main: import.meta.url, port: 3000 },
169
+ * Effect.gen(function* () {
170
+ * const cache = yield* Fly.ReadWriteRedis(Cache);
171
+ * return {
172
+ * fetch: Effect.gen(function* () {
173
+ * yield* cache.set("marker", "hello");
174
+ * const value = yield* cache.get("marker");
175
+ * return HttpServerResponse.json({ value });
176
+ * }),
177
+ * };
178
+ * }).pipe(Effect.provide(Fly.ReadWriteRedisHttp)),
179
+ * ) {}
180
+ * ```
181
+ *
182
+ * ### Eviction
183
+ * Enable eviction for cache workloads. Updated in place.
184
+ *
185
+ * **Example:** Eviction
186
+ * ```typescript
187
+ * const cache = yield* Fly.Redis("Cache", {
188
+ * eviction: true,
189
+ * });
190
+ * ```
191
+ *
192
+ * ### Read replicas
193
+ * `readRegions` are extra replica regions. Updated in place.
194
+ *
195
+ * **Example:** Replica region
196
+ * ```typescript
197
+ * const cache = yield* Fly.Redis("Cache", {
198
+ * primaryRegion: "iad",
199
+ * readRegions: ["sjc"],
200
+ * });
201
+ * ```
202
+ *
203
+ * ### Plan
204
+ * Omit `plan` for the cheapest listed plan. Pass a plan id or display
205
+ * name to pin one. Fixed plans are billed.
206
+ *
207
+ * **Example:** Pin pay-as-you-go
208
+ * ```typescript
209
+ * const cache = yield* Fly.Redis("Cache", {
210
+ * plan: "Pay-as-you-go",
211
+ * });
212
+ * ```
213
+ *
214
+ * :::caution[Fixed plans are billed]
215
+ * Fixed plans are billed monthly. Prefer omitting `plan` unless you
216
+ * need a specific size.
217
+ * :::
218
+ *
219
+ * @resource
220
+ * @product Redis
221
+ */
222
+ export const Redis = Resource<Redis>("Fly.Redis");
223
+
224
+ export class RedisNotCreated extends Data.TaggedError("Fly.RedisNotCreated")<{
225
+ name: string;
226
+ errorMessage?: string;
227
+ }> {}
228
+
229
+ export class RedisPlanNotFound extends Data.TaggedError("Fly.RedisPlanNotFound")<{
230
+ plan: string;
231
+ }> {}
232
+
233
+ export class RedisOrgMissing extends Data.TaggedError("Fly.RedisOrgMissing")<{
234
+ orgSlug: string;
235
+ }> {}
236
+
237
+ class RedisPending extends Data.TaggedError("Fly.RedisPending")<{
238
+ redisId: string;
239
+ status: string;
240
+ }> {}
241
+
242
+ type ObservedRedis = AddOnsResponseEdgesItemNode | CreateAddOnResponseAddOn;
243
+
244
+ type RedisPlan = AddOnPlansResponseEdgesItemNode;
245
+
246
+ const backoff = Schedule.min([
247
+ Schedule.exponential(Duration.millis(500), 1.5),
248
+ Schedule.spaced(Duration.seconds(5)),
249
+ ]);
250
+
251
+ const unwrapSensitive = (
252
+ value: string | Redacted.Redacted<string> | null | undefined,
253
+ ): string | undefined => {
254
+ if (value == null) return undefined;
255
+ return Redacted.isRedacted(value) ? Redacted.value(value) : value;
256
+ };
257
+
258
+ const recordOf = (value: unknown): Record<string, unknown> => {
259
+ if (value != null && typeof value === "object" && !Array.isArray(value)) {
260
+ return { ...(value as Record<string, unknown>) };
261
+ }
262
+ return {};
263
+ };
264
+
265
+ const stringRecordOf = (value: unknown): Record<string, string> =>
266
+ Object.fromEntries(
267
+ Object.entries(recordOf(value)).flatMap(([key, item]) =>
268
+ typeof item === "string" && item.length > 0 ? [[key, item]] : [],
269
+ ),
270
+ );
271
+
272
+ const evictionOf = (options: unknown): boolean | undefined => {
273
+ const value = recordOf(options).eviction;
274
+ return typeof value === "boolean" ? value : undefined;
275
+ };
276
+
277
+ const sorted = (regions: readonly string[] | null | undefined): string[] =>
278
+ [...(regions ?? [])].sort();
279
+
280
+ const pendingStatus = (status: string | null | undefined): boolean => {
281
+ if (status == null || status.length === 0) return false;
282
+ const value = status.toLowerCase();
283
+ return (
284
+ value === "pending" || value === "provisioning" || value === "creating" || value === "launching"
285
+ );
286
+ };
287
+
288
+ const failedStatus = (status: string | null | undefined): boolean => {
289
+ if (status == null) return false;
290
+ const value = status.toLowerCase();
291
+ return value === "error" || value === "failed" || value === "destroyed";
292
+ };
293
+
294
+ const isLegacyPlanName = (plan: RedisPlan): boolean => {
295
+ const normalized = (plan.displayName ?? plan.name ?? "").toLowerCase().replaceAll(" ", "_");
296
+ return (
297
+ normalized === "pro_2k" ||
298
+ normalized === "pro_10k" ||
299
+ normalized === "starter" ||
300
+ normalized === "standard"
301
+ );
302
+ };
303
+
304
+ export const isFixedRedisPlan = (plan: Pick<RedisPlan, "name" | "displayName">): boolean => {
305
+ const display = (plan.displayName ?? "").toLowerCase();
306
+ const name = (plan.name ?? "").toLowerCase();
307
+ return display.startsWith("fixed ") || name.startsWith("flyio_fixed_");
308
+ };
309
+
310
+ const hasAlchemyMetadata = (metadata: unknown): boolean => {
311
+ const tags = stringRecordOf(metadata);
312
+ const stack = tags["alchemy::stack"] ?? tags["alchemy.stack"];
313
+ return stack !== undefined && stack.length > 0;
314
+ };
315
+
316
+ const isOwnedRedis = (row: ObservedRedis): boolean =>
317
+ matchesAlchemyPhysicalName(row.name ?? undefined) || hasAlchemyMetadata(row.metadata);
318
+
319
+ const resolveName = (id: string, name: string | undefined, existing?: string) =>
320
+ Effect.gen(function* () {
321
+ if (name !== undefined) return sanitizeFlyAppName(name);
322
+ if (existing !== undefined) return existing;
323
+ return yield* createFlyAppName(id);
324
+ });
325
+
326
+ const urlOf = (
327
+ row: ObservedRedis,
328
+ previous?: Redacted.Redacted<string>,
329
+ ): Redacted.Redacted<string> | undefined => {
330
+ const raw = unwrapSensitive(row.publicUrl);
331
+ if (raw !== undefined && raw.length > 0) return Redacted.make(raw);
332
+ return previous;
333
+ };
334
+
335
+ const toAttrs = (
336
+ row: ObservedRedis,
337
+ fallback: {
338
+ name: string;
339
+ primaryRegion: string;
340
+ orgSlug?: string;
341
+ planId?: string;
342
+ url?: Redacted.Redacted<string>;
343
+ },
344
+ ): Redis["Attributes"] => ({
345
+ redisId: row.id,
346
+ name: row.name ?? fallback.name,
347
+ primaryRegion: row.primaryRegion ?? fallback.primaryRegion,
348
+ readRegions: sorted(row.readRegions),
349
+ status: row.status ?? undefined,
350
+ planId:
351
+ "addOnPlan" in row
352
+ ? ((row.addOnPlan as { id?: string } | null | undefined)?.id ?? fallback.planId)
353
+ : fallback.planId,
354
+ planName: row.addOnPlanName ?? undefined,
355
+ privateIp: row.privateIp ?? undefined,
356
+ orgSlug:
357
+ "organization" in row
358
+ ? ((row.organization as { slug?: string | null } | undefined)?.slug ?? fallback.orgSlug)
359
+ : fallback.orgSlug,
360
+ eviction: evictionOf(row.options),
361
+ url: urlOf(row, fallback.url),
362
+ });
363
+
364
+ export const listRedisAddOns = Effect.fn(function* () {
365
+ const rows: AddOnsResponseEdgesItemNode[] = [];
366
+ let after: string | undefined;
367
+ for (let i = 0; i < 8; i++) {
368
+ const page = yield* addons.addOns({
369
+ type: REDIS_ADDON_TYPE,
370
+ first: 50,
371
+ after,
372
+ });
373
+ for (const edge of page.edges ?? []) {
374
+ if (edge?.node != null) rows.push(edge.node);
375
+ }
376
+ if (!page.pageInfo.hasNextPage) break;
377
+ after = page.pageInfo.endCursor ?? undefined;
378
+ if (after === undefined || after.length === 0) break;
379
+ }
380
+ return rows;
381
+ });
382
+
383
+ export const listRedisPlans = Effect.fn(function* () {
384
+ const rows: RedisPlan[] = [];
385
+ let after: string | undefined;
386
+ for (let i = 0; i < 4; i++) {
387
+ const page = yield* addons.addOnPlans({
388
+ type: REDIS_ADDON_TYPE,
389
+ first: 50,
390
+ after,
391
+ });
392
+ for (const edge of page.edges ?? []) {
393
+ if (edge?.node != null) rows.push(edge.node);
394
+ }
395
+ if (!page.pageInfo.hasNextPage) break;
396
+ after = page.pageInfo.endCursor ?? undefined;
397
+ if (after === undefined || after.length === 0) break;
398
+ }
399
+ return rows;
400
+ });
401
+
402
+ export const findRedisAddOn = (input: { id?: string; name?: string }) =>
403
+ listRedisAddOns().pipe(
404
+ Effect.map((rows) =>
405
+ rows.find((row) => {
406
+ if (input.id !== undefined && row.id === input.id) return true;
407
+ if (input.name !== undefined && row.name === input.name) return true;
408
+ return false;
409
+ }),
410
+ ),
411
+ );
412
+
413
+ const cheapestPlan = (plans: RedisPlan[]) => {
414
+ const usable = plans.filter((plan) => !isLegacyPlanName(plan));
415
+ const pool = usable.length > 0 ? usable : plans;
416
+ if (pool.length === 0) return undefined;
417
+ const free = pool.filter((plan) => (plan.pricePerMonth ?? 0) === 0);
418
+ const ranked = (free.length > 0 ? free : pool).slice().sort((left, right) => {
419
+ const byPrice = (left.pricePerMonth ?? 0) - (right.pricePerMonth ?? 0);
420
+ if (byPrice !== 0) return byPrice;
421
+ return (left.displayName ?? left.name ?? "").localeCompare(
422
+ right.displayName ?? right.name ?? "",
423
+ );
424
+ });
425
+ const payg = ranked.find((plan) =>
426
+ /pay.?as.?you.?go|free/i.test(`${plan.displayName ?? ""} ${plan.name ?? ""}`),
427
+ );
428
+ return payg ?? ranked[0];
429
+ };
430
+
431
+ const resolvePlan = (plan: string | undefined, existingId: string | undefined) =>
432
+ Effect.gen(function* () {
433
+ const plans = yield* listRedisPlans();
434
+ if (plan !== undefined) {
435
+ const found = plans.find(
436
+ (item) => item.id === plan || item.name === plan || item.displayName === plan,
437
+ );
438
+ if (found === undefined) {
439
+ return yield* new RedisPlanNotFound({ plan });
440
+ }
441
+ return found;
442
+ }
443
+ if (existingId !== undefined) {
444
+ const existing = plans.find((item) => item.id === existingId);
445
+ if (existing !== undefined) return existing;
446
+ }
447
+ const cheapest = cheapestPlan(plans);
448
+ if (cheapest === undefined) {
449
+ return yield* new RedisPlanNotFound({ plan: "default" });
450
+ }
451
+ return cheapest;
452
+ });
453
+
454
+ const resolveOrganization = (orgSlug: string) =>
455
+ addons
456
+ .organization({ slug: orgSlug })
457
+ .pipe(Effect.catchTag("FlyIoParseError", () => Effect.succeed(undefined)));
458
+
459
+ const ensureTos = (orgSlug: string, organizationId: string) =>
460
+ Effect.gen(function* () {
461
+ const agreed = yield* addons.agreedToProviderTos({
462
+ slug: orgSlug,
463
+ providerName: REDIS_PROVIDER,
464
+ });
465
+ if (agreed === true) return;
466
+ // Tokens without org-admin cannot write the ToS row. Create still
467
+ // succeeds when the org already agreed via flyctl.
468
+ yield* Effect.result(
469
+ addons.createExtensionTosAgreement({
470
+ input: {
471
+ addOnProviderName: REDIS_PROVIDER,
472
+ organizationId,
473
+ },
474
+ }),
475
+ );
476
+ });
477
+
478
+ const waitUntilReady = (id: string, name: string) =>
479
+ findRedisAddOn({ id, name }).pipe(
480
+ Effect.flatMap(
481
+ (row): Effect.Effect<AddOnsResponseEdgesItemNode, RedisPending | RedisNotCreated> => {
482
+ if (row === undefined) {
483
+ return Effect.fail(new RedisPending({ redisId: id, status: "missing" }));
484
+ }
485
+ if (failedStatus(row.status)) {
486
+ return Effect.fail(
487
+ new RedisNotCreated({
488
+ name: row.name ?? name,
489
+ errorMessage: row.errorMessage ?? row.status ?? undefined,
490
+ }),
491
+ );
492
+ }
493
+ if (pendingStatus(row.status)) {
494
+ return Effect.fail(
495
+ new RedisPending({
496
+ redisId: id,
497
+ status: row.status ?? "provisioning",
498
+ }),
499
+ );
500
+ }
501
+ return Effect.succeed(row);
502
+ },
503
+ ),
504
+ Effect.retry({
505
+ while: (error) => error._tag === "Fly.RedisPending",
506
+ times: 10,
507
+ schedule: backoff,
508
+ }),
509
+ Effect.catchTag("Fly.RedisPending", () => findRedisAddOn({ id, name })),
510
+ );
511
+
512
+ const waitUntilGone = (id: string, name: string) =>
513
+ findRedisAddOn({ id, name }).pipe(
514
+ Effect.map((row) => row === undefined),
515
+ Effect.repeat({
516
+ schedule: Schedule.spaced("2 seconds"),
517
+ until: (gone) => gone,
518
+ times: 10,
519
+ }),
520
+ );
521
+
522
+ const desiredOptions = (
523
+ props: RedisProps,
524
+ plan: RedisPlan,
525
+ observed: unknown | undefined,
526
+ ): Record<string, unknown> => {
527
+ const options = recordOf(observed);
528
+ if (props.eviction !== undefined) options.eviction = props.eviction;
529
+ if (isFixedRedisPlan(plan)) {
530
+ if (props.autoUpgrade !== undefined) {
531
+ options.auto_upgrade = props.autoUpgrade;
532
+ }
533
+ } else {
534
+ delete options.auto_upgrade;
535
+ }
536
+ delete options.prod_pack;
537
+ return options;
538
+ };
539
+
540
+ class RedisSecretVersionMissing extends Data.TaggedError("Fly.RedisSecretVersionMissing")<{
541
+ appName: string;
542
+ }> {}
543
+
544
+ const redisSecretVersion = (
545
+ appName: string,
546
+ response: machines.AppSecretsUpdateResp | machines.SetAppSecretResponse,
547
+ ) => {
548
+ const version = response.version ?? response.Version;
549
+ return version !== undefined && Number.isSafeInteger(version) && version >= 0
550
+ ? Effect.succeed(version)
551
+ : Effect.fail(new RedisSecretVersionMissing({ appName }));
552
+ };
553
+
554
+ /**
555
+ * Write `REDIS_URL` onto an App from attached Redis add-on names.
556
+ * Called from {@link Service} reconcile so the secret exists before
557
+ * Machines boot. Returns the highest accepted secret-version floor, or
558
+ * `undefined` when no secret was written; this is not a vault snapshot.
559
+ */
560
+ export const attachRedisSecrets = Effect.fn(function* (
561
+ appName: string,
562
+ attached: readonly { name: string; id?: string }[],
563
+ ) {
564
+ if (appName.length === 0 || attached.length === 0) return undefined;
565
+ const versions: number[] = [];
566
+ for (const item of attached) {
567
+ const name = item.name;
568
+ const id = item.id;
569
+ if (name.length === 0 && (id === undefined || id.length === 0)) continue;
570
+ const row = yield* findRedisAddOn({ id, name }).pipe(
571
+ Effect.flatMap((found) =>
572
+ found === undefined
573
+ ? Effect.fail(
574
+ new RedisPending({
575
+ redisId: id ?? "",
576
+ status: "missing",
577
+ }),
578
+ )
579
+ : Effect.succeed(found),
580
+ ),
581
+ Effect.retry({
582
+ while: (error) => error._tag === "Fly.RedisPending",
583
+ times: 8,
584
+ schedule: backoff,
585
+ }),
586
+ Effect.catchTag("Fly.RedisPending", () => findRedisAddOn({ id, name })),
587
+ );
588
+ if (row === undefined) {
589
+ return yield* new RedisPending({
590
+ redisId: id ?? name,
591
+ status: "missing",
592
+ });
593
+ }
594
+ let url = unwrapSensitive(row.publicUrl);
595
+ if ((url === undefined || url.length === 0) && row.id !== undefined) {
596
+ const detail = yield* addons
597
+ .addOn({ id: row.id })
598
+ .pipe(Effect.catchTag("FlyIoParseError", () => Effect.succeed(undefined)));
599
+ url = unwrapSensitive(detail?.publicUrl);
600
+ }
601
+ if (url === undefined || url.length === 0) {
602
+ return yield* new RedisPending({
603
+ redisId: row.id ?? id ?? name,
604
+ status: "credentials missing",
605
+ });
606
+ }
607
+ const value = url;
608
+ const update = machines
609
+ .updateSecrets({
610
+ app_name: appName,
611
+ values: { [REDIS_URL_ENV]: value },
612
+ })
613
+ .pipe(Effect.flatMap((response) => redisSecretVersion(appName, response)));
614
+ const version = yield* update.pipe(
615
+ Effect.catchTag("NotFound", () =>
616
+ machines
617
+ .createSecret({
618
+ app_name: appName,
619
+ secret_name: REDIS_URL_ENV,
620
+ value,
621
+ })
622
+ .pipe(
623
+ Effect.flatMap((response) => redisSecretVersion(appName, response)),
624
+ Effect.catchTag("Conflict", () => update),
625
+ ),
626
+ ),
627
+ );
628
+ versions.push(version);
629
+ }
630
+ return versions.length > 0 ? Math.max(...versions) : undefined;
631
+ });
632
+
633
+ export const RedisProvider = () =>
634
+ Provider.succeed(Redis, {
635
+ stables: ["redisId", "name", "primaryRegion", "orgSlug"],
636
+
637
+ diff: Effect.fn(function* ({ news, output }) {
638
+ if (news === undefined || !isResolved(news)) return undefined;
639
+ if (output === undefined) return undefined;
640
+ const desiredName = news.name !== undefined ? sanitizeFlyAppName(news.name) : output.name;
641
+ const nameChanged = desiredName !== output.name;
642
+ const desiredRegion = news.primaryRegion ?? DEFAULT_REDIS_REGION;
643
+ const regionChanged = desiredRegion !== output.primaryRegion;
644
+ const orgChanged = news.orgSlug !== undefined && news.orgSlug !== output.orgSlug;
645
+ if (nameChanged || regionChanged || orgChanged) {
646
+ return {
647
+ action: "replace" as const,
648
+ deleteFirst: !nameChanged,
649
+ };
650
+ }
651
+ return undefined;
652
+ }),
653
+
654
+ read: Effect.fn(function* ({ id, olds, output }) {
655
+ const name = yield* resolveName(id, olds?.name, output?.name);
656
+ const found =
657
+ (output?.redisId !== undefined
658
+ ? yield* findRedisAddOn({ id: output.redisId, name: output.name })
659
+ : undefined) ?? (yield* findRedisAddOn({ name }));
660
+ if (found === undefined) return undefined;
661
+ const attrs = toAttrs(found, {
662
+ name,
663
+ primaryRegion: olds?.primaryRegion ?? DEFAULT_REDIS_REGION,
664
+ orgSlug: olds?.orgSlug ?? output?.orgSlug,
665
+ url: output?.url,
666
+ });
667
+ if (output !== undefined) return attrs;
668
+ return isOwnedRedis(found) ? attrs : Unowned(attrs);
669
+ }),
670
+
671
+ list: Effect.fn(function* () {
672
+ const rows = yield* listRedisAddOns();
673
+ return rows.flatMap((row) => {
674
+ if (!isOwnedRedis(row)) return [];
675
+ const name = row.name;
676
+ if (name == null || name.length === 0) return [];
677
+ return [
678
+ toAttrs(row, {
679
+ name,
680
+ primaryRegion: row.primaryRegion ?? DEFAULT_REDIS_REGION,
681
+ }),
682
+ ];
683
+ });
684
+ }),
685
+
686
+ reconcile: Effect.fn(function* ({ id, news, output }) {
687
+ const props = news ?? {};
688
+ const name = yield* resolveName(id, props.name, output?.name);
689
+ const primaryRegion = props.primaryRegion ?? output?.primaryRegion ?? DEFAULT_REDIS_REGION;
690
+ const orgSlug = props.orgSlug ?? (yield* resolveOrgSlug());
691
+ const org = yield* resolveOrganization(orgSlug);
692
+ if (org === undefined) {
693
+ return yield* new RedisOrgMissing({ orgSlug });
694
+ }
695
+
696
+ let current: ObservedRedis | undefined =
697
+ output?.redisId !== undefined
698
+ ? yield* findRedisAddOn({
699
+ id: output.redisId,
700
+ name: output.name,
701
+ })
702
+ : undefined;
703
+ if (current === undefined && (output === undefined || output.name !== name)) {
704
+ current = yield* findRedisAddOn({ name });
705
+ }
706
+
707
+ const plan = yield* resolvePlan(
708
+ props.plan,
709
+ current !== undefined && "addOnPlan" in current ? current.addOnPlan?.id : output?.planId,
710
+ );
711
+
712
+ if (current === undefined) {
713
+ yield* ensureTos(orgSlug, org.id);
714
+ const created = yield* Effect.result(
715
+ addons.createAddOn({
716
+ input: {
717
+ type: REDIS_ADDON_TYPE,
718
+ name,
719
+ organizationId: org.id,
720
+ planId: plan.id,
721
+ primaryRegion,
722
+ readRegions: props.readRegions ?? [],
723
+ options: desiredOptions(props, plan, undefined),
724
+ },
725
+ }),
726
+ );
727
+ if (Result.isSuccess(created)) {
728
+ current = created.success.addOn;
729
+ } else {
730
+ current = yield* findRedisAddOn({ name });
731
+ if (current === undefined) {
732
+ return yield* created.failure;
733
+ }
734
+ }
735
+ }
736
+
737
+ if (current === undefined) {
738
+ return yield* new RedisNotCreated({ name });
739
+ }
740
+
741
+ if (pendingStatus(current.status)) {
742
+ const ready = yield* waitUntilReady(current.id, name);
743
+ if (ready !== undefined) current = ready;
744
+ }
745
+
746
+ if (current === undefined) {
747
+ return yield* new RedisNotCreated({ name });
748
+ }
749
+
750
+ const observedOptions = recordOf(current.options);
751
+ const nextOptions = desiredOptions(props, plan, current.options);
752
+ const nextReadRegions = sorted(props.readRegions ?? current.readRegions ?? []);
753
+ const observedReadRegions = sorted(current.readRegions);
754
+ const observedPlanId = "addOnPlan" in current ? current.addOnPlan?.id : output?.planId;
755
+ const planChanged = observedPlanId !== undefined && observedPlanId !== plan.id;
756
+ const regionsChanged = !deepEqual(observedReadRegions, nextReadRegions);
757
+ const optionsChanged = !deepEqual(observedOptions, nextOptions);
758
+ const prodPackChanged = props.prodPack !== undefined && planChanged;
759
+
760
+ if (planChanged || regionsChanged || optionsChanged || prodPackChanged) {
761
+ const updated = yield* Effect.result(
762
+ addons.updateAddOn({
763
+ input: {
764
+ addOnId: current.id,
765
+ planId: plan.id,
766
+ readRegions: nextReadRegions,
767
+ options: nextOptions,
768
+ prodPack: prodPackChanged ? props.prodPack : undefined,
769
+ },
770
+ }),
771
+ );
772
+ if (Result.isSuccess(updated)) {
773
+ current = {
774
+ ...current,
775
+ ...updated.success.addOn,
776
+ };
777
+ } else {
778
+ const refreshed = yield* findRedisAddOn({
779
+ id: current.id,
780
+ name,
781
+ });
782
+ if (refreshed !== undefined) current = refreshed;
783
+ }
784
+ }
785
+
786
+ let latest = (yield* findRedisAddOn({ id: current.id, name })) ?? current;
787
+ if (unwrapSensitive(latest.publicUrl) === undefined && latest.id !== undefined) {
788
+ const detail = yield* addons.addOn({ id: latest.id });
789
+ latest = { ...latest, ...detail };
790
+ }
791
+ return toAttrs(latest, {
792
+ name,
793
+ primaryRegion,
794
+ orgSlug,
795
+ planId: plan.id,
796
+ url: output?.url,
797
+ });
798
+ }),
799
+
800
+ delete: Effect.fn(function* ({ output }) {
801
+ const redisId = output.redisId;
802
+ const name = output.name;
803
+ if (redisId.length === 0 && (name === undefined || name.length === 0)) {
804
+ return;
805
+ }
806
+ const deleted = yield* Effect.result(
807
+ addons.deleteAddOn({
808
+ input: redisId.length > 0 ? { addOnId: redisId } : { name, provider: REDIS_PROVIDER },
809
+ }),
810
+ );
811
+ if (Result.isFailure(deleted)) {
812
+ const still = yield* findRedisAddOn({ id: redisId, name });
813
+ if (still !== undefined) {
814
+ return yield* deleted.failure;
815
+ }
816
+ return;
817
+ }
818
+ yield* waitUntilGone(redisId, name);
819
+ }),
820
+ });