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