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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +57 -4
  3. package/lib/App.d.ts +230 -0
  4. package/lib/App.d.ts.map +1 -0
  5. package/lib/App.js +338 -0
  6. package/lib/App.js.map +1 -0
  7. package/lib/AuthProvider.d.ts +22 -0
  8. package/lib/AuthProvider.d.ts.map +1 -0
  9. package/lib/AuthProvider.js +48 -0
  10. package/lib/AuthProvider.js.map +1 -0
  11. package/lib/BindService.d.ts +159 -0
  12. package/lib/BindService.d.ts.map +1 -0
  13. package/lib/BindService.js +222 -0
  14. package/lib/BindService.js.map +1 -0
  15. package/lib/Bootstrap.d.ts +8 -0
  16. package/lib/Bootstrap.d.ts.map +1 -0
  17. package/lib/Bootstrap.js +41 -0
  18. package/lib/Bootstrap.js.map +1 -0
  19. package/lib/Bucket.d.ts +278 -0
  20. package/lib/Bucket.d.ts.map +1 -0
  21. package/lib/Bucket.js +658 -0
  22. package/lib/Bucket.js.map +1 -0
  23. package/lib/BucketBinding.d.ts +33 -0
  24. package/lib/BucketBinding.d.ts.map +1 -0
  25. package/lib/BucketBinding.js +70 -0
  26. package/lib/BucketBinding.js.map +1 -0
  27. package/lib/Catalog.d.ts +28 -0
  28. package/lib/Catalog.d.ts.map +1 -0
  29. package/lib/Catalog.js +31 -0
  30. package/lib/Catalog.js.map +1 -0
  31. package/lib/Certificate.d.ts +189 -0
  32. package/lib/Certificate.d.ts.map +1 -0
  33. package/lib/Certificate.js +380 -0
  34. package/lib/Certificate.js.map +1 -0
  35. package/lib/Checkpoint.d.ts +55 -0
  36. package/lib/Checkpoint.d.ts.map +1 -0
  37. package/lib/Checkpoint.js +3 -0
  38. package/lib/Checkpoint.js.map +1 -0
  39. package/lib/CheckpointHttp.d.ts +22 -0
  40. package/lib/CheckpointHttp.d.ts.map +1 -0
  41. package/lib/CheckpointHttp.js +53 -0
  42. package/lib/CheckpointHttp.js.map +1 -0
  43. package/lib/ConnectPostgres.d.ts +58 -0
  44. package/lib/ConnectPostgres.d.ts.map +1 -0
  45. package/lib/ConnectPostgres.js +13 -0
  46. package/lib/ConnectPostgres.js.map +1 -0
  47. package/lib/ConnectPostgresHttp.d.ts +26 -0
  48. package/lib/ConnectPostgresHttp.d.ts.map +1 -0
  49. package/lib/ConnectPostgresHttp.js +57 -0
  50. package/lib/ConnectPostgresHttp.js.map +1 -0
  51. package/lib/Contributions.d.ts +7 -0
  52. package/lib/Contributions.d.ts.map +1 -0
  53. package/lib/Contributions.js +6 -0
  54. package/lib/Contributions.js.map +1 -0
  55. package/lib/Credentials.d.ts +33 -0
  56. package/lib/Credentials.d.ts.map +1 -0
  57. package/lib/Credentials.js +55 -0
  58. package/lib/Credentials.js.map +1 -0
  59. package/lib/Decrypt.d.ts +52 -0
  60. package/lib/Decrypt.d.ts.map +1 -0
  61. package/lib/Decrypt.js +3 -0
  62. package/lib/Decrypt.js.map +1 -0
  63. package/lib/DecryptHttp.d.ts +22 -0
  64. package/lib/DecryptHttp.d.ts.map +1 -0
  65. package/lib/DecryptHttp.js +43 -0
  66. package/lib/DecryptHttp.js.map +1 -0
  67. package/lib/DeleteObject.d.ts +29 -0
  68. package/lib/DeleteObject.d.ts.map +1 -0
  69. package/lib/DeleteObject.js +3 -0
  70. package/lib/DeleteObject.js.map +1 -0
  71. package/lib/DeleteObjectHttp.d.ts +12 -0
  72. package/lib/DeleteObjectHttp.d.ts.map +1 -0
  73. package/lib/DeleteObjectHttp.js +17 -0
  74. package/lib/DeleteObjectHttp.js.map +1 -0
  75. package/lib/Deployment.d.ts +51 -0
  76. package/lib/Deployment.d.ts.map +1 -0
  77. package/lib/Deployment.js +62 -0
  78. package/lib/Deployment.js.map +1 -0
  79. package/lib/DeploymentImages.d.ts +18 -0
  80. package/lib/DeploymentImages.d.ts.map +1 -0
  81. package/lib/DeploymentImages.js +61 -0
  82. package/lib/DeploymentImages.js.map +1 -0
  83. package/lib/DeploymentState.d.ts +17 -0
  84. package/lib/DeploymentState.d.ts.map +1 -0
  85. package/lib/DeploymentState.js +87 -0
  86. package/lib/DeploymentState.js.map +1 -0
  87. package/lib/Encrypt.d.ts +50 -0
  88. package/lib/Encrypt.d.ts.map +1 -0
  89. package/lib/Encrypt.js +3 -0
  90. package/lib/Encrypt.js.map +1 -0
  91. package/lib/EncryptHttp.d.ts +22 -0
  92. package/lib/EncryptHttp.d.ts.map +1 -0
  93. package/lib/EncryptHttp.js +39 -0
  94. package/lib/EncryptHttp.js.map +1 -0
  95. package/lib/Environment.d.ts +45 -0
  96. package/lib/Environment.d.ts.map +1 -0
  97. package/lib/Environment.js +43 -0
  98. package/lib/Environment.js.map +1 -0
  99. package/lib/Errors.d.ts +18 -0
  100. package/lib/Errors.d.ts.map +1 -0
  101. package/lib/Errors.js +13 -0
  102. package/lib/Errors.js.map +1 -0
  103. package/lib/Exec.d.ts +41 -0
  104. package/lib/Exec.d.ts.map +1 -0
  105. package/lib/Exec.js +3 -0
  106. package/lib/Exec.js.map +1 -0
  107. package/lib/ExecHttp.d.ts +22 -0
  108. package/lib/ExecHttp.d.ts.map +1 -0
  109. package/lib/ExecHttp.js +39 -0
  110. package/lib/ExecHttp.js.map +1 -0
  111. package/lib/GetObject.d.ts +34 -0
  112. package/lib/GetObject.d.ts.map +1 -0
  113. package/lib/GetObject.js +3 -0
  114. package/lib/GetObject.js.map +1 -0
  115. package/lib/GetObjectHttp.d.ts +12 -0
  116. package/lib/GetObjectHttp.d.ts.map +1 -0
  117. package/lib/GetObjectHttp.js +17 -0
  118. package/lib/GetObjectHttp.js.map +1 -0
  119. package/lib/GetSecret.d.ts +44 -0
  120. package/lib/GetSecret.d.ts.map +1 -0
  121. package/lib/GetSecret.js +3 -0
  122. package/lib/GetSecret.js.map +1 -0
  123. package/lib/GetSecretHttp.d.ts +22 -0
  124. package/lib/GetSecretHttp.d.ts.map +1 -0
  125. package/lib/GetSecretHttp.js +50 -0
  126. package/lib/GetSecretHttp.js.map +1 -0
  127. package/lib/HeadObject.d.ts +29 -0
  128. package/lib/HeadObject.d.ts.map +1 -0
  129. package/lib/HeadObject.js +3 -0
  130. package/lib/HeadObject.js.map +1 -0
  131. package/lib/HeadObjectHttp.d.ts +12 -0
  132. package/lib/HeadObjectHttp.d.ts.map +1 -0
  133. package/lib/HeadObjectHttp.js +17 -0
  134. package/lib/HeadObjectHttp.js.map +1 -0
  135. package/lib/IpAssignment.d.ts +258 -0
  136. package/lib/IpAssignment.d.ts.map +1 -0
  137. package/lib/IpAssignment.js +376 -0
  138. package/lib/IpAssignment.js.map +1 -0
  139. package/lib/ListObjectsV2.d.ts +29 -0
  140. package/lib/ListObjectsV2.d.ts.map +1 -0
  141. package/lib/ListObjectsV2.js +3 -0
  142. package/lib/ListObjectsV2.js.map +1 -0
  143. package/lib/ListObjectsV2Http.d.ts +12 -0
  144. package/lib/ListObjectsV2Http.d.ts.map +1 -0
  145. package/lib/ListObjectsV2Http.js +17 -0
  146. package/lib/ListObjectsV2Http.js.map +1 -0
  147. package/lib/ListSecrets.d.ts +53 -0
  148. package/lib/ListSecrets.d.ts.map +1 -0
  149. package/lib/ListSecrets.js +3 -0
  150. package/lib/ListSecrets.js.map +1 -0
  151. package/lib/ListSecretsHttp.d.ts +22 -0
  152. package/lib/ListSecretsHttp.d.ts.map +1 -0
  153. package/lib/ListSecretsHttp.js +35 -0
  154. package/lib/ListSecretsHttp.js.map +1 -0
  155. package/lib/Machine.d.ts +802 -0
  156. package/lib/Machine.d.ts.map +1 -0
  157. package/lib/Machine.js +773 -0
  158. package/lib/Machine.js.map +1 -0
  159. package/lib/MachineContainers.d.ts +44 -0
  160. package/lib/MachineContainers.d.ts.map +1 -0
  161. package/lib/MachineContainers.js +115 -0
  162. package/lib/MachineContainers.js.map +1 -0
  163. package/lib/Metadata.d.ts +109 -0
  164. package/lib/Metadata.d.ts.map +1 -0
  165. package/lib/Metadata.js +159 -0
  166. package/lib/Metadata.js.map +1 -0
  167. package/lib/MountVolume.d.ts +295 -0
  168. package/lib/MountVolume.d.ts.map +1 -0
  169. package/lib/MountVolume.js +20 -0
  170. package/lib/MountVolume.js.map +1 -0
  171. package/lib/Postgres.d.ts +298 -0
  172. package/lib/Postgres.d.ts.map +1 -0
  173. package/lib/Postgres.js +508 -0
  174. package/lib/Postgres.js.map +1 -0
  175. package/lib/PostgresMigrations.d.ts +20 -0
  176. package/lib/PostgresMigrations.d.ts.map +1 -0
  177. package/lib/PostgresMigrations.js +58 -0
  178. package/lib/PostgresMigrations.js.map +1 -0
  179. package/lib/Providers.d.ts +38 -0
  180. package/lib/Providers.d.ts.map +1 -0
  181. package/lib/Providers.js +95 -0
  182. package/lib/Providers.js.map +1 -0
  183. package/lib/PutObject.d.ts +35 -0
  184. package/lib/PutObject.d.ts.map +1 -0
  185. package/lib/PutObject.js +3 -0
  186. package/lib/PutObject.js.map +1 -0
  187. package/lib/PutObjectHttp.d.ts +12 -0
  188. package/lib/PutObjectHttp.d.ts.map +1 -0
  189. package/lib/PutObjectHttp.js +17 -0
  190. package/lib/PutObjectHttp.js.map +1 -0
  191. package/lib/ReadRedis.d.ts +26 -0
  192. package/lib/ReadRedis.d.ts.map +1 -0
  193. package/lib/ReadRedis.js +3 -0
  194. package/lib/ReadRedis.js.map +1 -0
  195. package/lib/ReadRedisHttp.d.ts +11 -0
  196. package/lib/ReadRedisHttp.d.ts.map +1 -0
  197. package/lib/ReadRedisHttp.js +15 -0
  198. package/lib/ReadRedisHttp.js.map +1 -0
  199. package/lib/ReadWriteRedis.d.ts +29 -0
  200. package/lib/ReadWriteRedis.d.ts.map +1 -0
  201. package/lib/ReadWriteRedis.js +3 -0
  202. package/lib/ReadWriteRedis.js.map +1 -0
  203. package/lib/ReadWriteRedisHttp.d.ts +11 -0
  204. package/lib/ReadWriteRedisHttp.d.ts.map +1 -0
  205. package/lib/ReadWriteRedisHttp.js +15 -0
  206. package/lib/ReadWriteRedisHttp.js.map +1 -0
  207. package/lib/Redis.d.ts +252 -0
  208. package/lib/Redis.d.ts.map +1 -0
  209. package/lib/Redis.js +611 -0
  210. package/lib/Redis.js.map +1 -0
  211. package/lib/RedisBinding.d.ts +7 -0
  212. package/lib/RedisBinding.d.ts.map +1 -0
  213. package/lib/RedisBinding.js +53 -0
  214. package/lib/RedisBinding.js.map +1 -0
  215. package/lib/RedisHttp.d.ts +8 -0
  216. package/lib/RedisHttp.d.ts.map +1 -0
  217. package/lib/RedisHttp.js +11 -0
  218. package/lib/RedisHttp.js.map +1 -0
  219. package/lib/Region.d.ts +16 -0
  220. package/lib/Region.d.ts.map +1 -0
  221. package/lib/Region.js +13 -0
  222. package/lib/Region.js.map +1 -0
  223. package/lib/Secret.d.ts +190 -0
  224. package/lib/Secret.d.ts.map +1 -0
  225. package/lib/Secret.js +310 -0
  226. package/lib/Secret.js.map +1 -0
  227. package/lib/SecretHttp.d.ts +54 -0
  228. package/lib/SecretHttp.d.ts.map +1 -0
  229. package/lib/SecretHttp.js +66 -0
  230. package/lib/SecretHttp.js.map +1 -0
  231. package/lib/SecretKey.d.ts +164 -0
  232. package/lib/SecretKey.d.ts.map +1 -0
  233. package/lib/SecretKey.js +277 -0
  234. package/lib/SecretKey.js.map +1 -0
  235. package/lib/SecretKeyHttp.d.ts +14 -0
  236. package/lib/SecretKeyHttp.d.ts.map +1 -0
  237. package/lib/SecretKeyHttp.js +5 -0
  238. package/lib/SecretKeyHttp.js.map +1 -0
  239. package/lib/Service.d.ts +1017 -0
  240. package/lib/Service.d.ts.map +1 -0
  241. package/lib/Service.js +1430 -0
  242. package/lib/Service.js.map +1 -0
  243. package/lib/Sign.d.ts +36 -0
  244. package/lib/Sign.d.ts.map +1 -0
  245. package/lib/Sign.js +3 -0
  246. package/lib/Sign.js.map +1 -0
  247. package/lib/SignHttp.d.ts +22 -0
  248. package/lib/SignHttp.d.ts.map +1 -0
  249. package/lib/SignHttp.js +36 -0
  250. package/lib/SignHttp.js.map +1 -0
  251. package/lib/Sprite.d.ts +283 -0
  252. package/lib/Sprite.d.ts.map +1 -0
  253. package/lib/Sprite.js +471 -0
  254. package/lib/Sprite.js.map +1 -0
  255. package/lib/SpriteHttp.d.ts +25 -0
  256. package/lib/SpriteHttp.d.ts.map +1 -0
  257. package/lib/SpriteHttp.js +33 -0
  258. package/lib/SpriteHttp.js.map +1 -0
  259. package/lib/Verify.d.ts +37 -0
  260. package/lib/Verify.d.ts.map +1 -0
  261. package/lib/Verify.js +3 -0
  262. package/lib/Verify.js.map +1 -0
  263. package/lib/VerifyHttp.d.ts +22 -0
  264. package/lib/VerifyHttp.d.ts.map +1 -0
  265. package/lib/VerifyHttp.js +38 -0
  266. package/lib/VerifyHttp.js.map +1 -0
  267. package/lib/Volume.d.ts +53 -0
  268. package/lib/Volume.d.ts.map +1 -0
  269. package/lib/Volume.js +188 -0
  270. package/lib/Volume.js.map +1 -0
  271. package/lib/VolumeSnapshot.d.ts +135 -0
  272. package/lib/VolumeSnapshot.d.ts.map +1 -0
  273. package/lib/VolumeSnapshot.js +213 -0
  274. package/lib/VolumeSnapshot.js.map +1 -0
  275. package/lib/Website/AssetDeployment.d.ts +43 -0
  276. package/lib/Website/AssetDeployment.d.ts.map +1 -0
  277. package/lib/Website/AssetDeployment.js +162 -0
  278. package/lib/Website/AssetDeployment.js.map +1 -0
  279. package/lib/Website/Astro.d.ts +89 -0
  280. package/lib/Website/Astro.d.ts.map +1 -0
  281. package/lib/Website/Astro.js +54 -0
  282. package/lib/Website/Astro.js.map +1 -0
  283. package/lib/Website/Foldkit.d.ts +52 -0
  284. package/lib/Website/Foldkit.d.ts.map +1 -0
  285. package/lib/Website/Foldkit.js +45 -0
  286. package/lib/Website/Foldkit.js.map +1 -0
  287. package/lib/Website/FrameworkSite.d.ts +212 -0
  288. package/lib/Website/FrameworkSite.d.ts.map +1 -0
  289. package/lib/Website/FrameworkSite.js +205 -0
  290. package/lib/Website/FrameworkSite.js.map +1 -0
  291. package/lib/Website/Nextjs.d.ts +54 -0
  292. package/lib/Website/Nextjs.d.ts.map +1 -0
  293. package/lib/Website/Nextjs.js +46 -0
  294. package/lib/Website/Nextjs.js.map +1 -0
  295. package/lib/Website/Nuxt.d.ts +51 -0
  296. package/lib/Website/Nuxt.d.ts.map +1 -0
  297. package/lib/Website/Nuxt.js +36 -0
  298. package/lib/Website/Nuxt.js.map +1 -0
  299. package/lib/Website/Octane.d.ts +49 -0
  300. package/lib/Website/Octane.d.ts.map +1 -0
  301. package/lib/Website/Octane.js +39 -0
  302. package/lib/Website/Octane.js.map +1 -0
  303. package/lib/Website/ReactRouter.d.ts +80 -0
  304. package/lib/Website/ReactRouter.d.ts.map +1 -0
  305. package/lib/Website/ReactRouter.js +70 -0
  306. package/lib/Website/ReactRouter.js.map +1 -0
  307. package/lib/Website/SolidStart.d.ts +93 -0
  308. package/lib/Website/SolidStart.d.ts.map +1 -0
  309. package/lib/Website/SolidStart.js +71 -0
  310. package/lib/Website/SolidStart.js.map +1 -0
  311. package/lib/Website/StaticSite.d.ts +162 -0
  312. package/lib/Website/StaticSite.d.ts.map +1 -0
  313. package/lib/Website/StaticSite.js +180 -0
  314. package/lib/Website/StaticSite.js.map +1 -0
  315. package/lib/Website/SvelteKit.d.ts +52 -0
  316. package/lib/Website/SvelteKit.d.ts.map +1 -0
  317. package/lib/Website/SvelteKit.js +37 -0
  318. package/lib/Website/SvelteKit.js.map +1 -0
  319. package/lib/Website/TanStackStart.d.ts +76 -0
  320. package/lib/Website/TanStackStart.d.ts.map +1 -0
  321. package/lib/Website/TanStackStart.js +66 -0
  322. package/lib/Website/TanStackStart.js.map +1 -0
  323. package/lib/Website/Vinext.d.ts +73 -0
  324. package/lib/Website/Vinext.d.ts.map +1 -0
  325. package/lib/Website/Vinext.js +67 -0
  326. package/lib/Website/Vinext.js.map +1 -0
  327. package/lib/Website/Vite.d.ts +112 -0
  328. package/lib/Website/Vite.d.ts.map +1 -0
  329. package/lib/Website/Vite.js +100 -0
  330. package/lib/Website/Vite.js.map +1 -0
  331. package/lib/Website/Vocs.d.ts +52 -0
  332. package/lib/Website/Vocs.d.ts.map +1 -0
  333. package/lib/Website/Vocs.js +38 -0
  334. package/lib/Website/Vocs.js.map +1 -0
  335. package/lib/Website/Waku.d.ts +64 -0
  336. package/lib/Website/Waku.d.ts.map +1 -0
  337. package/lib/Website/Waku.js +39 -0
  338. package/lib/Website/Waku.js.map +1 -0
  339. package/lib/Website/index.d.ts +17 -0
  340. package/lib/Website/index.d.ts.map +1 -0
  341. package/lib/Website/index.js +17 -0
  342. package/lib/Website/index.js.map +1 -0
  343. package/lib/WriteCertificates.d.ts +63 -0
  344. package/lib/WriteCertificates.d.ts.map +1 -0
  345. package/lib/WriteCertificates.js +3 -0
  346. package/lib/WriteCertificates.js.map +1 -0
  347. package/lib/WriteCertificatesHttp.d.ts +25 -0
  348. package/lib/WriteCertificatesHttp.d.ts.map +1 -0
  349. package/lib/WriteCertificatesHttp.js +67 -0
  350. package/lib/WriteCertificatesHttp.js.map +1 -0
  351. package/lib/WriteRedis.d.ts +26 -0
  352. package/lib/WriteRedis.d.ts.map +1 -0
  353. package/lib/WriteRedis.js +3 -0
  354. package/lib/WriteRedis.js.map +1 -0
  355. package/lib/WriteRedisHttp.d.ts +11 -0
  356. package/lib/WriteRedisHttp.d.ts.map +1 -0
  357. package/lib/WriteRedisHttp.js +15 -0
  358. package/lib/WriteRedisHttp.js.map +1 -0
  359. package/lib/WriteSecret.d.ts +68 -0
  360. package/lib/WriteSecret.d.ts.map +1 -0
  361. package/lib/WriteSecret.js +4 -0
  362. package/lib/WriteSecret.js.map +1 -0
  363. package/lib/WriteSecretHttp.d.ts +26 -0
  364. package/lib/WriteSecretHttp.d.ts.map +1 -0
  365. package/lib/WriteSecretHttp.js +54 -0
  366. package/lib/WriteSecretHttp.js.map +1 -0
  367. package/lib/bluegreen.d.ts +36 -0
  368. package/lib/bluegreen.d.ts.map +1 -0
  369. package/lib/bluegreen.js +460 -0
  370. package/lib/bluegreen.js.map +1 -0
  371. package/lib/hosted.d.ts +171 -0
  372. package/lib/hosted.d.ts.map +1 -0
  373. package/lib/hosted.js +458 -0
  374. package/lib/hosted.js.map +1 -0
  375. package/lib/index.d.ts +65 -0
  376. package/lib/index.d.ts.map +1 -0
  377. package/lib/index.js +63 -0
  378. package/lib/index.js.map +1 -0
  379. package/lib/internal/RemoteBuilder.d.ts +28 -0
  380. package/lib/internal/RemoteBuilder.d.ts.map +1 -0
  381. package/lib/internal/RemoteBuilder.js +158 -0
  382. package/lib/internal/RemoteBuilder.js.map +1 -0
  383. package/lib/leases.d.ts +53 -0
  384. package/lib/leases.d.ts.map +1 -0
  385. package/lib/leases.js +279 -0
  386. package/lib/leases.js.map +1 -0
  387. package/lib/ports.d.ts +51 -0
  388. package/lib/ports.d.ts.map +1 -0
  389. package/lib/ports.js +123 -0
  390. package/lib/ports.js.map +1 -0
  391. package/lib/replicas.d.ts +270 -0
  392. package/lib/replicas.d.ts.map +1 -0
  393. package/lib/replicas.js +969 -0
  394. package/lib/replicas.js.map +1 -0
  395. package/lib/rpc.d.ts +35 -0
  396. package/lib/rpc.d.ts.map +1 -0
  397. package/lib/rpc.js +113 -0
  398. package/lib/rpc.js.map +1 -0
  399. package/package.json +83 -3
  400. package/src/App.ts +514 -0
  401. package/src/AuthProvider.ts +68 -0
  402. package/src/BindService.ts +303 -0
  403. package/src/Bootstrap.ts +66 -0
  404. package/src/Bucket.ts +918 -0
  405. package/src/BucketBinding.ts +128 -0
  406. package/src/Catalog.ts +43 -0
  407. package/src/Certificate.ts +548 -0
  408. package/src/Checkpoint.ts +69 -0
  409. package/src/CheckpointHttp.ts +66 -0
  410. package/src/ConnectPostgres.ts +68 -0
  411. package/src/ConnectPostgresHttp.ts +77 -0
  412. package/src/Contributions.ts +9 -0
  413. package/src/Credentials.ts +75 -0
  414. package/src/Decrypt.ts +62 -0
  415. package/src/DecryptHttp.ts +52 -0
  416. package/src/DeleteObject.ts +43 -0
  417. package/src/DeleteObjectHttp.ts +20 -0
  418. package/src/Deployment.ts +121 -0
  419. package/src/DeploymentImages.ts +84 -0
  420. package/src/DeploymentState.ts +104 -0
  421. package/src/Encrypt.ts +60 -0
  422. package/src/EncryptHttp.ts +48 -0
  423. package/src/Environment.ts +81 -0
  424. package/src/Errors.ts +14 -0
  425. package/src/Exec.ts +50 -0
  426. package/src/ExecHttp.ts +47 -0
  427. package/src/GetObject.ts +48 -0
  428. package/src/GetObjectHttp.ts +20 -0
  429. package/src/GetSecret.ts +48 -0
  430. package/src/GetSecretHttp.ts +60 -0
  431. package/src/HeadObject.ts +43 -0
  432. package/src/HeadObjectHttp.ts +20 -0
  433. package/src/IpAssignment.ts +522 -0
  434. package/src/ListObjectsV2.ts +43 -0
  435. package/src/ListObjectsV2Http.ts +20 -0
  436. package/src/ListSecrets.ts +57 -0
  437. package/src/ListSecretsHttp.ts +43 -0
  438. package/src/Machine.ts +1270 -0
  439. package/src/MachineContainers.ts +152 -0
  440. package/src/Metadata.ts +195 -0
  441. package/src/MountVolume.ts +315 -0
  442. package/src/Postgres.ts +777 -0
  443. package/src/PostgresMigrations.ts +93 -0
  444. package/src/Providers.ts +155 -0
  445. package/src/PutObject.ts +49 -0
  446. package/src/PutObjectHttp.ts +20 -0
  447. package/src/ReadRedis.ts +31 -0
  448. package/src/ReadRedisHttp.ts +18 -0
  449. package/src/ReadWriteRedis.ts +33 -0
  450. package/src/ReadWriteRedisHttp.ts +18 -0
  451. package/src/Redis.ts +823 -0
  452. package/src/RedisBinding.ts +64 -0
  453. package/src/RedisHttp.ts +14 -0
  454. package/src/Region.ts +44 -0
  455. package/src/Secret.ts +405 -0
  456. package/src/SecretHttp.ts +149 -0
  457. package/src/SecretKey.ts +389 -0
  458. package/src/SecretKeyHttp.ts +23 -0
  459. package/src/Service.ts +1968 -0
  460. package/src/Sign.ts +46 -0
  461. package/src/SignHttp.ts +44 -0
  462. package/src/Sprite.ts +673 -0
  463. package/src/SpriteHttp.ts +50 -0
  464. package/src/Verify.ts +47 -0
  465. package/src/VerifyHttp.ts +46 -0
  466. package/src/Volume.ts +264 -0
  467. package/src/VolumeSnapshot.ts +321 -0
  468. package/src/Website/AssetDeployment.ts +292 -0
  469. package/src/Website/Astro.ts +92 -0
  470. package/src/Website/Foldkit.ts +54 -0
  471. package/src/Website/FrameworkSite.ts +449 -0
  472. package/src/Website/Nextjs.ts +50 -0
  473. package/src/Website/Nuxt.ts +48 -0
  474. package/src/Website/Octane.ts +44 -0
  475. package/src/Website/ReactRouter.ts +76 -0
  476. package/src/Website/SolidStart.ts +90 -0
  477. package/src/Website/StaticSite.ts +295 -0
  478. package/src/Website/SvelteKit.ts +49 -0
  479. package/src/Website/TanStackStart.ts +72 -0
  480. package/src/Website/Vinext.ts +79 -0
  481. package/src/Website/Vite.ts +121 -0
  482. package/src/Website/Vocs.ts +50 -0
  483. package/src/Website/Waku.ts +65 -0
  484. package/src/Website/index.ts +16 -0
  485. package/src/WriteCertificates.ts +90 -0
  486. package/src/WriteCertificatesHttp.ts +93 -0
  487. package/src/WriteRedis.ts +31 -0
  488. package/src/WriteRedisHttp.ts +18 -0
  489. package/src/WriteSecret.ts +86 -0
  490. package/src/WriteSecretHttp.ts +71 -0
  491. package/src/bluegreen.ts +711 -0
  492. package/src/globals.d.ts +2 -0
  493. package/src/hosted.ts +667 -0
  494. package/src/index.ts +64 -0
  495. package/src/internal/RemoteBuilder.ts +242 -0
  496. package/src/leases.ts +437 -0
  497. package/src/ports.ts +177 -0
  498. package/src/replicas.ts +1480 -0
  499. package/src/rpc.ts +136 -0
@@ -0,0 +1,2 @@
1
+ // `globalThis.__ALCHEMY_RUNTIME__`, declared by alchemy's Phase module.
2
+ import type {} from "alchemy/Phase";
package/src/hosted.ts ADDED
@@ -0,0 +1,667 @@
1
+ import type { Docker } from "@alchemy.run/docker/Docker";
2
+ import type { FlyMachineService } from "@distilled.cloud/fly-io/machines";
3
+ import * as machines from "@distilled.cloud/fly-io/machines";
4
+ import * as Bundle from "alchemy/Bundle/Bundle";
5
+ import {
6
+ matchesPackageRoot,
7
+ normalizeInstallTargets,
8
+ resolvePackageInstallIdentity,
9
+ type PackageInstall,
10
+ } from "alchemy/Bundle/InstalledPackages";
11
+ import { findCwdForBundle, getStableContextDir, resolveMainPath } from "alchemy/Bundle/TempRoot";
12
+ import { safeHttpEffect } from "alchemy/Http";
13
+ import type { ResourceBinding } from "alchemy/Resource";
14
+ import { createContainerRuntimeContext, type HostRuntimeContext } from "alchemy/Runtime/Process";
15
+ import {
16
+ copyExtraFiles,
17
+ contextRootOf,
18
+ extraFileDestination,
19
+ hashExtraFiles,
20
+ isContextRootDest,
21
+ posixRelUnder,
22
+ resolveExtraSource,
23
+ type ExtraFile,
24
+ } from "alchemy/Util/extraFiles";
25
+ import { sha256, sha256Object } from "alchemy/Util/sha256";
26
+ import * as Data from "effect/Data";
27
+ import * as Effect from "effect/Effect";
28
+ import * as FileSystem from "effect/FileSystem";
29
+ import * as Path from "effect/Path";
30
+ import * as Redacted from "effect/Redacted";
31
+ import * as Schedule from "effect/Schedule";
32
+ import type * as rolldown from "rolldown";
33
+ import { buildOnRemoteBuilder } from "./internal/RemoteBuilder.ts";
34
+ import type { BoundTarget, DiskSpec, ServiceBinding } from "./MountVolume.ts";
35
+ import { rpcMethodsOf, serveFlyRpc } from "./rpc.ts";
36
+
37
+ export type FlyHostRuntimeContext = HostRuntimeContext;
38
+
39
+ /**
40
+ * Container runtime context for Fly hosts. It also serves the program's RPC
41
+ * methods to bound callers (see {@link serveFlyRpc}) and boots the HTTP
42
+ * server for a program that exposes methods but no `fetch`.
43
+ */
44
+ export const createFlyHostRuntimeContext =
45
+ (type: string) =>
46
+ (id: string): HostRuntimeContext => {
47
+ const base = createContainerRuntimeContext(type)(id);
48
+ const serveBase = base.serve;
49
+ const serve: HostRuntimeContext["serve"] = (handler, options) => {
50
+ const shape = options?.shape;
51
+ const methods = rpcMethodsOf(shape);
52
+ // `safeHttpEffect` also resolves a `fetch` given as an Effect that
53
+ // builds the handler.
54
+ const wrapped = serveFlyRpc(methods, safeHttpEffect(handler));
55
+ const boots =
56
+ shape === undefined || shape.fetch !== undefined || Object.keys(methods).length > 0;
57
+ return serveBase(
58
+ wrapped,
59
+ boots ? { shape: { ...shape, fetch: shape?.fetch ?? wrapped } } : options,
60
+ ) as Effect.Effect<void, never, any>;
61
+ };
62
+ return Object.assign(base, { serve });
63
+ };
64
+
65
+ export const FLY_REGISTRY = "registry.fly.io";
66
+ export const DEFAULT_BASE_IMAGE = "node:26-slim";
67
+ export const DEFAULT_PORT = 3000;
68
+ export const MACHINE_PLATFORM = "linux/amd64";
69
+
70
+ export interface FlyBuildOptions extends Bundle.BundleConfig {
71
+ /**
72
+ * Native or Node-only packages to install into the Machine image with
73
+ * `npm install` instead of bundling them. Same `build.install` shape as
74
+ * Lambda.
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * build: { install: ["sharp"] }
79
+ * ```
80
+ */
81
+ readonly install?: PackageInstall;
82
+ /**
83
+ * Build the image on Fly's remote builders (Depot), as `fly deploy` does,
84
+ * instead of with the local Docker engine. Only the build context is
85
+ * uploaded; the builder pulls the base image and pushes the result to
86
+ * `registry.fly.io` next to it. Set `false` to build and push locally.
87
+ * Either way, the local `docker buildx` client drives the build.
88
+ *
89
+ * @default true
90
+ */
91
+ readonly remote?: boolean;
92
+ }
93
+
94
+ export type { ExtraFile };
95
+
96
+ export interface HostedProgramProps {
97
+ main: string;
98
+ handler?: string;
99
+ port?: number;
100
+ image?: string;
101
+ env?: Record<string, any>;
102
+ isExternal?: boolean;
103
+ build?: FlyBuildOptions;
104
+ /**
105
+ * Extra host directories baked into the image (framework client
106
+ * assets, Next.js `.next`, …). Hashed into `code.hash` so asset
107
+ * changes rebuild the image.
108
+ */
109
+ extraFiles?: ReadonlyArray<ExtraFile>;
110
+ }
111
+
112
+ export { extraFileDestination };
113
+
114
+ const matchesConfiguredExternal = (
115
+ external: rolldown.InputOptions["external"],
116
+ moduleId: string,
117
+ parentId: string | undefined,
118
+ isResolved: boolean,
119
+ ): boolean => {
120
+ if (external === undefined) return false;
121
+ if (typeof external === "function") {
122
+ return external(moduleId, parentId, isResolved) === true;
123
+ }
124
+ const matchers = Array.isArray(external) ? external : [external];
125
+ return matchers.some((matcher) =>
126
+ typeof matcher === "string" ? matcher === moduleId : matcher.test(moduleId),
127
+ );
128
+ };
129
+
130
+ export class DeployTokenMissing extends Data.TaggedError("Fly.DeployTokenMissing")<{
131
+ appName: string;
132
+ }> {}
133
+
134
+ /**
135
+ * The generated entry for `Fly.Service` / `Fly.Sprite` machines: a shim
136
+ * importing only `@alchemy.run/fly/Bootstrap` plus the user's `main` —
137
+ * see that module for why the entry never imports alchemy's own
138
+ * dependencies. The runtime flag is raised BEFORE the user's module is
139
+ * evaluated (hence the dynamic import) so its module-scope code sees it.
140
+ */
141
+ const makeBunBootstrap =
142
+ (handler: string) =>
143
+ (importPath: string): string =>
144
+ `
145
+ import { bootstrap } from "@alchemy.run/fly/Bootstrap";
146
+
147
+ globalThis.__ALCHEMY_RUNTIME__ = true;
148
+ const { ${handler}: entrypoint } = await import(${JSON.stringify(importPath)});
149
+
150
+ await bootstrap(entrypoint);
151
+ `;
152
+
153
+ /** Unwrap env inputs while preserving serialized RuntimeContext markers. */
154
+ export const plainEnvValue = (value: unknown): string | undefined => {
155
+ if (value === undefined || value === null) return undefined;
156
+ if (Redacted.isRedacted(value)) return value.pipe(Redacted.value, plainEnvValue);
157
+ if (typeof value === "string") {
158
+ return value.length > 0 ? value : undefined;
159
+ }
160
+ if (typeof value === "number" || typeof value === "boolean") {
161
+ return String(value);
162
+ }
163
+ return undefined;
164
+ };
165
+
166
+ export const toEnvRecord = (env: Record<string, any> | undefined): Record<string, string> =>
167
+ Object.fromEntries(
168
+ Object.entries(env ?? {}).flatMap(([key, value]) => {
169
+ const raw = plainEnvValue(value);
170
+ return raw === undefined ? [] : [[key, raw]];
171
+ }),
172
+ );
173
+
174
+ const coerceBindingName = (value: unknown): string | undefined => {
175
+ const direct = plainEnvValue(value);
176
+ if (direct !== undefined) return direct;
177
+ if (value != null && typeof value === "object") {
178
+ const record = value as { name?: unknown; id?: unknown; addOnId?: unknown };
179
+ return (
180
+ coerceBindingName(record.name) ??
181
+ coerceBindingName(record.id) ??
182
+ coerceBindingName(record.addOnId)
183
+ );
184
+ }
185
+ return undefined;
186
+ };
187
+
188
+ export const collectBindingState = (bindings: readonly ResourceBinding<ServiceBinding>[]) => {
189
+ const active = bindings.filter(
190
+ (binding: ResourceBinding<ServiceBinding> & { action?: string }) => binding.action !== "delete",
191
+ );
192
+ const env = toEnvRecord(
193
+ active
194
+ .map((binding) => binding?.data?.env)
195
+ .reduce<Record<string, any>>((acc, value) => ({ ...acc, ...value }), {}),
196
+ );
197
+ const mounts: DiskSpec[] = [];
198
+ const seen = new Set<string>();
199
+ const redis: { name: string; id?: string }[] = [];
200
+ const buckets: { name: string; id?: string; values?: Record<string, string> }[] = [];
201
+ const postgres: { clusterId: string; variableName?: string }[] = [];
202
+ const targets: BoundTarget[] = [];
203
+ for (const binding of active) {
204
+ const target = binding?.data?.target;
205
+ if (target !== undefined) targets.push(target);
206
+ for (const mount of binding?.data?.mounts ?? []) {
207
+ if (seen.has(mount.path)) continue;
208
+ seen.add(mount.path);
209
+ mounts.push(mount);
210
+ }
211
+ const attached = binding?.data?.redis;
212
+ const redisName = coerceBindingName(attached?.name);
213
+ const redisId = coerceBindingName(attached?.id);
214
+ if (redisName !== undefined || redisId !== undefined) {
215
+ redis.push({ name: redisName ?? "", id: redisId });
216
+ }
217
+ const bucket = binding?.data?.bucket as
218
+ | {
219
+ name?: unknown;
220
+ id?: unknown;
221
+ addOnId?: unknown;
222
+ bucketName?: unknown;
223
+ accessKeyId?: unknown;
224
+ secretAccessKey?: unknown;
225
+ endpoint?: unknown;
226
+ region?: unknown;
227
+ }
228
+ | undefined;
229
+ const bucketName = coerceBindingName(bucket?.name);
230
+ const bucketId = coerceBindingName(bucket?.id) ?? coerceBindingName(bucket?.addOnId);
231
+ if (bucketName !== undefined || bucketId !== undefined) {
232
+ // The bound Bucket's attributes carry the create-time Tigris
233
+ // credentials, which Fly's add-on lookup often returns empty.
234
+ const values: Record<string, string> = {};
235
+ for (const [key, value] of [
236
+ ["BUCKET_NAME", bucket?.bucketName],
237
+ ["AWS_ACCESS_KEY_ID", bucket?.accessKeyId],
238
+ ["AWS_SECRET_ACCESS_KEY", bucket?.secretAccessKey],
239
+ ["AWS_ENDPOINT_URL_S3", bucket?.endpoint],
240
+ ["AWS_REGION", bucket?.region],
241
+ ] as const) {
242
+ const plain = plainEnvValue(value);
243
+ if (plain !== undefined) values[key] = plain;
244
+ }
245
+ buckets.push({ name: bucketName ?? "", id: bucketId, values });
246
+ }
247
+ const pg = binding?.data?.postgres;
248
+ const clusterId = coerceBindingName(pg?.clusterId);
249
+ if (clusterId !== undefined) {
250
+ postgres.push({
251
+ clusterId,
252
+ variableName:
253
+ typeof pg?.variableName === "string" && pg.variableName.length > 0
254
+ ? pg.variableName
255
+ : undefined,
256
+ });
257
+ }
258
+ }
259
+ return { env, mounts, redis, buckets, postgres, targets };
260
+ };
261
+
262
+ /**
263
+ * HTTP 80 → HTTPS redirect plus HTTPS 443 for public Services. Private
264
+ * (Flycast-only) Services publish plain HTTP on 80: Fly issues no
265
+ * certificate for `.flycast`, so a redirect to HTTPS would break callers.
266
+ */
267
+ export const defaultHttpServices = (
268
+ port: number,
269
+ count = 1,
270
+ isPublic = true,
271
+ ): FlyMachineService[] => [
272
+ {
273
+ protocol: "tcp",
274
+ internal_port: port,
275
+ autostart: true,
276
+ autostop: "off",
277
+ min_machines_running: count,
278
+ ports: isPublic
279
+ ? [
280
+ { port: 80, handlers: ["http"], force_https: true },
281
+ { port: 443, handlers: ["tls", "http"] },
282
+ ]
283
+ : [{ port: 80, handlers: ["http"] }],
284
+ // Wait until the process is listening before the proxy sends traffic.
285
+ // Without this, fly.dev hangs (status 0) while Node is still booting.
286
+ checks: [{ type: "tcp", port, interval: "10s", timeout: "2s", grace_period: "30s" }],
287
+ },
288
+ ];
289
+
290
+ const sanitizeImageRepo = (id: string): string => {
291
+ const lowered = id
292
+ .toLowerCase()
293
+ .replace(/[^a-z0-9_.-]+/g, "-")
294
+ .replace(/^-+|-+$/g, "");
295
+ return lowered.length === 0 ? "service" : lowered;
296
+ };
297
+
298
+ const generateDockerfile = (
299
+ props: HostedProgramProps,
300
+ hasChunks: boolean,
301
+ install?: Record<string, string>,
302
+ entryRel?: string,
303
+ ) => {
304
+ const port = props.port ?? DEFAULT_PORT;
305
+ const lines = [`FROM ${props.image ?? DEFAULT_BASE_IMAGE}`, `WORKDIR /app`];
306
+ if (install !== undefined && Object.keys(install).length > 0) {
307
+ lines.push(
308
+ `COPY package.json /app/package.json`,
309
+ `RUN npm install --omit=dev --no-fund --no-audit`,
310
+ );
311
+ }
312
+ if (props.isExternal === true) {
313
+ lines.push(`COPY . /app`);
314
+ const entry = entryRel !== undefined && entryRel.length > 0 ? entryRel : "serve-node.mjs";
315
+ lines.push(
316
+ `ENV PORT=${String(port)}`,
317
+ `ENV HOST=0.0.0.0`,
318
+ `EXPOSE ${String(port)}`,
319
+ `ENTRYPOINT ["node", ${JSON.stringify(`/app/${entry}`)}]`,
320
+ );
321
+ return `${lines.join("\n")}\n`;
322
+ }
323
+ lines.push(`COPY index.mjs /app/index.mjs`);
324
+ if (hasChunks) {
325
+ lines.push(`COPY *.js /app/`);
326
+ }
327
+ const seen = new Set<string>();
328
+ for (const extra of props.extraFiles ?? []) {
329
+ const dest = extraFileDestination(extra.dest);
330
+ if (isContextRootDest(dest) || seen.has(dest)) continue;
331
+ seen.add(dest);
332
+ lines.push(`COPY ${dest} /app/${dest}`);
333
+ }
334
+ lines.push(
335
+ `ENV PORT=${String(port)}`,
336
+ `ENV HOST=0.0.0.0`,
337
+ `EXPOSE ${String(port)}`,
338
+ `ENTRYPOINT ["node", "/app/index.mjs"]`,
339
+ );
340
+ return `${lines.join("\n")}\n`;
341
+ };
342
+
343
+ const installManifest = (dependencies: Record<string, string>) =>
344
+ `${JSON.stringify({ private: true, type: "module", dependencies }, null, 2)}\n`;
345
+
346
+ export const createFlyHostedSupport = ({
347
+ stackName,
348
+ stage,
349
+ virtualEntryPlugin,
350
+ docker,
351
+ dotAlchemy,
352
+ }: {
353
+ stackName: string;
354
+ stage: string;
355
+ virtualEntryPlugin: (content: (importPath: string) => string) => rolldown.Plugin;
356
+ docker: Docker["Service"];
357
+ dotAlchemy: string;
358
+ }) => {
359
+ const alchemyEnv = {
360
+ ALCHEMY_STACK_NAME: stackName,
361
+ ALCHEMY_STAGE: stage,
362
+ ALCHEMY_PHASE: "runtime",
363
+ HOST: "0.0.0.0",
364
+ };
365
+
366
+ const bundleProgram = Effect.fn(function* (props: HostedProgramProps) {
367
+ const handler = props.handler ?? "default";
368
+ const realMain = yield* resolveMainPath(props.main);
369
+ const cwd = yield* findCwdForBundle(realMain);
370
+ const bootstrap = makeBunBootstrap(handler);
371
+ const requested = yield* normalizeInstallTargets(props.build?.install);
372
+ const installRoots = new Set(Object.keys(requested));
373
+ const configuredExternal = props.build?.input?.external;
374
+
375
+ const buildBundle = Effect.fn(function* (
376
+ entry: string,
377
+ plugins?: rolldown.RolldownPluginOption,
378
+ ) {
379
+ return yield* Bundle.build(
380
+ {
381
+ ...props.build?.input,
382
+ input: entry,
383
+ cwd,
384
+ platform: "node",
385
+ external: (moduleId, parentId, isResolved) => {
386
+ if (moduleId === "bun" || moduleId.startsWith("bun:")) return true;
387
+ for (const root of installRoots) {
388
+ if (matchesPackageRoot(moduleId, root)) return true;
389
+ }
390
+ return matchesConfiguredExternal(configuredExternal, moduleId, parentId, isResolved);
391
+ },
392
+ resolve: {
393
+ conditionNames: [...Bundle.NODE_CONDITION_NAMES],
394
+ ...props.build?.input?.resolve,
395
+ },
396
+ plugins: [props.build?.input?.plugins, plugins],
397
+ },
398
+ {
399
+ ...props.build?.output,
400
+ format: "esm",
401
+ sourcemap: props.build?.output?.sourcemap ?? false,
402
+ entryFileNames: "index.mjs",
403
+ strictExecutionOrder: true,
404
+ keepNames: true,
405
+ },
406
+ props.build,
407
+ );
408
+ });
409
+
410
+ if (props.isExternal === true) {
411
+ const fs = yield* FileSystem.FileSystem;
412
+ const path = yield* Path.Path;
413
+ const bytes = yield* fs.readFile(realMain);
414
+ const hash = yield* sha256(bytes);
415
+ return { files: [{ path: path.basename(realMain), content: bytes }], hash };
416
+ }
417
+
418
+ const bundleOutput = yield* buildBundle(realMain, virtualEntryPlugin(bootstrap));
419
+
420
+ const files = bundleOutput.files.map((file) => ({
421
+ path: file.path,
422
+ content:
423
+ typeof file.content === "string" ? new TextEncoder().encode(file.content) : file.content,
424
+ }));
425
+
426
+ return { files, hash: bundleOutput.hash };
427
+ });
428
+
429
+ const computeCodeHash = Effect.fn(function* (props: HostedProgramProps) {
430
+ const bundled = yield* bundleProgram(props);
431
+ const realMain = yield* resolveMainPath(props.main);
432
+ const cwd = yield* findCwdForBundle(realMain);
433
+ const path = yield* Path.Path;
434
+ const requested = yield* normalizeInstallTargets(props.build?.install);
435
+ const identity =
436
+ Object.keys(requested).length > 0
437
+ ? yield* resolvePackageInstallIdentity({ cwd, requested })
438
+ : undefined;
439
+ const install =
440
+ identity !== undefined && Object.keys(identity.resolved).length > 0
441
+ ? identity.resolved
442
+ : undefined;
443
+ const packageJson = install === undefined ? undefined : installManifest(install);
444
+ const extras = (props.extraFiles ?? []).map((file) => ({
445
+ source: file.source,
446
+ dest: file.dest,
447
+ }));
448
+ const root = contextRootOf(realMain, extras, path, (source) =>
449
+ resolveExtraSource(source, path),
450
+ );
451
+ const entryRel =
452
+ props.isExternal === true
453
+ ? (posixRelUnder(root, realMain, path) ?? path.basename(realMain))
454
+ : undefined;
455
+ const dockerfile = generateDockerfile(props, bundled.files.length > 1, install, entryRel);
456
+ const extraFiles = yield* hashExtraFiles(props.extraFiles);
457
+ const codeHash = (yield* sha256Object({
458
+ bundleHash: bundled.hash,
459
+ dockerfile,
460
+ packageJson,
461
+ extraFiles,
462
+ extraFilesIncludesNodeModules: true,
463
+ })).slice(0, 16);
464
+ return { bundled, dockerfile, codeHash, packageJson, entryRel };
465
+ });
466
+
467
+ const imageExists = (imageRef: string) =>
468
+ docker.image.inspect(imageRef).pipe(
469
+ Effect.map(() => true),
470
+ Effect.catchReason("PlatformError", "NotFound", () => Effect.succeed(false)),
471
+ );
472
+
473
+ const pushBackoff = Schedule.exponential("2 seconds");
474
+
475
+ /**
476
+ * Bundle `main`, content-hash the image, build it when missing, and
477
+ * push to `registry.fly.io/{appName}:{logicalId}-{hash}` using an
478
+ * app deploy token. When `previousHash` matches, skip build and push.
479
+ *
480
+ * Fly's registry is app-scoped (`/v2/{app}/...`). A nested
481
+ * `{app}/{image}` repository 404s on blob upload.
482
+ */
483
+ const resolveImage = Effect.fn(function* (input: {
484
+ id: string;
485
+ appName: string;
486
+ props: HostedProgramProps;
487
+ previousHash?: string;
488
+ session?: { note: (message: string) => Effect.Effect<void> };
489
+ }) {
490
+ const note = input.session?.note ?? ((_message: string) => Effect.void);
491
+ yield* note(`Bundling ${input.id} program...`);
492
+ const { bundled, dockerfile, codeHash, packageJson } = yield* computeCodeHash(input.props);
493
+ yield* note(`Hashed ${input.id} (${codeHash})`);
494
+ const repo = sanitizeImageRepo(input.id);
495
+ const imageRef = `${FLY_REGISTRY}/${input.appName}:${repo}-${codeHash}`;
496
+
497
+ if (input.previousHash === codeHash) {
498
+ return { imageRef, codeHash };
499
+ }
500
+
501
+ const minted = yield* machines.createAppDeployToken({ app_name: input.appName });
502
+ const token =
503
+ minted.token === undefined || Redacted.isRedacted(minted.token)
504
+ ? minted.token
505
+ : Redacted.make(minted.token);
506
+ if (token === undefined || Redacted.value(token).length === 0) {
507
+ return yield* new DeployTokenMissing({ appName: input.appName });
508
+ }
509
+ const registry = { server: FLY_REGISTRY, username: "x", password: token };
510
+
511
+ const materialize = Effect.gen(function* () {
512
+ const realMain = yield* resolveMainPath(input.props.main);
513
+ const contextDir = yield* getStableContextDir(realMain, dotAlchemy, `${input.id}-image`);
514
+ const fs = yield* FileSystem.FileSystem;
515
+ const path = yield* Path.Path;
516
+ const files =
517
+ input.props.isExternal === true
518
+ ? packageJson !== undefined
519
+ ? [{ path: "package.json", content: new TextEncoder().encode(packageJson) }]
520
+ : []
521
+ : [
522
+ ...bundled.files.map((file, index) => ({
523
+ path: index === 0 ? "index.mjs" : file.path,
524
+ content: file.content,
525
+ })),
526
+ ...(packageJson !== undefined
527
+ ? [{ path: "package.json", content: new TextEncoder().encode(packageJson) }]
528
+ : []),
529
+ ];
530
+ yield* docker.materialize({ context: contextDir, dockerfile, files });
531
+ yield* copyExtraFiles(contextDir, input.props.extraFiles);
532
+ if (input.props.isExternal === true) {
533
+ const extras = (input.props.extraFiles ?? []).map((file) => ({
534
+ source: file.source,
535
+ dest: file.dest,
536
+ }));
537
+ const root = contextRootOf(realMain, extras, path, (source) =>
538
+ resolveExtraSource(source, path),
539
+ );
540
+ const entryRel = posixRelUnder(root, realMain, path) ?? path.basename(realMain);
541
+ const dest = path.join(contextDir, entryRel);
542
+ if (!(yield* fs.exists(dest).pipe(Effect.orElseSucceed(() => false)))) {
543
+ yield* fs.makeDirectory(path.dirname(dest), { recursive: true });
544
+ yield* fs.copy(realMain, dest, { overwrite: true });
545
+ }
546
+ }
547
+ return contextDir;
548
+ });
549
+
550
+ if (input.props.build?.remote !== false) {
551
+ const contextDir = yield* materialize;
552
+ yield* note(`Building ${imageRef} on a Fly remote builder...`);
553
+ yield* buildOnRemoteBuilder({
554
+ docker,
555
+ appName: input.appName,
556
+ contextDir,
557
+ imageRef,
558
+ platform: MACHINE_PLATFORM,
559
+ registry,
560
+ note,
561
+ });
562
+ yield* note(`Pushed ${imageRef}`);
563
+ return { imageRef, codeHash };
564
+ }
565
+
566
+ if (!(yield* imageExists(imageRef))) {
567
+ const contextDir = yield* materialize;
568
+ yield* note(`Building container image ${imageRef}...`);
569
+ yield* docker.image.build({ context: contextDir, tag: imageRef, platform: MACHINE_PLATFORM });
570
+ yield* note(`Built ${imageRef}`);
571
+ }
572
+
573
+ yield* note(`Pushing ${imageRef}...`);
574
+ yield* docker.image
575
+ .push(imageRef, registry)
576
+ .pipe(Effect.retry({ times: 3, schedule: pushBackoff }));
577
+ yield* note(`Pushed ${imageRef}`);
578
+ return { imageRef, codeHash };
579
+ });
580
+
581
+ const hash = Effect.fn(function* (props: HostedProgramProps) {
582
+ const { codeHash } = yield* computeCodeHash(props);
583
+ return codeHash;
584
+ });
585
+
586
+ return { alchemyEnv, bundleProgram, computeCodeHash, resolveImage, hash };
587
+ };
588
+
589
+ /**
590
+ * Bundle a Sprite program the same way {@link createFlyHostedSupport}
591
+ * bundles a Service — rolldown + Node bootstrap — without building a
592
+ * Docker image. The provider writes the files onto the Sprite.
593
+ */
594
+ export const createSpriteHostedSupport = ({
595
+ stackName,
596
+ stage,
597
+ virtualEntryPlugin,
598
+ }: {
599
+ stackName: string;
600
+ stage: string;
601
+ virtualEntryPlugin: (content: (importPath: string) => string) => rolldown.Plugin;
602
+ }) => {
603
+ const alchemyEnv = {
604
+ ALCHEMY_STACK_NAME: stackName,
605
+ ALCHEMY_STAGE: stage,
606
+ ALCHEMY_PHASE: "runtime",
607
+ HOST: "0.0.0.0",
608
+ };
609
+
610
+ const bundleProgram = Effect.fn(function* (props: HostedProgramProps) {
611
+ const handler = props.handler ?? "default";
612
+ const realMain = yield* resolveMainPath(props.main);
613
+ const cwd = yield* findCwdForBundle(realMain);
614
+ const bootstrap = makeBunBootstrap(handler);
615
+
616
+ const buildBundle = Effect.fn(function* (
617
+ entry: string,
618
+ plugins?: rolldown.RolldownPluginOption,
619
+ ) {
620
+ return yield* Bundle.build(
621
+ {
622
+ ...props.build?.input,
623
+ input: entry,
624
+ cwd,
625
+ platform: "node",
626
+ external: [
627
+ "bun",
628
+ "bun:*",
629
+ ...((props.build?.input?.external as string[] | undefined) ?? []),
630
+ ],
631
+ resolve: {
632
+ conditionNames: [...Bundle.NODE_CONDITION_NAMES],
633
+ ...props.build?.input?.resolve,
634
+ },
635
+ plugins: [props.build?.input?.plugins, plugins],
636
+ },
637
+ {
638
+ ...props.build?.output,
639
+ format: "esm",
640
+ sourcemap: props.build?.output?.sourcemap ?? false,
641
+ minify: props.build?.output?.minify ?? false,
642
+ entryFileNames: "index.mjs",
643
+ },
644
+ props.build,
645
+ );
646
+ });
647
+
648
+ const bundleOutput = props.isExternal
649
+ ? yield* buildBundle(realMain)
650
+ : yield* buildBundle(realMain, virtualEntryPlugin(bootstrap));
651
+
652
+ const files = bundleOutput.files.map((file) => ({
653
+ path: file.path,
654
+ content:
655
+ typeof file.content === "string" ? new TextEncoder().encode(file.content) : file.content,
656
+ }));
657
+
658
+ return { files, hash: bundleOutput.hash };
659
+ });
660
+
661
+ const hash = Effect.fn(function* (props: HostedProgramProps) {
662
+ const bundled = yield* bundleProgram(props);
663
+ return (yield* sha256Object({ bundleHash: bundled.hash })).slice(0, 16);
664
+ });
665
+
666
+ return { alchemyEnv, bundleProgram, hash };
667
+ };