@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/Machine.ts ADDED
@@ -0,0 +1,1270 @@
1
+ import type {
2
+ FlyMachineConfig,
3
+ FlyMachineGuest,
4
+ FlyMachineInit,
5
+ FlyMachineMount,
6
+ FlyMachineRestart,
7
+ FlyMachineService,
8
+ Machine as FlyMachine,
9
+ } from "@distilled.cloud/fly-io/machines";
10
+ import { deepEqual, isResolved } from "alchemy/Diff";
11
+ import type { Input } from "alchemy/Input";
12
+ import * as Provider from "alchemy/Provider";
13
+ import { Resource, type ResourceBinding } from "alchemy/Resource";
14
+ import * as Data from "effect/Data";
15
+ import * as Effect from "effect/Effect";
16
+ import { App } from "./App.ts";
17
+ import {
18
+ deploymentPolicy,
19
+ validateDeployment,
20
+ type MachineDeploy,
21
+ type MachineShutdown,
22
+ type MachineCheck,
23
+ } from "./Deployment.ts";
24
+ import { toEnvRecord } from "./hosted.ts";
25
+ import {
26
+ sameContainerWorkload,
27
+ toFlyContainers,
28
+ validateMachineContainers,
29
+ } from "./MachineContainers.ts";
30
+ import { createFlyResourceName, diffMachineMetadata, sanitizeFlyAppName } from "./Metadata.ts";
31
+ import type { DiskSpec, MountedDisk, ServiceBinding } from "./MountVolume.ts";
32
+ import type { Providers } from "./Providers.ts";
33
+ import {
34
+ deleteReplicaSet,
35
+ listReplicaSets,
36
+ observeReplicaSet,
37
+ reconcileReplicas,
38
+ resolveCount,
39
+ sameServices,
40
+ toFlyService,
41
+ volumeIdsOf,
42
+ type Replica,
43
+ type ReplicaSet,
44
+ } from "./replicas.ts";
45
+
46
+ export type { Replica };
47
+
48
+ const DEFAULT_REGION = "iad";
49
+ const DEFAULT_CPU_KIND = "shared";
50
+ const DEFAULT_CPUS = 1;
51
+ const DEFAULT_MEMORY_MB = 256;
52
+
53
+ /**
54
+ * A resource-valued prop: the resource itself, or an Effect that produces
55
+ * it (so `yield* App(...)` and `App(...)` both type-check).
56
+ */
57
+ type Ref<T> = T | Effect.Effect<T, never, Providers>;
58
+
59
+ export interface MachineGuest {
60
+ /**
61
+ * CPU kind (`shared`, `performance`, `shared-cpu-1x`, …).
62
+ *
63
+ * @default "shared"
64
+ */
65
+ cpuKind?: string;
66
+ /**
67
+ * Number of CPUs.
68
+ *
69
+ * @default 1
70
+ */
71
+ cpus?: number;
72
+ /**
73
+ * Memory in MB.
74
+ *
75
+ * @default 256
76
+ */
77
+ memoryMb?: number;
78
+ /** GPU kind, if this Machine should have a GPU. */
79
+ gpuKind?: string;
80
+ /** Number of GPUs. */
81
+ gpus?: number;
82
+ }
83
+
84
+ export interface MachineInit {
85
+ /** Process command. */
86
+ cmd?: string[];
87
+ /** Container entrypoint. */
88
+ entrypoint?: string[];
89
+ /** Exec form override. */
90
+ exec?: string[];
91
+ /** Swap size in MB. */
92
+ swapSizeMb?: number;
93
+ /** Allocate a TTY. */
94
+ tty?: boolean;
95
+ }
96
+
97
+ export interface MachineRestart {
98
+ /**
99
+ * Restart policy (`no`, `always`, `on-failure`, `spot-price`).
100
+ */
101
+ policy?: "no" | "always" | "on-failure" | "spot-price";
102
+ /** Max restarts when `policy` is `on-failure`. */
103
+ maxRetries?: number;
104
+ }
105
+
106
+ export interface MachinePort {
107
+ /** Published proxy port. */
108
+ port?: number;
109
+ /** Fly handlers (`http`, `tls`, `pg_tls`, …). */
110
+ handlers?: string[];
111
+ /** Redirect HTTP to HTTPS on this port. */
112
+ forceHttps?: boolean;
113
+ /** Inclusive start of a published port range. */
114
+ startPort?: number;
115
+ /** Inclusive end of a published port range. */
116
+ endPort?: number;
117
+ }
118
+
119
+ /** A health check attached to a Fly service. */
120
+ export interface MachineServiceCheck {
121
+ /** Check type. HTTP checks send a request; TCP checks open a connection. */
122
+ type: "http" | "tcp";
123
+ /** Port to check. Usually the service's {@link MachineService.internalPort}. */
124
+ port?: number;
125
+ /**
126
+ * Time between checks, such as `"15s"`.
127
+ * Fly caps service checks at `"60s"`; this cap does not apply to named Machine checks.
128
+ */
129
+ interval?: string;
130
+ /** Maximum time for a check, such as `"2s"`. */
131
+ timeout?: string;
132
+ /** Delay after the Machine starts before checks begin, such as `"30s"`. */
133
+ gracePeriod?: string;
134
+ /** HTTP method for an `http` check. */
135
+ method?: string;
136
+ /** Request path for an `http` check. */
137
+ path?: string;
138
+ /** Request protocol for an `http` check. */
139
+ protocol?: "http" | "https";
140
+ /** Headers sent by an `http` check. */
141
+ headers?: Array<{
142
+ /** Header name. */
143
+ name: string;
144
+ /** Header values. */
145
+ values: string[];
146
+ }>;
147
+ /** Hostname used to validate the certificate for an HTTPS check. */
148
+ tlsServerName?: string;
149
+ /** Skip certificate verification for an HTTPS check. */
150
+ tlsSkipVerify?: boolean;
151
+ }
152
+
153
+ export interface MachineService {
154
+ /**
155
+ * Proxy protocol (`tcp` or `udp`).
156
+ */
157
+ protocol?: string;
158
+ /** Port the process listens on inside the Machine. */
159
+ internalPort?: number;
160
+ /** Published Fly proxy ports. */
161
+ ports?: MachinePort[];
162
+ /** Start this Machine when a request arrives. */
163
+ autostart?: boolean;
164
+ /**
165
+ * Stop or suspend this Machine when idle.
166
+ */
167
+ autostop?: "off" | "stop" | "suspend" | boolean;
168
+ /** Minimum Machines to keep running for this service. */
169
+ minMachinesRunning?: number;
170
+ /** Health checks for this service. */
171
+ checks?: MachineServiceCheck[];
172
+ }
173
+
174
+ export type MachineMount = DiskSpec;
175
+
176
+ /** Startup dependency on another named container in the same Machine. */
177
+ export interface MachineContainerDependency {
178
+ /** Name of another container in this Machine. */
179
+ name: string;
180
+ /** Startup condition Fly waits for. */
181
+ condition?: "started" | "healthy" | "exited_successfully";
182
+ }
183
+
184
+ /** A native Pilot health check; timing fields are numeric seconds. */
185
+ export interface MachineContainerHealthCheck {
186
+ /** Optional check name, unique within this container. */
187
+ name?: string;
188
+ /** Whether the check gates readiness or liveness. */
189
+ kind?: "readiness" | "liveness";
190
+ /** Seconds between checks. */
191
+ interval?: number;
192
+ /** Seconds before a check times out. */
193
+ timeout?: number;
194
+ /** Seconds after startup before checks begin. */
195
+ gracePeriod?: number;
196
+ /** Consecutive successes required to become healthy. */
197
+ successThreshold?: number;
198
+ /** Consecutive failures required to become unhealthy. */
199
+ failureThreshold?: number;
200
+ /** HTTP probe. Configure exactly one of HTTP, TCP, or exec. */
201
+ http?: {
202
+ /** Container-local port. */
203
+ port: number;
204
+ /** Request path. */
205
+ path?: string;
206
+ /** Request method. */
207
+ method?: string;
208
+ /** Request scheme. */
209
+ scheme?: "http" | "https";
210
+ /** Additional request headers. */
211
+ headers?: Array<{ name: string; values: string[] }>;
212
+ /** Hostname for TLS certificate verification. */
213
+ tlsServerName?: string;
214
+ /** Skip TLS certificate verification. */
215
+ tlsSkipVerify?: boolean;
216
+ };
217
+ /** TCP connection probe. */
218
+ tcp?: { port: number };
219
+ /** Process execution probe. */
220
+ exec?: { command: string[] };
221
+ }
222
+
223
+ /** One named container in a Machine replica. */
224
+ export interface MachineContainer {
225
+ /** Stable name identifying this container within the group. */
226
+ name: string;
227
+ /** Docker image reference. Rolling deployments accept tags or digests. */
228
+ image: string;
229
+ /** Command override. */
230
+ cmd?: string[];
231
+ /** Entrypoint override. */
232
+ entrypoint?: string[];
233
+ /** Per-container environment variables; Fly applies these over Machine env. */
234
+ env?: Record<string, string>;
235
+ /** Other named containers that must reach a startup condition first. */
236
+ dependsOn?: MachineContainerDependency[];
237
+ /** Native Pilot checks for this container. Deployment readiness is configured separately. */
238
+ healthChecks?: MachineContainerHealthCheck[];
239
+ }
240
+
241
+ export interface MachinePropsBase {
242
+ /** Deployment strategy and readiness deadline. Defaults to in-place rolling updates. */
243
+ deploy?: MachineDeploy;
244
+ /** Graceful process shutdown. Defaults to SIGTERM / 30 seconds when blue/green is enabled. */
245
+ shutdown?: MachineShutdown;
246
+ /** Named readiness checks for workers without public services. */
247
+ checks?: Record<string, MachineCheck>;
248
+ /**
249
+ * Parent Fly App. Changing it replaces the Machine.
250
+ */
251
+ app: Ref<App>;
252
+ /**
253
+ * Machine name. Unique per App. If omitted, a unique name is generated
254
+ * from the stack, stage and logical ID. Changing it replaces the Machine.
255
+ * In blue/green mode this is a base for generation-qualified physical names.
256
+ */
257
+ name?: string;
258
+ /**
259
+ * Region to start the Machine in (`iad`, `ewr`, `ord`, …). Changing it
260
+ * replaces the Machine.
261
+ *
262
+ * @default "iad"
263
+ */
264
+ region?: string;
265
+ /**
266
+ * Number of Machines to provision, including stopped/suspended idle capacity.
267
+ * Fly's proxy load-balances published `services` across available replicas.
268
+ * Blue/green checks a representative and the required running floor while
269
+ * preserving idle nonrepresentatives. Each replica gets its own Volume
270
+ * from every {@link mounts} group; attached volumes require rolling updates.
271
+ *
272
+ * @default 1
273
+ */
274
+ count?: number;
275
+ /**
276
+ * Guest size. Defaults to shared-cpu-1x 256 MB.
277
+ */
278
+ guest?: MachineGuest;
279
+ /**
280
+ * Environment variables. Merged with binding `env`.
281
+ */
282
+ env?: Record<string, string>;
283
+ /**
284
+ * Fly proxy services (HTTP/TCP ports).
285
+ */
286
+ services?: MachineService[];
287
+ /**
288
+ * Disks to attach. Each entry is a Fly volume group: `count`
289
+ * independent Volumes, one mounted on each replica. Also collected
290
+ * from `MountVolume` bindings.
291
+ */
292
+ mounts?: MachineMount[];
293
+ /**
294
+ * User metadata. Alchemy ownership keys (`alchemy.stack` /
295
+ * `alchemy.stage` / `alchemy.id` / `alchemy.type` /
296
+ * `alchemy.replica`) are always merged.
297
+ */
298
+ metadata?: Record<string, string>;
299
+ /**
300
+ * Destroy the Machine when its main process exits.
301
+ *
302
+ * @default false
303
+ */
304
+ autoDestroy?: boolean;
305
+ /**
306
+ * Restart policy after the main process exits.
307
+ */
308
+ restart?: MachineRestart;
309
+ /**
310
+ * Create or update without launching the Machine.
311
+ *
312
+ * @default false
313
+ */
314
+ skipLaunch?: boolean;
315
+ /**
316
+ * Minimum App-secrets version required by this Machine, not an immutable
317
+ * snapshot. Other writers can advance the shared vault. Secret changes are
318
+ * not automatically watched; change an explicit deployment input or floor
319
+ * when an out-of-band rotation requires reconciliation.
320
+ */
321
+ minSecretsVersion?: number;
322
+ }
323
+
324
+ export type MachineProps =
325
+ | (MachinePropsBase & {
326
+ /** Docker image reference. Rolling updates change the existing Machines. */
327
+ image: string;
328
+ containers?: never;
329
+ /** Process init overrides for a single-image Machine. */
330
+ init?: MachineInit;
331
+ })
332
+ | (MachinePropsBase & {
333
+ /** Named containers run together in every Machine replica. */
334
+ containers: MachineContainer[];
335
+ image?: never;
336
+ init?: never;
337
+ });
338
+
339
+ export type MachineImageRef = {
340
+ registry?: string;
341
+ repository?: string;
342
+ tag?: string;
343
+ digest?: string;
344
+ };
345
+
346
+ export type Machine = Resource<
347
+ "Fly.Machine",
348
+ MachineProps,
349
+ {
350
+ /** Whether recovery must finish an interrupted deployment. */
351
+ rolloutPending?: boolean;
352
+ /** Parent Fly App name. */
353
+ appName: string;
354
+ /** Fly Machine id of replica 0. */
355
+ machineId: string;
356
+ /** Fly Machine ids of every replica. */
357
+ machineIds: string[];
358
+ /** Logical base for generation-qualified Machine names. */
359
+ baseName?: string;
360
+ /** Machine name of replica 0 (unique per App). Changes during blue/green deployment. */
361
+ name: string;
362
+ /** Region the Machines are running in. */
363
+ region: string;
364
+ /** Observed state of replica 0 (`created`, `started`, `stopped`, …). */
365
+ state: string;
366
+ /** Fly instance / version id of replica 0, if the API returned one. */
367
+ instanceId: string | undefined;
368
+ /** Internal 6PN address of replica 0. */
369
+ privateIp: string | undefined;
370
+ /** Parsed image reference from Fly. */
371
+ imageRef: MachineImageRef | undefined;
372
+ /** Observed guest size. */
373
+ guest: MachineGuest | undefined;
374
+ /** Number of Machines in the replica set. */
375
+ count: number;
376
+ /** Disks mounted on replica 0. */
377
+ mounts: MountedDisk[];
378
+ /** Every replica in the set. */
379
+ replicas: Replica[];
380
+ },
381
+ ServiceBinding,
382
+ Providers
383
+ >;
384
+
385
+ /**
386
+ * A Fly.Machine is a Firecracker VM running one image or a named container group.
387
+ *
388
+ * Prefer a {@link Service} when the program is Effect. A Service is effectful, supports bindings,
389
+ * and scales with `count`. Alchemy builds and pushes the image. Use `Fly.Machine` when you already
390
+ * have an image.
391
+ *
392
+ * @see https://fly.io/docs/machines/api/machines-resource/
393
+ *
394
+ * ### Prefer a Service
395
+ * Declare a {@link Service} when you own the program. Alchemy bundles
396
+ * `main`, builds `linux/amd64`, and pushes to `registry.fly.io`.
397
+ *
398
+ * **Example:** Effect HTTP service
399
+ * ```typescript
400
+ * export default class Api extends Fly.Service<Api>()(
401
+ * "Api",
402
+ * { app: Site, main: import.meta.url, region: "iad", count: 3, port: 3000 },
403
+ * Effect.gen(function* () {
404
+ * return {
405
+ * fetch: Effect.succeed(HttpServerResponse.text("hello")),
406
+ * };
407
+ * }),
408
+ * ) {}
409
+ * ```
410
+ *
411
+ * ### Launch a Machine
412
+ * The parent is an {@link App}. Pin a region and an image. Guest
413
+ * defaults to shared-cpu 1× / 256 MB. Rolling updates `image` in place;
414
+ * blue/green prepares replacement Machines.
415
+ *
416
+ * **Example:** Nginx
417
+ * ```typescript
418
+ * const web = yield* Fly.Machine("Web", {
419
+ * app: Site,
420
+ * region: "iad",
421
+ * image: "nginx:alpine",
422
+ * });
423
+ * ```
424
+ *
425
+ * :::caution[Changing `app` replaces the Machine]
426
+ * The new App gets a new Machine. The old one is deleted.
427
+ * :::
428
+ *
429
+ * ### Run named containers
430
+ * Each replica contains the entire group. Container checks and dependencies
431
+ * control Pilot startup; configure Machine or service checks for deployment
432
+ * readiness. Rolling updates can restart the entire group when one image
433
+ * changes. Blue/green requires every named image to use an immutable
434
+ * `repository@sha256:` digest and cannot attach volumes. Alchemy replaces
435
+ * the entire group and applies readiness policy before retiring predecessors.
436
+ *
437
+ * **Example:** API and worker
438
+ * ```typescript
439
+ * const preview = yield* Fly.Machine("Preview", {
440
+ * app: Site,
441
+ * containers: [
442
+ * { name: "api", image: apiImage, healthChecks: [{ http: { port: 3000, path: "/health" } }] },
443
+ * { name: "worker", image: workerImage, dependsOn: [{ name: "api", condition: "healthy" }] },
444
+ * ],
445
+ * });
446
+ * ```
447
+ *
448
+ * ### A stable name
449
+ * Machine names are unique per App. Omit `name` and Alchemy generates
450
+ * one from the stack, stage, and logical ID.
451
+ *
452
+ * **Example:** Explicit name
453
+ * ```typescript
454
+ * const web = yield* Fly.Machine("Web", {
455
+ * app: Site,
456
+ * name: "web",
457
+ * region: "iad",
458
+ * image: "nginx:alpine",
459
+ * });
460
+ * ```
461
+ *
462
+ * :::caution[Changing `name` replaces the Machine]
463
+ * Fly cannot rename a Machine. Alchemy creates the new name, then
464
+ * deletes the old one.
465
+ * :::
466
+ *
467
+ * ### Region
468
+ * Fly Machines live in a region. Default is `iad`. See
469
+ * [Regions](/fly/compute/regions) for the list of codes.
470
+ *
471
+ * **Example:** Pin a region
472
+ * ```typescript
473
+ * const web = yield* Fly.Machine("Web", {
474
+ * app: Site,
475
+ * region: "ewr",
476
+ * image: "nginx:alpine",
477
+ * });
478
+ * ```
479
+ *
480
+ * :::caution[Changing `region` replaces the Machine]
481
+ * The Machine is created in the new region. The old one is deleted.
482
+ * :::
483
+ *
484
+ * ### Guest size
485
+ * `guest` is CPU kind, CPU count, and memory. Default is shared-cpu,
486
+ * 1 CPU, 256 MB. Rolling updates guest sizing in place; blue/green replaces
487
+ * the Machines.
488
+ *
489
+ * **Example:** Shared CPU
490
+ * ```typescript
491
+ * const web = yield* Fly.Machine("Web", {
492
+ * app: Site,
493
+ * region: "iad",
494
+ * image: "nginx:alpine",
495
+ * guest: { cpuKind: "shared", cpus: 1, memoryMb: 256 },
496
+ * });
497
+ * ```
498
+ *
499
+ * ### GPU
500
+ * Set `gpuKind` and `gpus` on `guest` when the Machine should have a
501
+ * GPU.
502
+ *
503
+ * **Example:** GPU guest
504
+ * ```typescript
505
+ * const worker = yield* Fly.Machine("Worker", {
506
+ * app: Site,
507
+ * region: "iad",
508
+ * image: "my-gpu-image:tag",
509
+ * guest: {
510
+ * cpuKind: "performance",
511
+ * cpus: 2,
512
+ * memoryMb: 4096,
513
+ * gpuKind: "a10",
514
+ * gpus: 1,
515
+ * },
516
+ * });
517
+ * ```
518
+ *
519
+ * ### Environment variables
520
+ * `env` is merged onto the Machine. Fly also injects App
521
+ * {@link Secret} values as env vars unless the Machine skips secrets.
522
+ *
523
+ * **Example:** Set env
524
+ * ```typescript
525
+ * const worker = yield* Fly.Machine("Worker", {
526
+ * app: Site,
527
+ * region: "iad",
528
+ * image: "my-image:tag",
529
+ * env: { LOG_LEVEL: "info" },
530
+ * });
531
+ * ```
532
+ *
533
+ * ### Publish a proxy service
534
+ * `services` publishes ports on Fly's proxy. The App needs an
535
+ * {@link IpAssignment} before `{app}.fly.dev` answers. For a public
536
+ * endpoint without managing Apps and addresses, use a {@link Service}.
537
+ *
538
+ * Handlers are `http`, `tls`, `pg_tls`, and similar. Set `forceHttps`
539
+ * to redirect HTTP to HTTPS. Use `startPort` / `endPort` for a
540
+ * published range.
541
+ *
542
+ * Omit `services` (or pass `[]`) for a process that should not be
543
+ * reachable from the internet.
544
+ *
545
+ * **Example:** HTTP on port 80
546
+ * ```typescript
547
+ * const web = yield* Fly.Machine("Web", {
548
+ * app: Site,
549
+ * region: "iad",
550
+ * image: "nginx:alpine",
551
+ * services: [
552
+ * {
553
+ * protocol: "tcp",
554
+ * internalPort: 80,
555
+ * ports: [
556
+ * { port: 80, handlers: ["http"], forceHttps: true },
557
+ * { port: 443, handlers: ["tls", "http"] },
558
+ * ],
559
+ * },
560
+ * ],
561
+ * });
562
+ * ```
563
+ *
564
+ * ### Service health checks
565
+ * Add HTTP or TCP `checks` to a service. Fly uses their results to
566
+ * determine whether the service is ready to receive traffic. With rolling
567
+ * updates, reconcile waits for each started replica's checks before updating
568
+ * the next replica. Missing or non-passing results are polled within
569
+ * `deploy.healthTimeout` (60 seconds by default), then fail deployment with
570
+ * `Fly.ReplicaChecksNotPassing`. Later replicas remain unchanged; earlier
571
+ * updates are not rolled back. A single rolling replica can be unavailable.
572
+ * Blue/green checks replacements before retiring the old set, with
573
+ * representative/floor readiness for idle capacity.
574
+ *
575
+ * **Example:** HTTP readiness check
576
+ * ```typescript
577
+ * const web = yield* Fly.Machine("Web", {
578
+ * app: Site,
579
+ * region: "iad",
580
+ * image: "nginx:alpine",
581
+ * services: [
582
+ * {
583
+ * protocol: "tcp",
584
+ * internalPort: 80,
585
+ * ports: [{ port: 80, handlers: ["http"] }],
586
+ * checks: [
587
+ * {
588
+ * type: "http",
589
+ * port: 80,
590
+ * method: "GET",
591
+ * path: "/",
592
+ * protocol: "http",
593
+ * interval: "15s",
594
+ * timeout: "2s",
595
+ * gracePeriod: "30s",
596
+ * headers: [{ name: "X-Health-Check", values: ["alchemy"] }],
597
+ * },
598
+ * ],
599
+ * },
600
+ * ],
601
+ * });
602
+ * ```
603
+ *
604
+ * ### Autostart and autostop
605
+ * `autostart` starts the Machine when a request arrives. `autostop` is
606
+ * `"off"`, `"stop"`, `"suspend"`, or a boolean. `minMachinesRunning`
607
+ * keeps that many Machines up for the service.
608
+ *
609
+ * Autostop only affects Machines that already exist. Set `count` or declare
610
+ * more resources to size the pool. Stop boots a new process on autostart;
611
+ * suspend may resume memory or fall back to a cold start. Suspension is not
612
+ * SIGTERM shutdown and does not run ordinary shutdown finalizers.
613
+ *
614
+ * Blue/green supports both policies: it checks a representative and the
615
+ * required running floor while preserving idle nonrepresentatives. It
616
+ * restores the requested idle policy before retiring predecessors and
617
+ * checks any new instance created by restoration. A replacement does not
618
+ * inherit its suspended predecessor's process memory.
619
+ *
620
+ * **Example:** Stop when idle
621
+ * ```typescript
622
+ * const web = yield* Fly.Machine("Web", {
623
+ * app: Site,
624
+ * region: "iad",
625
+ * image: "nginx:alpine",
626
+ * services: [
627
+ * {
628
+ * protocol: "tcp",
629
+ * internalPort: 80,
630
+ * autostart: true,
631
+ * autostop: "stop",
632
+ * minMachinesRunning: 0,
633
+ * ports: [{ port: 80, handlers: ["http"] }],
634
+ * },
635
+ * ],
636
+ * });
637
+ * ```
638
+ *
639
+ * ### Scale up
640
+ * Each Machine resource runs one VM by default. Set `count` to manage
641
+ * several replicas together, or declare separate resources for Machines
642
+ * with different configuration. Fly's proxy load-balances published
643
+ * `services` across them.
644
+ *
645
+ * Both Machine and {@link Service} support `count`. Default rolling updates
646
+ * replicas sequentially; blue/green prepares replacements before retirement.
647
+ * Separate resources do not share an update order or App-wide lease lock.
648
+ *
649
+ * **Example:** Two Machines
650
+ * ```typescript
651
+ * const web1 = yield* Fly.Machine("Web1", {
652
+ * app: Site,
653
+ * region: "iad",
654
+ * image: "nginx:alpine",
655
+ * services: [
656
+ * {
657
+ * protocol: "tcp",
658
+ * internalPort: 80,
659
+ * ports: [{ port: 80, handlers: ["http"] }],
660
+ * },
661
+ * ],
662
+ * });
663
+ *
664
+ * const web2 = yield* Fly.Machine("Web2", {
665
+ * app: Site,
666
+ * region: "iad",
667
+ * image: "nginx:alpine",
668
+ * services: [
669
+ * {
670
+ * protocol: "tcp",
671
+ * internalPort: 80,
672
+ * ports: [{ port: 80, handlers: ["http"] }],
673
+ * },
674
+ * ],
675
+ * });
676
+ * ```
677
+ *
678
+ * ### Scale down
679
+ * Remove a Machine from the stack. The next deploy deletes it.
680
+ *
681
+ * **Example:** Drop Web2
682
+ * ```diff
683
+ * const web1 = yield* Fly.Machine("Web1", {
684
+ * app: Site,
685
+ * region: "iad",
686
+ * image: "nginx:alpine",
687
+ * });
688
+ * -
689
+ * - const web2 = yield* Fly.Machine("Web2", {
690
+ * - app: Site,
691
+ * - region: "iad",
692
+ * - image: "nginx:alpine",
693
+ * - });
694
+ * ```
695
+ *
696
+ * ### Attach a disk
697
+ * Pass disks as `mounts`. Alchemy creates a Volume in the Machine's
698
+ * app and region. A Volume attaches to one Machine. There is no
699
+ * standalone Volume resource.
700
+ *
701
+ * `sizeGb` can grow in place. Shrinking is not supported. Encryption,
702
+ * filesystem type, `snapshotId`, and `sourceVolumeId` are create-only.
703
+ * See {@link MountVolume} for the full disk spec. From a Service,
704
+ * prefer `MountVolume` so the path is part of the binding graph.
705
+ *
706
+ * **Example:** Mount `/data`
707
+ * ```typescript
708
+ * const box = yield* Fly.Machine("Box", {
709
+ * app: Site,
710
+ * region: "iad",
711
+ * image: "postgres:16",
712
+ * mounts: [{ path: "/data", sizeGb: 10 }],
713
+ * });
714
+ * ```
715
+ *
716
+ * ### Init
717
+ * `init` overrides `cmd`, `entrypoint`, `exec`, swap, and TTY. Updates
718
+ * in place.
719
+ *
720
+ * **Example:** Custom command
721
+ * ```typescript
722
+ * const box = yield* Fly.Machine("Box", {
723
+ * app: Site,
724
+ * region: "iad",
725
+ * image: "postgres:16",
726
+ * init: { cmd: ["postgres", "-c", "shared_buffers=256MB"] },
727
+ * });
728
+ * ```
729
+ *
730
+ * ### Restart policy
731
+ * `restart.policy` is `"no"`, `"always"`, `"on-failure"`, or
732
+ * `"spot-price"`. `maxRetries` applies when the policy is
733
+ * `"on-failure"`. Updates in place.
734
+ *
735
+ * **Example:** Always restart
736
+ * ```typescript
737
+ * const worker = yield* Fly.Machine("Worker", {
738
+ * app: Site,
739
+ * region: "iad",
740
+ * image: "my-image:tag",
741
+ * restart: { policy: "always" },
742
+ * });
743
+ * ```
744
+ *
745
+ * ### Destroy on exit
746
+ * `autoDestroy: true` tears the Machine down when its main process
747
+ * exits. Default is `false`.
748
+ *
749
+ * **Example:** One-shot Machine
750
+ * ```typescript
751
+ * const job = yield* Fly.Machine("Job", {
752
+ * app: Site,
753
+ * region: "iad",
754
+ * image: "my-job:tag",
755
+ * autoDestroy: true,
756
+ * restart: { policy: "no" },
757
+ * });
758
+ * ```
759
+ *
760
+ * ### Skip launch
761
+ * `skipLaunch: true` creates or updates the config without starting
762
+ * the Machine. Default is `false`. Reconcile otherwise waits until
763
+ * the Machine is `started`, and until service checks are passing when
764
+ * the Machine has them.
765
+ *
766
+ * **Example:** Config only
767
+ * ```typescript
768
+ * const web = yield* Fly.Machine("Web", {
769
+ * app: Site,
770
+ * region: "iad",
771
+ * image: "nginx:alpine",
772
+ * skipLaunch: true,
773
+ * });
774
+ * ```
775
+ *
776
+ * ### Metadata
777
+ * User keys on `metadata` merge with Alchemy ownership keys
778
+ * (`alchemy.stack`, `alchemy.stage`, `alchemy.id`, `alchemy.type`,
779
+ * `alchemy.replica`). Those ownership keys are always written so
780
+ * `list()` can find owned Machines. Fly Apps have no labels.
781
+ *
782
+ * **Example:** User metadata
783
+ * ```typescript
784
+ * const web = yield* Fly.Machine("Web", {
785
+ * app: Site,
786
+ * region: "iad",
787
+ * image: "nginx:alpine",
788
+ * metadata: { role: "edge" },
789
+ * });
790
+ * ```
791
+ *
792
+ * ### Secrets version
793
+ * `minSecretsVersion` requires at least that App-secrets version, not an
794
+ * immutable snapshot. Machine leases do not serialize vault writers.
795
+ * After rotating a {@link Secret}, declare the required floor or another
796
+ * explicit rollout input; an out-of-band change alone does not watch/redeploy.
797
+ *
798
+ * **Example:** Wait for secrets
799
+ * ```typescript
800
+ * const web = yield* Fly.Machine("Web", {
801
+ * app: Site,
802
+ * region: "iad",
803
+ * image: "nginx:alpine",
804
+ * minSecretsVersion: 2,
805
+ * });
806
+ * ```
807
+ *
808
+ * ### Blue/green deployments
809
+ * Prepare a healthy replacement set before retiring the current Machines.
810
+ * Physical IDs and names change; the App URL remains stable. Volumes,
811
+ * auto-destroy, and skipLaunch are incompatible. Autostop preserves idle
812
+ * nonrepresentatives while a representative passes checks. Raw images must
813
+ * handle their own shutdown signal and stop accepting background work.
814
+ *
815
+ * Retirement honors each predecessor's own signal and timeout. Native
816
+ * target leases do not exclude every simultaneous first deployment or
817
+ * snapshot; serialize CI for the same resource. See the
818
+ * [deployment guide](/fly/compute/deployments) for idle capacity, secret
819
+ * floors, recovery, and the limits of live-tested parity.
820
+ *
821
+ * **Example:** Private worker readiness
822
+ * ```typescript
823
+ * const worker = yield* Fly.Machine("Worker", {
824
+ * app: Site,
825
+ * image: "registry.example.com/worker:v2",
826
+ * deploy: { strategy: "bluegreen", healthTimeout: "60 seconds" },
827
+ * shutdown: { signal: "SIGTERM", timeout: "30 seconds" },
828
+ * checks: {
829
+ * ready: { type: "http", port: 3000, path: "/healthz", interval: "5s", timeout: "2s" },
830
+ * },
831
+ * });
832
+ * ```
833
+ *
834
+ * Every published service needs its own service check. Before promotion, a
835
+ * failed candidate leaves the old generation serving. After possible promotion,
836
+ * potentially serving replacements are preserved rather than blindly deleted.
837
+ * Retry an interrupted deploy to finish promotion or retirement; destroy
838
+ * discovers unfinished owned generations.
839
+ * See the [deployment guide](/fly/compute/deployments) for recovery and limits.
840
+ *
841
+ * @resource
842
+ * @product Machine
843
+ */
844
+ export const Machine = Resource<Machine>("Fly.Machine");
845
+
846
+ export class MachineNotCreated extends Data.TaggedError("Fly.MachineNotCreated")<{
847
+ resourceName: string;
848
+ appName: string;
849
+ }> {}
850
+
851
+ export class MachineAppNotResolved extends Data.TaggedError("Fly.MachineAppNotResolved")<{
852
+ message: string;
853
+ }> {}
854
+
855
+ type MachineBinding = Machine["Binding"];
856
+
857
+ const appNameOf = (value: unknown): string | undefined => {
858
+ if (value == null || typeof value !== "object") return undefined;
859
+ const name = (value as { appName?: unknown }).appName;
860
+ return typeof name === "string" && name.length > 0 ? name : undefined;
861
+ };
862
+
863
+ const compactRecord = (
864
+ record: Record<string, string | undefined> | null | undefined,
865
+ ): Record<string, string> =>
866
+ Object.fromEntries(
867
+ Object.entries(record ?? {}).flatMap(([key, value]) =>
868
+ value === undefined ? [] : [[key, value]],
869
+ ),
870
+ );
871
+
872
+ const toEnv = toEnvRecord;
873
+
874
+ const resolveMachineName = (id: string, name: string | undefined, existing?: string) =>
875
+ Effect.gen(function* () {
876
+ if (name !== undefined) return sanitizeFlyAppName(name);
877
+ if (existing !== undefined) return existing;
878
+ return yield* createFlyResourceName(id);
879
+ });
880
+
881
+ const mergeBindings = (bindings: readonly ResourceBinding<MachineBinding>[]) => {
882
+ const env: Record<string, any> = {};
883
+ const mounts: DiskSpec[] = [];
884
+ for (const binding of bindings) {
885
+ Object.assign(env, binding.data?.env);
886
+ if (binding.data?.mounts) mounts.push(...binding.data.mounts);
887
+ }
888
+ return { env, mounts };
889
+ };
890
+
891
+ const mergeDisks = (props: DiskSpec[] | undefined, bindingMounts: DiskSpec[]): DiskSpec[] => {
892
+ const byPath = new Map<string, DiskSpec>();
893
+ for (const disk of [...(props ?? []), ...bindingMounts]) {
894
+ byPath.set(disk.path, disk);
895
+ }
896
+ return [...byPath.values()];
897
+ };
898
+
899
+ const toFlyGuest = (guest: MachineGuest | undefined): FlyMachineGuest => {
900
+ const fly: FlyMachineGuest = {
901
+ cpu_kind: guest?.cpuKind ?? DEFAULT_CPU_KIND,
902
+ cpus: guest?.cpus ?? DEFAULT_CPUS,
903
+ memory_mb: guest?.memoryMb ?? DEFAULT_MEMORY_MB,
904
+ };
905
+ if (guest?.gpuKind !== undefined) fly.gpu_kind = guest.gpuKind;
906
+ if (guest?.gpus !== undefined) fly.gpus = guest.gpus;
907
+ return fly;
908
+ };
909
+
910
+ const toFlyInit = (init: MachineInit): FlyMachineInit => ({
911
+ cmd: init.cmd,
912
+ entrypoint: init.entrypoint,
913
+ exec: init.exec,
914
+ swap_size_mb: init.swapSizeMb,
915
+ tty: init.tty,
916
+ });
917
+
918
+ const toFlyRestart = (restart: MachineRestart): FlyMachineRestart => ({
919
+ policy: restart.policy,
920
+ max_retries: restart.maxRetries,
921
+ });
922
+
923
+ const desiredEnv = (
924
+ props: MachineProps,
925
+ bindingEnv: Record<string, any>,
926
+ ): Record<string, string> => ({ ...toEnv(props.env), ...toEnv(bindingEnv) });
927
+
928
+ const desiredMetadata = (
929
+ props: MachineProps,
930
+ alchemy: Record<string, string>,
931
+ ): Record<string, string> => ({ ...props.metadata, ...alchemy });
932
+
933
+ const buildConfig = (input: {
934
+ image: string | undefined;
935
+ containers: FlyMachineConfig["containers"];
936
+ guest: FlyMachineGuest;
937
+ env: Record<string, string>;
938
+ services: FlyMachineService[] | undefined;
939
+ mounts: FlyMachineMount[];
940
+ metadata: Record<string, string>;
941
+ restart: FlyMachineRestart | undefined;
942
+ autoDestroy: boolean | undefined;
943
+ init: FlyMachineInit | undefined;
944
+ }): FlyMachineConfig => ({
945
+ image: input.image,
946
+ containers: input.containers,
947
+ guest: input.guest,
948
+ env: Object.keys(input.env).length > 0 ? input.env : undefined,
949
+ services: input.services !== undefined && input.services.length > 0 ? input.services : undefined,
950
+ mounts: input.mounts.length > 0 ? input.mounts : undefined,
951
+ metadata: input.metadata,
952
+ restart: input.restart,
953
+ auto_destroy: input.autoDestroy,
954
+ init: input.init,
955
+ });
956
+
957
+ const sameImage = (machine: FlyMachine, image: string) => {
958
+ const configImage = machine.config?.image;
959
+ if (configImage === image) return true;
960
+ const ref = machine.image_ref;
961
+ const colon = image.lastIndexOf(":");
962
+ const slash = image.lastIndexOf("/");
963
+ const split = colon > slash ? colon : -1;
964
+ const repo = split === -1 ? image : image.slice(0, split);
965
+ const tag = split === -1 ? "latest" : image.slice(split + 1);
966
+ const observedRepo = ref?.repository;
967
+ if (observedRepo === undefined || ref?.tag !== tag) return false;
968
+ return observedRepo === repo || observedRepo.endsWith(`/${repo}`);
969
+ };
970
+
971
+ const sameGuest = (observed: FlyMachineGuest | undefined, desired: FlyMachineGuest) =>
972
+ (observed?.cpu_kind ?? DEFAULT_CPU_KIND) === desired.cpu_kind &&
973
+ (observed?.cpus ?? DEFAULT_CPUS) === desired.cpus &&
974
+ (observed?.memory_mb ?? DEFAULT_MEMORY_MB) === desired.memory_mb &&
975
+ observed?.gpu_kind === desired.gpu_kind &&
976
+ observed?.gpus === desired.gpus;
977
+
978
+ const sameEnv = (
979
+ observed: Record<string, string | undefined> | undefined,
980
+ desired: Record<string, string>,
981
+ ) => deepEqual(compactRecord(observed), desired);
982
+
983
+ const sameMounts = (observed: FlyMachineMount[] | undefined, desired: FlyMachineMount[]) => {
984
+ const key = (mount: FlyMachineMount) => `${mount.volume ?? ""}:${mount.path ?? ""}`;
985
+ const left = [...(observed ?? [])].map(key).sort();
986
+ const right = desired.map(key).sort();
987
+ return deepEqual(left, right);
988
+ };
989
+
990
+ const sameRestart = (
991
+ observed: FlyMachineRestart | undefined,
992
+ desired: FlyMachineRestart | undefined,
993
+ ) =>
994
+ deepEqual(
995
+ { policy: observed?.policy ?? "on-failure", max_retries: observed?.max_retries ?? 10 },
996
+ { policy: desired?.policy ?? "on-failure", max_retries: desired?.max_retries ?? 10 },
997
+ { stripNullish: true },
998
+ );
999
+
1000
+ const sameInit = (observed: FlyMachineInit | undefined, desired: FlyMachineInit | undefined) =>
1001
+ deepEqual(observed ?? {}, desired ?? {}, { stripNullish: true });
1002
+
1003
+ const metadataChanged = (
1004
+ observed: Record<string, string | undefined> | undefined,
1005
+ desired: Record<string, string>,
1006
+ ) => {
1007
+ const { removed, added, updated } = diffMachineMetadata(compactRecord(observed), desired);
1008
+ return removed.length > 0 || Object.keys(added).length > 0 || Object.keys(updated).length > 0;
1009
+ };
1010
+
1011
+ const configDrifted = (
1012
+ machine: FlyMachine,
1013
+ desired: {
1014
+ image: string | undefined;
1015
+ containers: FlyMachineConfig["containers"];
1016
+ guest: FlyMachineGuest;
1017
+ env: Record<string, string>;
1018
+ services: FlyMachineService[] | undefined;
1019
+ mounts: FlyMachineMount[];
1020
+ metadata: Record<string, string>;
1021
+ restart: FlyMachineRestart | undefined;
1022
+ autoDestroy: boolean | undefined;
1023
+ init: FlyMachineInit | undefined;
1024
+ },
1025
+ ) => {
1026
+ const config = machine.config;
1027
+ return (
1028
+ (desired.containers !== undefined
1029
+ ? !sameContainerWorkload(config, desired.containers)
1030
+ : desired.image === undefined ||
1031
+ !sameImage(machine, desired.image) ||
1032
+ (config?.containers?.length ?? 0) > 0) ||
1033
+ !sameGuest(config?.guest, desired.guest) ||
1034
+ !sameEnv(config?.env, desired.env) ||
1035
+ !sameServices(config?.services, desired.services) ||
1036
+ !sameMounts(config?.mounts, desired.mounts) ||
1037
+ metadataChanged(config?.metadata, desired.metadata) ||
1038
+ !sameRestart(config?.restart, desired.restart) ||
1039
+ (desired.autoDestroy ?? false) !== (config?.auto_destroy ?? false) ||
1040
+ !sameInit(config?.init, desired.init)
1041
+ );
1042
+ };
1043
+
1044
+ const toAttrs = (set: ReplicaSet): Machine["Attributes"] => ({
1045
+ appName: set.appName,
1046
+ rolloutPending: set.rolloutPending,
1047
+ machineId: set.machineId,
1048
+ machineIds: set.machineIds,
1049
+ name: set.name,
1050
+ baseName: set.baseName,
1051
+ region: set.region,
1052
+ state: set.state,
1053
+ instanceId: set.instanceId,
1054
+ privateIp: set.privateIp,
1055
+ imageRef: set.imageRef,
1056
+ guest: set.guest,
1057
+ count: set.count,
1058
+ mounts: set.mounts,
1059
+ replicas: set.replicas,
1060
+ });
1061
+
1062
+ const machineIdsOf = (output: Machine["Attributes"] | undefined) =>
1063
+ output?.machineIds ??
1064
+ (output?.machineId !== undefined && output.machineId.length > 0 ? [output.machineId] : []);
1065
+
1066
+ export const MachineProvider = () =>
1067
+ Provider.succeed(Machine, {
1068
+ stables: ["region", "appName"],
1069
+ nuke: { dependsOn: ["Fly.App"] },
1070
+
1071
+ diff: Effect.fn(function* ({ news, output }) {
1072
+ if (news === undefined) return;
1073
+ if ("app" in news) {
1074
+ const imageMode = { image: news.image, containers: news.containers, init: news.init };
1075
+ const imageModeResolved =
1076
+ isResolved<Pick<MachineProps, "image" | "containers" | "init">>(imageMode);
1077
+ if (imageModeResolved) yield* validateMachineContainers(imageMode);
1078
+ const settings: Input<
1079
+ Pick<
1080
+ MachineProps,
1081
+ | "deploy"
1082
+ | "shutdown"
1083
+ | "checks"
1084
+ | "services"
1085
+ | "mounts"
1086
+ | "skipLaunch"
1087
+ | "autoDestroy"
1088
+ | "restart"
1089
+ | "containers"
1090
+ >
1091
+ > = {
1092
+ deploy: news.deploy,
1093
+ shutdown: news.shutdown,
1094
+ checks: news.checks,
1095
+ services: news.services,
1096
+ mounts: news.mounts,
1097
+ skipLaunch: news.skipLaunch,
1098
+ autoDestroy: news.autoDestroy,
1099
+ restart: news.restart,
1100
+ containers: news.containers,
1101
+ };
1102
+ if (
1103
+ imageModeResolved &&
1104
+ isResolved<
1105
+ Pick<
1106
+ MachineProps,
1107
+ | "deploy"
1108
+ | "shutdown"
1109
+ | "checks"
1110
+ | "services"
1111
+ | "mounts"
1112
+ | "skipLaunch"
1113
+ | "autoDestroy"
1114
+ | "restart"
1115
+ | "containers"
1116
+ >
1117
+ >(settings)
1118
+ ) {
1119
+ yield* validateDeployment(
1120
+ yield* deploymentPolicy(settings.deploy, settings.shutdown),
1121
+ {
1122
+ services: settings.services?.map(toFlyService),
1123
+ checks: settings.checks,
1124
+ auto_destroy: settings.autoDestroy,
1125
+ restart: settings.restart,
1126
+ containers:
1127
+ settings.containers === undefined
1128
+ ? undefined
1129
+ : toFlyContainers(settings.containers),
1130
+ },
1131
+ (settings.mounts?.length ?? 0) > 0,
1132
+ settings.skipLaunch,
1133
+ );
1134
+ }
1135
+ }
1136
+ if (!isResolved(news))
1137
+ return output?.rolloutPending ? { action: "update" as const } : undefined;
1138
+ yield* validateMachineContainers(news);
1139
+ if (output === undefined) return undefined;
1140
+ const desiredAppName = appNameOf(news.app);
1141
+ const appChanged = desiredAppName !== undefined && desiredAppName !== output.appName;
1142
+ const desiredName =
1143
+ news.name !== undefined ? sanitizeFlyAppName(news.name) : (output.baseName ?? output.name);
1144
+ const nameChanged = desiredName !== (output.baseName ?? output.name);
1145
+ const desiredRegion = news.region ?? DEFAULT_REGION;
1146
+ const regionChanged = desiredRegion !== output.region;
1147
+ if (appChanged || nameChanged || regionChanged) {
1148
+ return {
1149
+ action: "replace" as const,
1150
+ // Name is unique per App — same name in a new region cannot coexist.
1151
+ deleteFirst: nameChanged === false && appChanged === false,
1152
+ };
1153
+ }
1154
+ return output.rolloutPending ? { action: "update" as const } : undefined;
1155
+ }),
1156
+
1157
+ read: Effect.fn(function* ({ id, fqn, instanceId, olds, output }) {
1158
+ const appName = appNameOf(olds?.app) ?? output?.appName;
1159
+ const name = yield* resolveMachineName(id, olds?.name, output?.baseName ?? output?.name);
1160
+ const found = yield* observeReplicaSet({
1161
+ appName,
1162
+ id,
1163
+ type: "Fly.Machine",
1164
+ fqn,
1165
+ resourceInstanceId: instanceId,
1166
+ machineIds: machineIdsOf(output),
1167
+ baseName: name,
1168
+ });
1169
+ if (found === undefined) return undefined;
1170
+ return toAttrs(found);
1171
+ }),
1172
+
1173
+ list: Effect.fn(function* () {
1174
+ const sets = yield* listReplicaSets("Fly.Machine");
1175
+ return sets.map(toAttrs);
1176
+ }),
1177
+
1178
+ reconcile: Effect.fn(function* ({ id, fqn, instanceId, news, output, bindings }) {
1179
+ const props = news;
1180
+ yield* validateMachineContainers(props);
1181
+ const policy = yield* deploymentPolicy(props.deploy, props.shutdown);
1182
+ const appName = appNameOf(props.app) ?? output?.appName;
1183
+ if (appName === undefined) {
1184
+ return yield* new MachineAppNotResolved({
1185
+ message: "Fly.Machine requires a resolved App with appName.",
1186
+ });
1187
+ }
1188
+ const name = yield* resolveMachineName(id, props.name, output?.baseName ?? output?.name);
1189
+ const region = props.region ?? output?.region ?? DEFAULT_REGION;
1190
+ const count = resolveCount(props.count);
1191
+ const skipLaunch = props.skipLaunch === true;
1192
+ const bound = mergeBindings(bindings ?? []);
1193
+ const disks = mergeDisks(props.mounts, bound.mounts);
1194
+ const env = desiredEnv(props, bound.env);
1195
+ const guest = toFlyGuest(props.guest);
1196
+ const services = props.services?.map(toFlyService);
1197
+ const restart = props.restart ? toFlyRestart(props.restart) : undefined;
1198
+ const init = props.init ? toFlyInit(props.init) : undefined;
1199
+ const containers =
1200
+ props.containers === undefined ? undefined : toFlyContainers(props.containers);
1201
+
1202
+ const set = yield* reconcileReplicas({
1203
+ id,
1204
+ type: "Fly.Machine",
1205
+ fqn,
1206
+ resourceInstanceId: instanceId,
1207
+ policy,
1208
+ checks: props.checks,
1209
+ appName,
1210
+ baseName: name,
1211
+ regions: [region],
1212
+ count,
1213
+ disks,
1214
+ skipLaunch,
1215
+ minSecretsVersion: props.minSecretsVersion,
1216
+ outputMachineIds: machineIdsOf(output),
1217
+ preferVolumeIds: (output?.replicas ?? []).map((replica) =>
1218
+ replica.mounts.map((mount) => mount.volumeId),
1219
+ ),
1220
+ configDrifted: (machine, desired) =>
1221
+ configDrifted(machine, {
1222
+ image: props.image,
1223
+ containers,
1224
+ guest,
1225
+ env,
1226
+ services,
1227
+ mounts: desired.mounts,
1228
+ metadata: desiredMetadata(props, desired.metadata),
1229
+ restart,
1230
+ autoDestroy: props.autoDestroy,
1231
+ init,
1232
+ }),
1233
+ buildConfig: ({ mounts, metadata }) =>
1234
+ buildConfig({
1235
+ image: props.image,
1236
+ containers,
1237
+ guest,
1238
+ env,
1239
+ services,
1240
+ mounts,
1241
+ metadata: desiredMetadata(props, metadata),
1242
+ restart,
1243
+ autoDestroy: props.autoDestroy,
1244
+ init,
1245
+ }),
1246
+ }).pipe(
1247
+ Effect.catchTag("Fly.ReplicaNotCreated", (error) =>
1248
+ Effect.fail(
1249
+ new MachineNotCreated({ resourceName: error.resourceName, appName: error.appName }),
1250
+ ),
1251
+ ),
1252
+ );
1253
+ return toAttrs(set);
1254
+ }),
1255
+
1256
+ delete: Effect.fn(function* ({ id, fqn, instanceId, olds, output, force }) {
1257
+ const appName = output.appName ?? appNameOf(olds.app);
1258
+ if (appName === undefined) return;
1259
+ yield* deleteReplicaSet({
1260
+ appName,
1261
+ id,
1262
+ type: "Fly.Machine",
1263
+ fqn,
1264
+ resourceInstanceId: instanceId,
1265
+ machineIds: machineIdsOf(output),
1266
+ volumeIds: volumeIdsOf(output),
1267
+ force,
1268
+ });
1269
+ }),
1270
+ });