@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/leases.ts ADDED
@@ -0,0 +1,437 @@
1
+ import {
2
+ BadGateway,
3
+ GatewayTimeout,
4
+ InternalServerError,
5
+ ServiceUnavailable,
6
+ TooManyRequests,
7
+ } from "@distilled.cloud/fly-io/Errors";
8
+ import * as machines from "@distilled.cloud/fly-io/machines";
9
+ import * as Retry from "@distilled.cloud/fly-io/Retry";
10
+ import * as Clock from "effect/Clock";
11
+ import * as Data from "effect/Data";
12
+ import * as Deferred from "effect/Deferred";
13
+ import * as Duration from "effect/Duration";
14
+ import * as Effect from "effect/Effect";
15
+ import * as Fiber from "effect/Fiber";
16
+ import * as FetchHttpClient from "effect/http/FetchHttpClient";
17
+ import * as HttpClient from "effect/http/HttpClient";
18
+ import * as HttpClientRequest from "effect/http/HttpClientRequest";
19
+ import * as Option from "effect/Option";
20
+ import * as Schedule from "effect/Schedule";
21
+
22
+ const TTL_SECONDS = 120;
23
+ const EXPIRY_MARGIN_MS = 15_000;
24
+
25
+ const retrySchedule = <E>(): Schedule.Schedule<Duration.Duration, E> =>
26
+ Schedule.exponential("500 millis").pipe(
27
+ Schedule.modifyDelay<Duration.Duration, E>(({ input, duration }) =>
28
+ Effect.succeed(
29
+ (TooManyRequests.is(input) ||
30
+ InternalServerError.is(input) ||
31
+ BadGateway.is(input) ||
32
+ ServiceUnavailable.is(input) ||
33
+ GatewayTimeout.is(input)) &&
34
+ input.retryAfter
35
+ ? Math.min(Duration.toMillis(input.retryAfter), 60_000)
36
+ : Math.min(Duration.toMillis(duration), 5_000),
37
+ ),
38
+ ),
39
+ Schedule.addDelay<Duration.Duration, E>(() =>
40
+ Effect.sync(() => Duration.millis(Math.random() * 50)),
41
+ ),
42
+ );
43
+
44
+ export class MachineLeaseBusy extends Data.TaggedError("Fly.MachineLeaseBusy")<{
45
+ appName: string;
46
+ machineId: string;
47
+ }> {}
48
+
49
+ export class MachineLeaseLost extends Data.TaggedError("Fly.MachineLeaseLost")<{
50
+ appName: string;
51
+ machineId: string;
52
+ reason: string;
53
+ }> {
54
+ get message() {
55
+ return `Machine lease authority lost for ${this.appName}/${this.machineId}: ${this.reason}`;
56
+ }
57
+ }
58
+
59
+ export class MachineMutationUncertain extends Data.TaggedError("Fly.MachineMutationUncertain")<{
60
+ appName: string;
61
+ machineId: string;
62
+ }> {}
63
+
64
+ interface HeldLease {
65
+ nonce: string;
66
+ deadline: number;
67
+ renewAt: number;
68
+ }
69
+
70
+ export const makeMachineLeases = Effect.fn(function* (appName: string) {
71
+ const scope = yield* Effect.scope;
72
+ const held = new Map<string, HeldLease>();
73
+ const deleting = new Set<string>();
74
+ const renewals = new Set<Fiber.Fiber<void, never>>();
75
+ const uncertain = new Set<string>();
76
+ const lost = yield* Deferred.make<never, MachineLeaseLost>();
77
+ let failure: MachineLeaseLost | undefined;
78
+ const lose = (machineId: string, reason: string) =>
79
+ Effect.gen(function* () {
80
+ failure ??= new MachineLeaseLost({ appName, machineId, reason });
81
+ yield* Deferred.fail(lost, failure);
82
+ return yield* failure;
83
+ });
84
+ const check = Effect.gen(function* () {
85
+ if (failure) return yield* failure;
86
+ const now = yield* Clock.currentTimeMillis;
87
+ for (const [machineId, lease] of held) {
88
+ if (now >= lease.deadline) return yield* lose(machineId, "lease authority expired");
89
+ }
90
+ });
91
+ const guard = <A, E, R>(effect: Effect.Effect<A, E, R>) =>
92
+ check.pipe(Effect.andThen(Effect.raceFirst(effect, Deferred.await(lost))));
93
+ const record = (machineId: string, response: machines.MachineLease, requestedAt: number) =>
94
+ Effect.gen(function* () {
95
+ const lease = response.data;
96
+ const now = yield* Clock.currentTimeMillis;
97
+ const deadline =
98
+ Math.min((lease?.expires_at ?? 0) * 1000, requestedAt + TTL_SECONDS * 1000) -
99
+ EXPIRY_MARGIN_MS;
100
+ const captured = lease?.nonce
101
+ ? { nonce: lease.nonce, deadline, renewAt: requestedAt + 25_000 }
102
+ : undefined;
103
+ if (captured) held.set(machineId, captured);
104
+ if (!captured || !Number.isFinite(deadline) || deadline <= now) {
105
+ return yield* lose(machineId, "invalid or expired lease response");
106
+ }
107
+ return captured;
108
+ });
109
+ const acquire = (machineIds: readonly string[]) =>
110
+ Effect.gen(function* () {
111
+ for (const machineId of [...new Set(machineIds)].sort()) {
112
+ yield* check;
113
+ if (held.has(machineId)) continue;
114
+ // Save a returned nonce atomically; uncertain interrupted requests expire at Fly.
115
+ yield* Effect.uninterruptibleMask((restore) =>
116
+ Effect.gen(function* () {
117
+ const requestedAt = yield* Clock.currentTimeMillis;
118
+ const response = yield* restore(
119
+ machines
120
+ .createMachineLease({
121
+ app_name: appName,
122
+ machine_id: machineId,
123
+ ttl: TTL_SECONDS,
124
+ description: "Alchemy Machine lifecycle",
125
+ })
126
+ .pipe(
127
+ Retry.none,
128
+ Effect.retry({
129
+ times: 8,
130
+ schedule: retrySchedule<machines.CreateMachineLeaseError>(),
131
+ while: (error) => error._tag === "Conflict" || error._tag === "TooManyRequests",
132
+ }),
133
+ Effect.timeout("30 seconds"),
134
+ Effect.catchTag("Conflict", () =>
135
+ Effect.fail(new MachineLeaseBusy({ appName, machineId })),
136
+ ),
137
+ Effect.catchTag(["HttpClientError", "GatewayTimeout", "TimeoutError"], (error) =>
138
+ lose(machineId, `acquisition uncertain: ${error._tag}`),
139
+ ),
140
+ ),
141
+ );
142
+ const lease = yield* record(machineId, response, requestedAt);
143
+ const renewal = yield* heartbeat(machineId, lease).pipe(
144
+ Effect.interruptible,
145
+ Effect.forkIn(scope),
146
+ );
147
+ renewals.add(renewal);
148
+ }),
149
+ );
150
+ yield* check;
151
+ }
152
+ });
153
+ const nonce = (machineId: string) =>
154
+ Effect.gen(function* () {
155
+ yield* check;
156
+ const lease = held.get(machineId);
157
+ if (!lease) return yield* lose(machineId, "target is outside the acquired lease set");
158
+ return lease.nonce;
159
+ });
160
+ const mutate = <A, E extends { readonly _tag: string }, R>(
161
+ machineId: string,
162
+ operation: (nonce: string) => Effect.Effect<A, E, R>,
163
+ options: { idempotent?: boolean; timeoutMs?: number } = {},
164
+ ) =>
165
+ guard(
166
+ Effect.gen(function* () {
167
+ const value = yield* nonce(machineId);
168
+ return yield* operation(value).pipe(Retry.none);
169
+ }).pipe(
170
+ Effect.retry({
171
+ times: 8,
172
+ schedule: retrySchedule<E | MachineLeaseLost>(),
173
+ // Only explicit throttling is safe to replay for update/stop/delete.
174
+ while: (error) =>
175
+ error._tag === "TooManyRequests" ||
176
+ (options.idempotent === true &&
177
+ (error._tag === "InternalServerError" ||
178
+ error._tag === "BadGateway" ||
179
+ error._tag === "ServiceUnavailable" ||
180
+ error._tag === "GatewayTimeout")),
181
+ }),
182
+ Effect.timeout(options.timeoutMs ?? 120_000),
183
+ Effect.catch((error) =>
184
+ Effect.gen(function* () {
185
+ if (error._tag === "Conflict" || error._tag === "Forbidden") {
186
+ return yield* lose(machineId, `leased mutation rejected: ${error._tag}`);
187
+ }
188
+ // Transport errors retain the request, including its private nonce header.
189
+ if (
190
+ error._tag === "HttpClientError" ||
191
+ error._tag === "GatewayTimeout" ||
192
+ error._tag === "TimeoutError"
193
+ ) {
194
+ return yield* new MachineMutationUncertain({
195
+ appName,
196
+ machineId,
197
+ });
198
+ }
199
+ return yield* Effect.fail(error);
200
+ }),
201
+ ),
202
+ ),
203
+ );
204
+ const forget = (machineId: string) =>
205
+ Effect.sync(() => {
206
+ held.delete(machineId);
207
+ });
208
+ const confirmRemoved = (machineId: string) =>
209
+ guard(
210
+ machines
211
+ .getMachine({
212
+ app_name: appName,
213
+ machine_id: machineId,
214
+ })
215
+ .pipe(
216
+ Retry.none,
217
+ Effect.map((machine) => machine.id === machineId && machine.state === "destroyed"),
218
+ Effect.catchTag("NotFound", () => Effect.succeed(true)),
219
+ Effect.catchTag(
220
+ [
221
+ "TooManyRequests",
222
+ "InternalServerError",
223
+ "BadGateway",
224
+ "ServiceUnavailable",
225
+ "GatewayTimeout",
226
+ ],
227
+ () => Effect.succeed(false),
228
+ ),
229
+ Effect.catchReason("HttpClientError", "TransportError", () => Effect.succeed(false)),
230
+ Effect.repeat({
231
+ times: 8,
232
+ schedule: Schedule.spaced("2 seconds"),
233
+ until: (absent) => absent,
234
+ }),
235
+ Effect.timeoutOrElse({ duration: "30 seconds", orElse: () => Effect.succeed(false) }),
236
+ Effect.catch((error) =>
237
+ Effect.gen(function* () {
238
+ if (!held.has(machineId)) return true;
239
+ if (error._tag === "Forbidden") {
240
+ return yield* lose(machineId, "removal observation forbidden");
241
+ }
242
+ return yield* error;
243
+ }),
244
+ ),
245
+ // Another observer's confirmed removal wins over a late uncertain response.
246
+ Effect.map((absent) => absent || !held.has(machineId)),
247
+ Effect.tap((absent) => (absent ? forget(machineId) : Effect.void)),
248
+ ),
249
+ );
250
+ const remove = <A, E extends { readonly _tag: string }, R>(
251
+ machineId: string,
252
+ operation: (nonce: string) => Effect.Effect<A, E, R>,
253
+ ) =>
254
+ Effect.gen(function* () {
255
+ const http = yield* HttpClient.HttpClient;
256
+ const fetchOptions = yield* Effect.serviceOption(FetchHttpClient.RequestInit);
257
+ yield* Effect.sync(() => {
258
+ deleting.add(machineId);
259
+ });
260
+ yield* mutate(machineId, (nonce) =>
261
+ operation(nonce).pipe(
262
+ // Bun can replay DELETE on a reused socket below the SDK retry policy.
263
+ Effect.provideService(
264
+ HttpClient.HttpClient,
265
+ HttpClient.mapRequest(http, HttpClientRequest.setHeader("connection", "close")),
266
+ ),
267
+ Effect.provideService(FetchHttpClient.RequestInit, {
268
+ ...Option.getOrUndefined(fetchOptions),
269
+ keepalive: false,
270
+ redirect: "error",
271
+ }),
272
+ ),
273
+ ).pipe(
274
+ Effect.asVoid,
275
+ Effect.catch((error) =>
276
+ Effect.gen(function* () {
277
+ if (error._tag === "NotFound") return yield* forget(machineId);
278
+ if (
279
+ error._tag === "Fly.MachineMutationUncertain" ||
280
+ error._tag === "InternalServerError" ||
281
+ error._tag === "BadGateway" ||
282
+ error._tag === "ServiceUnavailable"
283
+ ) {
284
+ // Keep renewal aware of the removal until its exact target has been observed.
285
+ if (yield* confirmRemoved(machineId)) return;
286
+ }
287
+ return yield* Effect.fail(error);
288
+ }),
289
+ ),
290
+ );
291
+ yield* forget(machineId);
292
+ }).pipe(
293
+ Effect.ensuring(
294
+ Effect.sync(() => {
295
+ deleting.delete(machineId);
296
+ }),
297
+ ),
298
+ );
299
+ const nonceIfHeld = (machineId: string) =>
300
+ check.pipe(Effect.map(() => held.get(machineId)?.nonce));
301
+
302
+ yield* Effect.addFinalizer(() =>
303
+ Effect.gen(function* () {
304
+ // A late refresh can recreate a lease after a successful release.
305
+ yield* Fiber.interruptAll(renewals);
306
+ yield* Effect.forEach(
307
+ [...held.entries()]
308
+ .filter(([machineId]) => !uncertain.has(machineId))
309
+ .sort(([a], [b]) => a.localeCompare(b)),
310
+ ([machineId, lease]) =>
311
+ machines
312
+ .machinesReleaseLease({
313
+ app_name: appName,
314
+ machine_id: machineId,
315
+ lease_nonce: lease.nonce,
316
+ })
317
+ .pipe(
318
+ Retry.none,
319
+ Effect.timeout("5 seconds"),
320
+ Effect.interruptible,
321
+ Effect.catchTag("NotFound", () => Effect.void),
322
+ Effect.catch((error) =>
323
+ Effect.logWarning(
324
+ "Fly lease release was not confirmed; expiry remains the safety bound",
325
+ { appName, machineId, error: error._tag },
326
+ ),
327
+ ),
328
+ Effect.asVoid,
329
+ ),
330
+ { concurrency: 4 },
331
+ );
332
+ if (uncertain.size > 0)
333
+ yield* Effect.logWarning(
334
+ "Fly lease renewal was not confirmed; expiry remains the safety bound",
335
+ { appName, machineIds: [...uncertain] },
336
+ );
337
+ }),
338
+ );
339
+
340
+ const refresh = (machineId: string, lease: HeldLease) =>
341
+ Effect.gen(function* () {
342
+ yield* check;
343
+ if (held.get(machineId) !== lease) return;
344
+ const requestedAt = yield* Clock.currentTimeMillis;
345
+ const response = yield* machines
346
+ .createMachineLease({
347
+ app_name: appName,
348
+ machine_id: machineId,
349
+ ttl: TTL_SECONDS,
350
+ lease_nonce: lease.nonce,
351
+ description: "Alchemy Machine lifecycle",
352
+ })
353
+ .pipe(Retry.none);
354
+ if (held.get(machineId) !== lease) return;
355
+ if (response.data?.nonce !== lease.nonce) {
356
+ return yield* lose(machineId, "refresh returned a different nonce");
357
+ }
358
+ return yield* record(machineId, response, requestedAt);
359
+ }).pipe(
360
+ Effect.retry({
361
+ times: 8,
362
+ schedule: retrySchedule<machines.CreateMachineLeaseError | MachineLeaseLost>(),
363
+ while: (error) => error._tag === "TooManyRequests",
364
+ }),
365
+ Effect.timeout("75 seconds"),
366
+ Effect.catch((error) =>
367
+ Effect.gen(function* () {
368
+ if (held.get(machineId) !== lease) return;
369
+ uncertain.add(machineId);
370
+ // A missing lease during removal is not proof that the Machine is gone.
371
+ if (error._tag === "NotFound" && deleting.has(machineId)) {
372
+ const absent = yield* confirmRemoved(machineId).pipe(
373
+ Effect.catch((observation) =>
374
+ held.get(machineId) === lease
375
+ ? lose(machineId, `removal observation uncertain: ${observation._tag}`)
376
+ : Effect.succeed(true),
377
+ ),
378
+ );
379
+ if (absent || held.get(machineId) !== lease) return;
380
+ return yield* lose(machineId, "lease disappeared before removal was confirmed");
381
+ }
382
+ return yield* lose(machineId, `refresh uncertain: ${error._tag}`);
383
+ }),
384
+ ),
385
+ (operation) =>
386
+ Effect.uninterruptible(
387
+ Effect.gen(function* () {
388
+ const pending = yield* operation.pipe(Effect.interruptible, Effect.forkChild);
389
+ return yield* Fiber.join(pending);
390
+ }),
391
+ ),
392
+ );
393
+ // Each target renews serially on its own cadence within the operation scope.
394
+ const heartbeat = (machineId: string, acquired: HeldLease) =>
395
+ Effect.gen(function* () {
396
+ let lease: HeldLease | undefined = acquired;
397
+ while (lease && held.get(machineId) === lease) {
398
+ const now = yield* Clock.currentTimeMillis;
399
+ yield* Effect.sleep(Math.max(0, lease.renewAt - now));
400
+ lease = yield* refresh(machineId, lease);
401
+ }
402
+ }).pipe(Effect.ignore);
403
+ yield* Effect.sleep("1 second").pipe(
404
+ Effect.andThen(check),
405
+ Effect.forever,
406
+ Effect.ignore,
407
+ Effect.forkScoped,
408
+ );
409
+ const checkTarget = (machineId: string) => nonce(machineId).pipe(Effect.asVoid);
410
+ return {
411
+ acquire,
412
+ check,
413
+ checkTarget,
414
+ guard,
415
+ mutate,
416
+ remove,
417
+ forget,
418
+ nonceIfHeld,
419
+ };
420
+ });
421
+
422
+ export type MachineLeases = Effect.Success<ReturnType<typeof makeMachineLeases>>;
423
+
424
+ export const usingMachineLeases = <A, E, R>(
425
+ appName: string,
426
+ existing: MachineLeases | undefined,
427
+ use: (leases: MachineLeases) => Effect.Effect<A, E, R>,
428
+ ) =>
429
+ Effect.gen(function* () {
430
+ if (existing) return yield* existing.guard(Effect.suspend(() => use(existing)));
431
+ return yield* Effect.scoped(
432
+ Effect.gen(function* () {
433
+ const leases = yield* makeMachineLeases(appName);
434
+ return yield* leases.guard(Effect.suspend(() => use(leases)));
435
+ }),
436
+ );
437
+ });
package/src/ports.ts ADDED
@@ -0,0 +1,177 @@
1
+ import type { FlyMachineService } from "@distilled.cloud/fly-io/machines";
2
+ import * as Data from "effect/Data";
3
+ import type { MachineService } from "./Machine.ts";
4
+
5
+ /** One port, or an inclusive port range, published on Fly's proxy. */
6
+ export interface PublishedPort {
7
+ protocol: string;
8
+ start: number;
9
+ end: number;
10
+ handlers: string[];
11
+ forceHttps: boolean;
12
+ }
13
+
14
+ export class ServicePortConflict extends Data.TaggedError("Fly.ServicePortConflict")<{
15
+ appName: string;
16
+ port: number;
17
+ protocol: string;
18
+ /** The two publishers of the port: Service logical ids or Machine ids. */
19
+ publishers: [string, string];
20
+ }> {
21
+ get message() {
22
+ return `Port ${this.port}/${this.protocol} in Fly App ${this.appName} is published by both ${this.publishers[0]} and ${this.publishers[1]}. Fly's proxy routes an App's traffic by port only, so give each Service in the App its own ports (\`services\`, or \`bindingPort\` for the plain-HTTP port Alchemy adds for bound callers).`;
23
+ }
24
+ }
25
+
26
+ const normalize = (entry: {
27
+ protocol?: string;
28
+ port?: number;
29
+ startPort?: number;
30
+ endPort?: number;
31
+ handlers?: string[];
32
+ forceHttps?: boolean;
33
+ }): PublishedPort[] => {
34
+ const start = entry.port ?? entry.startPort;
35
+ const end = entry.port ?? entry.endPort ?? entry.startPort;
36
+ if (start === undefined || end === undefined) return [];
37
+ return [
38
+ {
39
+ protocol: entry.protocol ?? "tcp",
40
+ start,
41
+ end,
42
+ handlers: entry.handlers ?? [],
43
+ forceHttps: entry.forceHttps === true,
44
+ },
45
+ ];
46
+ };
47
+
48
+ /** Published ports of observed or desired Fly Machine services. */
49
+ export const portsOfFly = (
50
+ services: readonly FlyMachineService[] | null | undefined,
51
+ ): PublishedPort[] =>
52
+ (services ?? []).flatMap((service) =>
53
+ (service.ports ?? []).flatMap((port) =>
54
+ normalize({
55
+ protocol: service.protocol,
56
+ port: port.port,
57
+ startPort: port.start_port,
58
+ endPort: port.end_port,
59
+ handlers: port.handlers,
60
+ forceHttps: port.force_https,
61
+ }),
62
+ ),
63
+ );
64
+
65
+ /**
66
+ * Published ports of a Service's `services` prop, falling back to the
67
+ * defaults: HTTP 80 (redirecting to HTTPS) and HTTPS 443 when public,
68
+ * plain HTTP 80 when private.
69
+ */
70
+ export const portsOfProps = (
71
+ services: readonly MachineService[] | undefined,
72
+ isPublic: boolean,
73
+ ): PublishedPort[] =>
74
+ services !== undefined
75
+ ? services.flatMap((service) =>
76
+ (service.ports ?? []).flatMap((port) => normalize({ protocol: service.protocol, ...port })),
77
+ )
78
+ : isPublic
79
+ ? [
80
+ {
81
+ protocol: "tcp",
82
+ start: 80,
83
+ end: 80,
84
+ handlers: ["http"],
85
+ forceHttps: true,
86
+ },
87
+ {
88
+ protocol: "tcp",
89
+ start: 443,
90
+ end: 443,
91
+ handlers: ["tls", "http"],
92
+ forceHttps: false,
93
+ },
94
+ ]
95
+ : [
96
+ {
97
+ protocol: "tcp",
98
+ start: 80,
99
+ end: 80,
100
+ handlers: ["http"],
101
+ forceHttps: false,
102
+ },
103
+ ];
104
+
105
+ const isPlainHttp = (port: PublishedPort) =>
106
+ port.start === port.end &&
107
+ port.protocol === "tcp" &&
108
+ port.handlers.includes("http") &&
109
+ !port.handlers.includes("tls") &&
110
+ !port.forceHttps;
111
+
112
+ /**
113
+ * The port bound callers use: the first plain-HTTP port, since Fly issues
114
+ * no certificate for `.flycast`. When the Service publishes ports but none
115
+ * of them is plain HTTP, Alchemy publishes `bindingPort` for bindings.
116
+ */
117
+ export const bindingPortOf = (
118
+ ports: readonly PublishedPort[],
119
+ bindingPort: number,
120
+ ): { port: number; added: boolean } | undefined => {
121
+ if (ports.length === 0) return undefined;
122
+ const others = ports.filter((port) => !(isPlainHttp(port) && port.start === bindingPort));
123
+ const plain = others.find(isPlainHttp);
124
+ if (plain !== undefined) return { port: plain.start, added: false };
125
+ return { port: bindingPort, added: true };
126
+ };
127
+
128
+ /** `ports` plus the binding port Alchemy adds, when it adds one. */
129
+ export const withBindingPort = (
130
+ ports: readonly PublishedPort[],
131
+ bindingPort: number,
132
+ ): PublishedPort[] => {
133
+ const binding = bindingPortOf(ports, bindingPort);
134
+ return binding?.added === true &&
135
+ !ports.some((port) => isPlainHttp(port) && port.start === bindingPort)
136
+ ? [
137
+ ...ports,
138
+ {
139
+ protocol: "tcp",
140
+ start: bindingPort,
141
+ end: bindingPort,
142
+ handlers: ["http"],
143
+ forceHttps: false,
144
+ },
145
+ ]
146
+ : [...ports];
147
+ };
148
+
149
+ const overlaps = (left: PublishedPort, right: PublishedPort) =>
150
+ left.protocol === right.protocol && left.start <= right.end && right.start <= left.end;
151
+
152
+ /**
153
+ * The first port two publishers share, if any. A publisher that lists the
154
+ * same port twice also conflicts with itself.
155
+ */
156
+ export const findPortConflict = (
157
+ appName: string,
158
+ publishers: ReadonlyArray<{ id: string; ports: readonly PublishedPort[] }>,
159
+ ): ServicePortConflict | undefined => {
160
+ const flat = publishers.flatMap((publisher) =>
161
+ publisher.ports.map((port) => ({ id: publisher.id, port })),
162
+ );
163
+ for (let i = 0; i < flat.length; i++) {
164
+ for (let j = i + 1; j < flat.length; j++) {
165
+ const left = flat[i]!;
166
+ const right = flat[j]!;
167
+ if (!overlaps(left.port, right.port)) continue;
168
+ return new ServicePortConflict({
169
+ appName,
170
+ port: Math.max(left.port.start, right.port.start),
171
+ protocol: left.port.protocol,
172
+ publishers: [left.id, right.id],
173
+ });
174
+ }
175
+ }
176
+ return undefined;
177
+ };