@alchemy.run/fly 0.0.0 → 2.0.0-beta.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +57 -4
- package/lib/App.d.ts +230 -0
- package/lib/App.d.ts.map +1 -0
- package/lib/App.js +340 -0
- package/lib/App.js.map +1 -0
- package/lib/AuthProvider.d.ts +22 -0
- package/lib/AuthProvider.d.ts.map +1 -0
- package/lib/AuthProvider.js +48 -0
- package/lib/AuthProvider.js.map +1 -0
- package/lib/BindService.d.ts +159 -0
- package/lib/BindService.d.ts.map +1 -0
- package/lib/BindService.js +222 -0
- package/lib/BindService.js.map +1 -0
- package/lib/Bootstrap.d.ts +8 -0
- package/lib/Bootstrap.d.ts.map +1 -0
- package/lib/Bootstrap.js +41 -0
- package/lib/Bootstrap.js.map +1 -0
- package/lib/Bucket.d.ts +278 -0
- package/lib/Bucket.d.ts.map +1 -0
- package/lib/Bucket.js +658 -0
- package/lib/Bucket.js.map +1 -0
- package/lib/BucketBinding.d.ts +33 -0
- package/lib/BucketBinding.d.ts.map +1 -0
- package/lib/BucketBinding.js +70 -0
- package/lib/BucketBinding.js.map +1 -0
- package/lib/Catalog.d.ts +28 -0
- package/lib/Catalog.d.ts.map +1 -0
- package/lib/Catalog.js +31 -0
- package/lib/Catalog.js.map +1 -0
- package/lib/Certificate.d.ts +189 -0
- package/lib/Certificate.d.ts.map +1 -0
- package/lib/Certificate.js +380 -0
- package/lib/Certificate.js.map +1 -0
- package/lib/Checkpoint.d.ts +55 -0
- package/lib/Checkpoint.d.ts.map +1 -0
- package/lib/Checkpoint.js +3 -0
- package/lib/Checkpoint.js.map +1 -0
- package/lib/CheckpointHttp.d.ts +22 -0
- package/lib/CheckpointHttp.d.ts.map +1 -0
- package/lib/CheckpointHttp.js +53 -0
- package/lib/CheckpointHttp.js.map +1 -0
- package/lib/ConnectPostgres.d.ts +58 -0
- package/lib/ConnectPostgres.d.ts.map +1 -0
- package/lib/ConnectPostgres.js +13 -0
- package/lib/ConnectPostgres.js.map +1 -0
- package/lib/ConnectPostgresHttp.d.ts +26 -0
- package/lib/ConnectPostgresHttp.d.ts.map +1 -0
- package/lib/ConnectPostgresHttp.js +57 -0
- package/lib/ConnectPostgresHttp.js.map +1 -0
- package/lib/Contributions.d.ts +7 -0
- package/lib/Contributions.d.ts.map +1 -0
- package/lib/Contributions.js +6 -0
- package/lib/Contributions.js.map +1 -0
- package/lib/Credentials.d.ts +33 -0
- package/lib/Credentials.d.ts.map +1 -0
- package/lib/Credentials.js +59 -0
- package/lib/Credentials.js.map +1 -0
- package/lib/Decrypt.d.ts +52 -0
- package/lib/Decrypt.d.ts.map +1 -0
- package/lib/Decrypt.js +3 -0
- package/lib/Decrypt.js.map +1 -0
- package/lib/DecryptHttp.d.ts +22 -0
- package/lib/DecryptHttp.d.ts.map +1 -0
- package/lib/DecryptHttp.js +43 -0
- package/lib/DecryptHttp.js.map +1 -0
- package/lib/DeleteObject.d.ts +29 -0
- package/lib/DeleteObject.d.ts.map +1 -0
- package/lib/DeleteObject.js +3 -0
- package/lib/DeleteObject.js.map +1 -0
- package/lib/DeleteObjectHttp.d.ts +12 -0
- package/lib/DeleteObjectHttp.d.ts.map +1 -0
- package/lib/DeleteObjectHttp.js +17 -0
- package/lib/DeleteObjectHttp.js.map +1 -0
- package/lib/Deployment.d.ts +51 -0
- package/lib/Deployment.d.ts.map +1 -0
- package/lib/Deployment.js +62 -0
- package/lib/Deployment.js.map +1 -0
- package/lib/DeploymentImages.d.ts +18 -0
- package/lib/DeploymentImages.d.ts.map +1 -0
- package/lib/DeploymentImages.js +61 -0
- package/lib/DeploymentImages.js.map +1 -0
- package/lib/DeploymentState.d.ts +17 -0
- package/lib/DeploymentState.d.ts.map +1 -0
- package/lib/DeploymentState.js +87 -0
- package/lib/DeploymentState.js.map +1 -0
- package/lib/Encrypt.d.ts +50 -0
- package/lib/Encrypt.d.ts.map +1 -0
- package/lib/Encrypt.js +3 -0
- package/lib/Encrypt.js.map +1 -0
- package/lib/EncryptHttp.d.ts +22 -0
- package/lib/EncryptHttp.d.ts.map +1 -0
- package/lib/EncryptHttp.js +39 -0
- package/lib/EncryptHttp.js.map +1 -0
- package/lib/Environment.d.ts +45 -0
- package/lib/Environment.d.ts.map +1 -0
- package/lib/Environment.js +43 -0
- package/lib/Environment.js.map +1 -0
- package/lib/Errors.d.ts +18 -0
- package/lib/Errors.d.ts.map +1 -0
- package/lib/Errors.js +13 -0
- package/lib/Errors.js.map +1 -0
- package/lib/Exec.d.ts +41 -0
- package/lib/Exec.d.ts.map +1 -0
- package/lib/Exec.js +3 -0
- package/lib/Exec.js.map +1 -0
- package/lib/ExecHttp.d.ts +22 -0
- package/lib/ExecHttp.d.ts.map +1 -0
- package/lib/ExecHttp.js +39 -0
- package/lib/ExecHttp.js.map +1 -0
- package/lib/GetObject.d.ts +34 -0
- package/lib/GetObject.d.ts.map +1 -0
- package/lib/GetObject.js +3 -0
- package/lib/GetObject.js.map +1 -0
- package/lib/GetObjectHttp.d.ts +12 -0
- package/lib/GetObjectHttp.d.ts.map +1 -0
- package/lib/GetObjectHttp.js +17 -0
- package/lib/GetObjectHttp.js.map +1 -0
- package/lib/GetSecret.d.ts +44 -0
- package/lib/GetSecret.d.ts.map +1 -0
- package/lib/GetSecret.js +3 -0
- package/lib/GetSecret.js.map +1 -0
- package/lib/GetSecretHttp.d.ts +22 -0
- package/lib/GetSecretHttp.d.ts.map +1 -0
- package/lib/GetSecretHttp.js +50 -0
- package/lib/GetSecretHttp.js.map +1 -0
- package/lib/HeadObject.d.ts +29 -0
- package/lib/HeadObject.d.ts.map +1 -0
- package/lib/HeadObject.js +3 -0
- package/lib/HeadObject.js.map +1 -0
- package/lib/HeadObjectHttp.d.ts +12 -0
- package/lib/HeadObjectHttp.d.ts.map +1 -0
- package/lib/HeadObjectHttp.js +17 -0
- package/lib/HeadObjectHttp.js.map +1 -0
- package/lib/IpAssignment.d.ts +258 -0
- package/lib/IpAssignment.d.ts.map +1 -0
- package/lib/IpAssignment.js +376 -0
- package/lib/IpAssignment.js.map +1 -0
- package/lib/ListObjectsV2.d.ts +29 -0
- package/lib/ListObjectsV2.d.ts.map +1 -0
- package/lib/ListObjectsV2.js +3 -0
- package/lib/ListObjectsV2.js.map +1 -0
- package/lib/ListObjectsV2Http.d.ts +12 -0
- package/lib/ListObjectsV2Http.d.ts.map +1 -0
- package/lib/ListObjectsV2Http.js +17 -0
- package/lib/ListObjectsV2Http.js.map +1 -0
- package/lib/ListSecrets.d.ts +53 -0
- package/lib/ListSecrets.d.ts.map +1 -0
- package/lib/ListSecrets.js +3 -0
- package/lib/ListSecrets.js.map +1 -0
- package/lib/ListSecretsHttp.d.ts +22 -0
- package/lib/ListSecretsHttp.d.ts.map +1 -0
- package/lib/ListSecretsHttp.js +35 -0
- package/lib/ListSecretsHttp.js.map +1 -0
- package/lib/Machine.d.ts +802 -0
- package/lib/Machine.d.ts.map +1 -0
- package/lib/Machine.js +773 -0
- package/lib/Machine.js.map +1 -0
- package/lib/MachineContainers.d.ts +44 -0
- package/lib/MachineContainers.d.ts.map +1 -0
- package/lib/MachineContainers.js +115 -0
- package/lib/MachineContainers.js.map +1 -0
- package/lib/Metadata.d.ts +109 -0
- package/lib/Metadata.d.ts.map +1 -0
- package/lib/Metadata.js +159 -0
- package/lib/Metadata.js.map +1 -0
- package/lib/MountVolume.d.ts +295 -0
- package/lib/MountVolume.d.ts.map +1 -0
- package/lib/MountVolume.js +20 -0
- package/lib/MountVolume.js.map +1 -0
- package/lib/Postgres.d.ts +298 -0
- package/lib/Postgres.d.ts.map +1 -0
- package/lib/Postgres.js +508 -0
- package/lib/Postgres.js.map +1 -0
- package/lib/PostgresMigrations.d.ts +35 -0
- package/lib/PostgresMigrations.d.ts.map +1 -0
- package/lib/PostgresMigrations.js +110 -0
- package/lib/PostgresMigrations.js.map +1 -0
- package/lib/Providers.d.ts +38 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +95 -0
- package/lib/Providers.js.map +1 -0
- package/lib/PutObject.d.ts +35 -0
- package/lib/PutObject.d.ts.map +1 -0
- package/lib/PutObject.js +3 -0
- package/lib/PutObject.js.map +1 -0
- package/lib/PutObjectHttp.d.ts +12 -0
- package/lib/PutObjectHttp.d.ts.map +1 -0
- package/lib/PutObjectHttp.js +17 -0
- package/lib/PutObjectHttp.js.map +1 -0
- package/lib/ReadRedis.d.ts +26 -0
- package/lib/ReadRedis.d.ts.map +1 -0
- package/lib/ReadRedis.js +3 -0
- package/lib/ReadRedis.js.map +1 -0
- package/lib/ReadRedisHttp.d.ts +11 -0
- package/lib/ReadRedisHttp.d.ts.map +1 -0
- package/lib/ReadRedisHttp.js +15 -0
- package/lib/ReadRedisHttp.js.map +1 -0
- package/lib/ReadWriteRedis.d.ts +29 -0
- package/lib/ReadWriteRedis.d.ts.map +1 -0
- package/lib/ReadWriteRedis.js +3 -0
- package/lib/ReadWriteRedis.js.map +1 -0
- package/lib/ReadWriteRedisHttp.d.ts +11 -0
- package/lib/ReadWriteRedisHttp.d.ts.map +1 -0
- package/lib/ReadWriteRedisHttp.js +15 -0
- package/lib/ReadWriteRedisHttp.js.map +1 -0
- package/lib/Redis.d.ts +252 -0
- package/lib/Redis.d.ts.map +1 -0
- package/lib/Redis.js +608 -0
- package/lib/Redis.js.map +1 -0
- package/lib/RedisBinding.d.ts +7 -0
- package/lib/RedisBinding.d.ts.map +1 -0
- package/lib/RedisBinding.js +53 -0
- package/lib/RedisBinding.js.map +1 -0
- package/lib/RedisHttp.d.ts +8 -0
- package/lib/RedisHttp.d.ts.map +1 -0
- package/lib/RedisHttp.js +8 -0
- package/lib/RedisHttp.js.map +1 -0
- package/lib/Region.d.ts +16 -0
- package/lib/Region.d.ts.map +1 -0
- package/lib/Region.js +13 -0
- package/lib/Region.js.map +1 -0
- package/lib/Secret.d.ts +190 -0
- package/lib/Secret.d.ts.map +1 -0
- package/lib/Secret.js +310 -0
- package/lib/Secret.js.map +1 -0
- package/lib/SecretHttp.d.ts +54 -0
- package/lib/SecretHttp.d.ts.map +1 -0
- package/lib/SecretHttp.js +66 -0
- package/lib/SecretHttp.js.map +1 -0
- package/lib/SecretKey.d.ts +164 -0
- package/lib/SecretKey.d.ts.map +1 -0
- package/lib/SecretKey.js +277 -0
- package/lib/SecretKey.js.map +1 -0
- package/lib/SecretKeyHttp.d.ts +14 -0
- package/lib/SecretKeyHttp.d.ts.map +1 -0
- package/lib/SecretKeyHttp.js +5 -0
- package/lib/SecretKeyHttp.js.map +1 -0
- package/lib/Service.d.ts +1022 -0
- package/lib/Service.d.ts.map +1 -0
- package/lib/Service.js +1397 -0
- package/lib/Service.js.map +1 -0
- package/lib/Sign.d.ts +36 -0
- package/lib/Sign.d.ts.map +1 -0
- package/lib/Sign.js +3 -0
- package/lib/Sign.js.map +1 -0
- package/lib/SignHttp.d.ts +22 -0
- package/lib/SignHttp.d.ts.map +1 -0
- package/lib/SignHttp.js +36 -0
- package/lib/SignHttp.js.map +1 -0
- package/lib/Sprite.d.ts +283 -0
- package/lib/Sprite.d.ts.map +1 -0
- package/lib/Sprite.js +469 -0
- package/lib/Sprite.js.map +1 -0
- package/lib/SpriteHttp.d.ts +25 -0
- package/lib/SpriteHttp.d.ts.map +1 -0
- package/lib/SpriteHttp.js +33 -0
- package/lib/SpriteHttp.js.map +1 -0
- package/lib/Verify.d.ts +37 -0
- package/lib/Verify.d.ts.map +1 -0
- package/lib/Verify.js +3 -0
- package/lib/Verify.js.map +1 -0
- package/lib/VerifyHttp.d.ts +22 -0
- package/lib/VerifyHttp.d.ts.map +1 -0
- package/lib/VerifyHttp.js +38 -0
- package/lib/VerifyHttp.js.map +1 -0
- package/lib/Volume.d.ts +53 -0
- package/lib/Volume.d.ts.map +1 -0
- package/lib/Volume.js +188 -0
- package/lib/Volume.js.map +1 -0
- package/lib/VolumeSnapshot.d.ts +135 -0
- package/lib/VolumeSnapshot.d.ts.map +1 -0
- package/lib/VolumeSnapshot.js +213 -0
- package/lib/VolumeSnapshot.js.map +1 -0
- package/lib/Website/AssetDeployment.d.ts +43 -0
- package/lib/Website/AssetDeployment.d.ts.map +1 -0
- package/lib/Website/AssetDeployment.js +162 -0
- package/lib/Website/AssetDeployment.js.map +1 -0
- package/lib/Website/Astro.d.ts +87 -0
- package/lib/Website/Astro.d.ts.map +1 -0
- package/lib/Website/Astro.js +55 -0
- package/lib/Website/Astro.js.map +1 -0
- package/lib/Website/Foldkit.d.ts +52 -0
- package/lib/Website/Foldkit.d.ts.map +1 -0
- package/lib/Website/Foldkit.js +45 -0
- package/lib/Website/Foldkit.js.map +1 -0
- package/lib/Website/FrameworkSite.d.ts +175 -0
- package/lib/Website/FrameworkSite.d.ts.map +1 -0
- package/lib/Website/FrameworkSite.js +162 -0
- package/lib/Website/FrameworkSite.js.map +1 -0
- package/lib/Website/Nextjs.d.ts +54 -0
- package/lib/Website/Nextjs.d.ts.map +1 -0
- package/lib/Website/Nextjs.js +46 -0
- package/lib/Website/Nextjs.js.map +1 -0
- package/lib/Website/Nuxt.d.ts +51 -0
- package/lib/Website/Nuxt.d.ts.map +1 -0
- package/lib/Website/Nuxt.js +36 -0
- package/lib/Website/Nuxt.js.map +1 -0
- package/lib/Website/Octane.d.ts +49 -0
- package/lib/Website/Octane.d.ts.map +1 -0
- package/lib/Website/Octane.js +39 -0
- package/lib/Website/Octane.js.map +1 -0
- package/lib/Website/ReactRouter.d.ts +80 -0
- package/lib/Website/ReactRouter.d.ts.map +1 -0
- package/lib/Website/ReactRouter.js +70 -0
- package/lib/Website/ReactRouter.js.map +1 -0
- package/lib/Website/SolidStart.d.ts +93 -0
- package/lib/Website/SolidStart.d.ts.map +1 -0
- package/lib/Website/SolidStart.js +71 -0
- package/lib/Website/SolidStart.js.map +1 -0
- package/lib/Website/StaticSite.d.ts +155 -0
- package/lib/Website/StaticSite.d.ts.map +1 -0
- package/lib/Website/StaticSite.js +168 -0
- package/lib/Website/StaticSite.js.map +1 -0
- package/lib/Website/SvelteKit.d.ts +52 -0
- package/lib/Website/SvelteKit.d.ts.map +1 -0
- package/lib/Website/SvelteKit.js +37 -0
- package/lib/Website/SvelteKit.js.map +1 -0
- package/lib/Website/TanStackStart.d.ts +76 -0
- package/lib/Website/TanStackStart.d.ts.map +1 -0
- package/lib/Website/TanStackStart.js +66 -0
- package/lib/Website/TanStackStart.js.map +1 -0
- package/lib/Website/Vinext.d.ts +73 -0
- package/lib/Website/Vinext.d.ts.map +1 -0
- package/lib/Website/Vinext.js +67 -0
- package/lib/Website/Vinext.js.map +1 -0
- package/lib/Website/Vite.d.ts +103 -0
- package/lib/Website/Vite.d.ts.map +1 -0
- package/lib/Website/Vite.js +91 -0
- package/lib/Website/Vite.js.map +1 -0
- package/lib/Website/Vocs.d.ts +52 -0
- package/lib/Website/Vocs.d.ts.map +1 -0
- package/lib/Website/Vocs.js +38 -0
- package/lib/Website/Vocs.js.map +1 -0
- package/lib/Website/Waku.d.ts +64 -0
- package/lib/Website/Waku.d.ts.map +1 -0
- package/lib/Website/Waku.js +39 -0
- package/lib/Website/Waku.js.map +1 -0
- package/lib/Website/index.d.ts +17 -0
- package/lib/Website/index.d.ts.map +1 -0
- package/lib/Website/index.js +17 -0
- package/lib/Website/index.js.map +1 -0
- package/lib/WriteCertificates.d.ts +63 -0
- package/lib/WriteCertificates.d.ts.map +1 -0
- package/lib/WriteCertificates.js +3 -0
- package/lib/WriteCertificates.js.map +1 -0
- package/lib/WriteCertificatesHttp.d.ts +25 -0
- package/lib/WriteCertificatesHttp.d.ts.map +1 -0
- package/lib/WriteCertificatesHttp.js +67 -0
- package/lib/WriteCertificatesHttp.js.map +1 -0
- package/lib/WriteRedis.d.ts +26 -0
- package/lib/WriteRedis.d.ts.map +1 -0
- package/lib/WriteRedis.js +3 -0
- package/lib/WriteRedis.js.map +1 -0
- package/lib/WriteRedisHttp.d.ts +11 -0
- package/lib/WriteRedisHttp.d.ts.map +1 -0
- package/lib/WriteRedisHttp.js +15 -0
- package/lib/WriteRedisHttp.js.map +1 -0
- package/lib/WriteSecret.d.ts +68 -0
- package/lib/WriteSecret.d.ts.map +1 -0
- package/lib/WriteSecret.js +4 -0
- package/lib/WriteSecret.js.map +1 -0
- package/lib/WriteSecretHttp.d.ts +26 -0
- package/lib/WriteSecretHttp.d.ts.map +1 -0
- package/lib/WriteSecretHttp.js +54 -0
- package/lib/WriteSecretHttp.js.map +1 -0
- package/lib/bluegreen.d.ts +36 -0
- package/lib/bluegreen.d.ts.map +1 -0
- package/lib/bluegreen.js +458 -0
- package/lib/bluegreen.js.map +1 -0
- package/lib/hosted.d.ts +172 -0
- package/lib/hosted.d.ts.map +1 -0
- package/lib/hosted.js +458 -0
- package/lib/hosted.js.map +1 -0
- package/lib/index.d.ts +65 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +63 -0
- package/lib/index.js.map +1 -0
- package/lib/internal/RemoteBuilder.d.ts +28 -0
- package/lib/internal/RemoteBuilder.d.ts.map +1 -0
- package/lib/internal/RemoteBuilder.js +145 -0
- package/lib/internal/RemoteBuilder.js.map +1 -0
- package/lib/leases.d.ts +53 -0
- package/lib/leases.d.ts.map +1 -0
- package/lib/leases.js +279 -0
- package/lib/leases.js.map +1 -0
- package/lib/ports.d.ts +51 -0
- package/lib/ports.d.ts.map +1 -0
- package/lib/ports.js +123 -0
- package/lib/ports.js.map +1 -0
- package/lib/replicas.d.ts +270 -0
- package/lib/replicas.d.ts.map +1 -0
- package/lib/replicas.js +969 -0
- package/lib/replicas.js.map +1 -0
- package/lib/rpc.d.ts +35 -0
- package/lib/rpc.d.ts.map +1 -0
- package/lib/rpc.js +113 -0
- package/lib/rpc.js.map +1 -0
- package/package.json +83 -3
- package/src/App.ts +516 -0
- package/src/AuthProvider.ts +68 -0
- package/src/BindService.ts +304 -0
- package/src/Bootstrap.ts +66 -0
- package/src/Bucket.ts +916 -0
- package/src/BucketBinding.ts +128 -0
- package/src/Catalog.ts +43 -0
- package/src/Certificate.ts +548 -0
- package/src/Checkpoint.ts +69 -0
- package/src/CheckpointHttp.ts +66 -0
- package/src/ConnectPostgres.ts +68 -0
- package/src/ConnectPostgresHttp.ts +77 -0
- package/src/Contributions.ts +9 -0
- package/src/Credentials.ts +102 -0
- package/src/Decrypt.ts +62 -0
- package/src/DecryptHttp.ts +52 -0
- package/src/DeleteObject.ts +43 -0
- package/src/DeleteObjectHttp.ts +20 -0
- package/src/Deployment.ts +121 -0
- package/src/DeploymentImages.ts +84 -0
- package/src/DeploymentState.ts +104 -0
- package/src/Encrypt.ts +60 -0
- package/src/EncryptHttp.ts +48 -0
- package/src/Environment.ts +81 -0
- package/src/Errors.ts +14 -0
- package/src/Exec.ts +50 -0
- package/src/ExecHttp.ts +47 -0
- package/src/GetObject.ts +48 -0
- package/src/GetObjectHttp.ts +20 -0
- package/src/GetSecret.ts +48 -0
- package/src/GetSecretHttp.ts +60 -0
- package/src/HeadObject.ts +43 -0
- package/src/HeadObjectHttp.ts +20 -0
- package/src/IpAssignment.ts +522 -0
- package/src/ListObjectsV2.ts +43 -0
- package/src/ListObjectsV2Http.ts +20 -0
- package/src/ListSecrets.ts +57 -0
- package/src/ListSecretsHttp.ts +43 -0
- package/src/Machine.ts +1268 -0
- package/src/MachineContainers.ts +152 -0
- package/src/Metadata.ts +195 -0
- package/src/MountVolume.ts +315 -0
- package/src/Postgres.ts +777 -0
- package/src/PostgresMigrations.ts +153 -0
- package/src/Providers.ts +155 -0
- package/src/PutObject.ts +49 -0
- package/src/PutObjectHttp.ts +20 -0
- package/src/ReadRedis.ts +31 -0
- package/src/ReadRedisHttp.ts +18 -0
- package/src/ReadWriteRedis.ts +33 -0
- package/src/ReadWriteRedisHttp.ts +18 -0
- package/src/Redis.ts +820 -0
- package/src/RedisBinding.ts +64 -0
- package/src/RedisHttp.ts +11 -0
- package/src/Region.ts +44 -0
- package/src/Secret.ts +405 -0
- package/src/SecretHttp.ts +149 -0
- package/src/SecretKey.ts +389 -0
- package/src/SecretKeyHttp.ts +23 -0
- package/src/Service.ts +1934 -0
- package/src/Sign.ts +46 -0
- package/src/SignHttp.ts +44 -0
- package/src/Sprite.ts +671 -0
- package/src/SpriteHttp.ts +50 -0
- package/src/Verify.ts +47 -0
- package/src/VerifyHttp.ts +46 -0
- package/src/Volume.ts +264 -0
- package/src/VolumeSnapshot.ts +321 -0
- package/src/Website/AssetDeployment.ts +294 -0
- package/src/Website/Astro.ts +87 -0
- package/src/Website/Foldkit.ts +54 -0
- package/src/Website/FrameworkSite.ts +363 -0
- package/src/Website/Nextjs.ts +50 -0
- package/src/Website/Nuxt.ts +48 -0
- package/src/Website/Octane.ts +44 -0
- package/src/Website/ReactRouter.ts +76 -0
- package/src/Website/SolidStart.ts +90 -0
- package/src/Website/StaticSite.ts +275 -0
- package/src/Website/SvelteKit.ts +49 -0
- package/src/Website/TanStackStart.ts +72 -0
- package/src/Website/Vinext.ts +79 -0
- package/src/Website/Vite.ts +112 -0
- package/src/Website/Vocs.ts +50 -0
- package/src/Website/Waku.ts +65 -0
- package/src/Website/index.ts +16 -0
- package/src/WriteCertificates.ts +90 -0
- package/src/WriteCertificatesHttp.ts +93 -0
- package/src/WriteRedis.ts +31 -0
- package/src/WriteRedisHttp.ts +18 -0
- package/src/WriteSecret.ts +86 -0
- package/src/WriteSecretHttp.ts +71 -0
- package/src/bluegreen.ts +708 -0
- package/src/globals.d.ts +2 -0
- package/src/hosted.ts +668 -0
- package/src/index.ts +64 -0
- package/src/internal/RemoteBuilder.ts +224 -0
- package/src/leases.ts +437 -0
- package/src/ports.ts +177 -0
- package/src/replicas.ts +1480 -0
- package/src/rpc.ts +136 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as Binding from "alchemy/Binding";
|
|
2
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
3
|
+
import * as Data from "effect/Data";
|
|
4
|
+
import type * as Effect from "effect/Effect";
|
|
5
|
+
import type * as Redacted from "effect/Redacted";
|
|
6
|
+
import type { Postgres } from "./Postgres.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Bind a {@link Postgres} cluster to a Fly {@link Service} and obtain
|
|
10
|
+
* the Effect-native connection strings for `Drizzle.Postgres` /
|
|
11
|
+
* `SQL.Postgres`. Alchemy transports the cluster's connection URIs
|
|
12
|
+
* automatically; callers do not configure connection-string env vars.
|
|
13
|
+
*
|
|
14
|
+
* `ConnectPostgres` is the Context tag, the type, and the callable —
|
|
15
|
+
* `yield* Fly.ConnectPostgres(Db)`. Provide {@link ConnectPostgresHttp}.
|
|
16
|
+
*
|
|
17
|
+
* **Example:** Bind Postgres in a Service
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import * as Drizzle from "@alchemy.run/drizzle/Postgres";
|
|
20
|
+
*
|
|
21
|
+
* const conn = yield* Fly.ConnectPostgres(Db);
|
|
22
|
+
* const db = yield* Drizzle.Postgres(conn.connectionString);
|
|
23
|
+
*
|
|
24
|
+
* fetch: Effect.gen(function* () {
|
|
25
|
+
* const rows = yield* db.select().from(users);
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @binding
|
|
30
|
+
* @product Postgres
|
|
31
|
+
*/
|
|
32
|
+
export interface ConnectPostgres extends Binding.Service<
|
|
33
|
+
ConnectPostgres,
|
|
34
|
+
"Fly.ConnectPostgres",
|
|
35
|
+
(postgres: Postgres) => Effect.Effect<ConnectPostgresClient>
|
|
36
|
+
> {}
|
|
37
|
+
|
|
38
|
+
export const ConnectPostgres = Binding.Service<ConnectPostgres>("Fly.ConnectPostgres");
|
|
39
|
+
|
|
40
|
+
export const connectEnvKeys = (postgres: Pick<Postgres, "LogicalId">) => {
|
|
41
|
+
const id = postgres.LogicalId.replaceAll(/[^a-zA-Z0-9]/g, "_").toUpperCase();
|
|
42
|
+
return {
|
|
43
|
+
pooled: `FLY_POSTGRES_${id}_POOLED`,
|
|
44
|
+
direct: `FLY_POSTGRES_${id}_DIRECT`,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export class PostgresUrlMissing extends Data.TaggedError("Fly.PostgresUrlMissing")<{
|
|
49
|
+
name: string;
|
|
50
|
+
}> {}
|
|
51
|
+
|
|
52
|
+
export interface ConnectPostgresClient {
|
|
53
|
+
/**
|
|
54
|
+
* Pooled PgBouncer connection string. Pass this to
|
|
55
|
+
* {@link Drizzle.Postgres} or `SQL.Postgres`.
|
|
56
|
+
*/
|
|
57
|
+
connectionString: Effect.Effect<Redacted.Redacted<string>, PostgresUrlMissing, RuntimeContext>;
|
|
58
|
+
/**
|
|
59
|
+
* Direct (non-PgBouncer) connection string. Use this for session-scoped
|
|
60
|
+
* features (advisory locks, `LISTEN/NOTIFY`) when you are not going
|
|
61
|
+
* through the pooled URL.
|
|
62
|
+
*/
|
|
63
|
+
directConnectionString: Effect.Effect<
|
|
64
|
+
Redacted.Redacted<string>,
|
|
65
|
+
PostgresUrlMissing,
|
|
66
|
+
RuntimeContext
|
|
67
|
+
>;
|
|
68
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as Binding from "alchemy/Binding";
|
|
2
|
+
import type { Resource } from "alchemy/Resource";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import * as Redacted from "effect/Redacted";
|
|
6
|
+
import {
|
|
7
|
+
ConnectPostgres,
|
|
8
|
+
PostgresUrlMissing,
|
|
9
|
+
type ConnectPostgresClient,
|
|
10
|
+
} from "./ConnectPostgres.ts";
|
|
11
|
+
import type { ServiceBinding } from "./MountVolume.ts";
|
|
12
|
+
import { type Postgres } from "./Postgres.ts";
|
|
13
|
+
|
|
14
|
+
const isFlyHost = (value: unknown): value is Resource<string, any, any, ServiceBinding> =>
|
|
15
|
+
typeof value === "object" &&
|
|
16
|
+
value !== null &&
|
|
17
|
+
((value as { Type?: string }).Type === "Fly.Service" ||
|
|
18
|
+
(value as { Type?: string }).Type === "Fly.Machine");
|
|
19
|
+
|
|
20
|
+
const asRedactedUrl = (
|
|
21
|
+
value: unknown,
|
|
22
|
+
name: string,
|
|
23
|
+
): Effect.Effect<Redacted.Redacted<string>, PostgresUrlMissing> => {
|
|
24
|
+
const plain =
|
|
25
|
+
typeof value === "string" ? value : Redacted.isRedacted(value) ? Redacted.value(value) : "";
|
|
26
|
+
const url = typeof plain === "string" ? plain : "";
|
|
27
|
+
return url.length > 0
|
|
28
|
+
? Effect.succeed(Redacted.make(url))
|
|
29
|
+
: Effect.fail(new PostgresUrlMissing({ name }));
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Implementation of {@link ConnectPostgres}. Provide it on the
|
|
34
|
+
* {@link Service} Effect.
|
|
35
|
+
*
|
|
36
|
+
* Registers the cluster attachment for Fly's private network. Alchemy
|
|
37
|
+
* transports each cluster's connection URIs through resource Outputs,
|
|
38
|
+
* so callers do not configure connection-string environment variables.
|
|
39
|
+
*
|
|
40
|
+
*
|
|
41
|
+
* ### Provide the layer
|
|
42
|
+
* **Example:** On a Service
|
|
43
|
+
* ```typescript
|
|
44
|
+
* Effect.gen(function* () {
|
|
45
|
+
* const conn = yield* Fly.ConnectPostgres(Db);
|
|
46
|
+
* const db = yield* Drizzle.Postgres(conn.connectionString);
|
|
47
|
+
* }).pipe(Effect.provide(Fly.ConnectPostgresHttp))
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @layer
|
|
51
|
+
* @product Postgres
|
|
52
|
+
* @provides Fly.ConnectPostgres
|
|
53
|
+
*/
|
|
54
|
+
export const ConnectPostgresHttp = Layer.effect(
|
|
55
|
+
ConnectPostgres,
|
|
56
|
+
Effect.succeed(
|
|
57
|
+
Effect.fn(function* (postgres: Postgres) {
|
|
58
|
+
const name = postgres.LogicalId;
|
|
59
|
+
if (!globalThis.__ALCHEMY_RUNTIME__) {
|
|
60
|
+
const host = yield* Binding.Host;
|
|
61
|
+
if (isFlyHost(host)) {
|
|
62
|
+
yield* host.bind`${postgres}`({
|
|
63
|
+
postgres: { clusterId: postgres.clusterId },
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const pooled = yield* postgres.pooledConnectionUri;
|
|
69
|
+
const direct = yield* postgres.connectionUri;
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
connectionString: pooled.pipe(Effect.flatMap((value) => asRedactedUrl(value, name))),
|
|
73
|
+
directConnectionString: direct.pipe(Effect.flatMap((value) => asRedactedUrl(value, name))),
|
|
74
|
+
} satisfies ConnectPostgresClient;
|
|
75
|
+
}),
|
|
76
|
+
),
|
|
77
|
+
);
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { ConfigError } from "@distilled.cloud/core/errors";
|
|
2
|
+
import { Credentials, CredentialsFromEnv } from "@distilled.cloud/fly-io";
|
|
3
|
+
import {
|
|
4
|
+
deferUntilFirstUse,
|
|
5
|
+
orDieCredentialsUnavailable,
|
|
6
|
+
resolveProviderConfig,
|
|
7
|
+
} from "alchemy/Auth/Resolve";
|
|
8
|
+
import * as Output from "alchemy/Output";
|
|
9
|
+
import * as Effect from "effect/Effect";
|
|
10
|
+
import * as Layer from "effect/Layer";
|
|
11
|
+
import * as Option from "effect/Option";
|
|
12
|
+
import * as Redacted from "effect/Redacted";
|
|
13
|
+
import {
|
|
14
|
+
FLY_AUTH_PROVIDER_NAME,
|
|
15
|
+
type FlyAuthConfig,
|
|
16
|
+
type FlyResolvedCredentials,
|
|
17
|
+
} from "./AuthProvider.ts";
|
|
18
|
+
|
|
19
|
+
export {
|
|
20
|
+
Credentials,
|
|
21
|
+
CredentialsFromEnv,
|
|
22
|
+
credentials,
|
|
23
|
+
DEFAULT_API_BASE_URL,
|
|
24
|
+
normalizeApiBaseUrl,
|
|
25
|
+
type Config as CredentialsConfig,
|
|
26
|
+
} from "@distilled.cloud/fly-io";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Capture the deployment's org token as a named runtime Output.
|
|
30
|
+
* Resolve it during binding initialization so plan/diff retains
|
|
31
|
+
* profile-backed credentials rather than falling back to process env.
|
|
32
|
+
*/
|
|
33
|
+
export const bindFlyApiToken = (): Effect.Effect<void, never, Credentials> =>
|
|
34
|
+
Effect.gen(function* () {
|
|
35
|
+
const token = globalThis.__ALCHEMY_RUNTIME__
|
|
36
|
+
? ""
|
|
37
|
+
: yield* Credentials.pipe(
|
|
38
|
+
Effect.flatMap((resolve) => resolve),
|
|
39
|
+
Effect.map((cfg) => Redacted.value(cfg.apiKey)),
|
|
40
|
+
);
|
|
41
|
+
yield* Output.named(Output.asOutput(token), "FLY_API_TOKEN").asEffect().pipe(Effect.asVoid);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* `Credentials` for the HTTP binding layers (`GetSecretHttp`, `ExecHttp`, …).
|
|
46
|
+
*
|
|
47
|
+
* Those layers are built in two places. Inside a stack (plan/deploy, or an
|
|
48
|
+
* Action) `providers()` has already resolved the profile-backed
|
|
49
|
+
* `Credentials`, and the binding must use them — a laptop deploy has no
|
|
50
|
+
* `FLY_API_TOKEN` in its env once the token lives in the Alchemy profile.
|
|
51
|
+
* Inside a deployed Machine there is no profile; `bindFlyApiToken`
|
|
52
|
+
* has already `RuntimeContext.set` the org token, which Platform copies
|
|
53
|
+
* into Machine env as `FLY_API_TOKEN`. So: reuse the ambient
|
|
54
|
+
* `Credentials` when present, otherwise read the env.
|
|
55
|
+
*/
|
|
56
|
+
export const CredentialsFromAmbientOrEnv: Layer.Layer<Credentials> = Layer.effect(
|
|
57
|
+
Credentials,
|
|
58
|
+
Effect.gen(function* () {
|
|
59
|
+
const ambient = yield* Effect.serviceOption(Credentials);
|
|
60
|
+
if (Option.isSome(ambient)) return ambient.value;
|
|
61
|
+
return yield* Credentials.pipe(Effect.provide(CredentialsFromEnv));
|
|
62
|
+
}),
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Build a `Credentials` layer that resolves Fly credentials via the current
|
|
67
|
+
* Alchemy profile, or directly from environment variables in CI.
|
|
68
|
+
*
|
|
69
|
+
* Maps onto `@distilled.cloud/fly-io`'s `{ apiKey, apiBaseUrl }` shape.
|
|
70
|
+
* Distilled's own `CredentialsFromEnv` also accepts `FLY_IO_API_KEY` as a
|
|
71
|
+
* fallback — Alchemy itself only reads `FLY_API_TOKEN`.
|
|
72
|
+
*/
|
|
73
|
+
export const fromAuthProvider = () =>
|
|
74
|
+
Layer.effect(
|
|
75
|
+
Credentials,
|
|
76
|
+
Effect.gen(function* () {
|
|
77
|
+
// Defer profile lookup and credential resolution until first use, so
|
|
78
|
+
// building the provider layers never requires a configured profile.
|
|
79
|
+
const resolve = yield* resolveProviderConfig<FlyAuthConfig, FlyResolvedCredentials>(
|
|
80
|
+
FLY_AUTH_PROVIDER_NAME,
|
|
81
|
+
).pipe(
|
|
82
|
+
Effect.flatMap(({ profileName, resolve }) =>
|
|
83
|
+
resolve.pipe(
|
|
84
|
+
Effect.map((creds) => ({
|
|
85
|
+
apiKey: creds.apiKey,
|
|
86
|
+
apiBaseUrl: creds.apiBaseUrl,
|
|
87
|
+
})),
|
|
88
|
+
Effect.mapError((e) =>
|
|
89
|
+
ConfigError.make({
|
|
90
|
+
message: `Failed to resolve Fly credentials from ${profileName === undefined ? "the CI environment" : `profile '${profileName}'`}: ${(e as { message?: string }).message ?? String(e)}`,
|
|
91
|
+
}),
|
|
92
|
+
),
|
|
93
|
+
),
|
|
94
|
+
),
|
|
95
|
+
deferUntilFirstUse,
|
|
96
|
+
);
|
|
97
|
+
return yield* resolve.pipe(
|
|
98
|
+
orDieCredentialsUnavailable(FLY_AUTH_PROVIDER_NAME),
|
|
99
|
+
Effect.cached,
|
|
100
|
+
);
|
|
101
|
+
}),
|
|
102
|
+
);
|
package/src/Decrypt.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { DecryptSecretKeyError } from "@distilled.cloud/fly-io/machines";
|
|
2
|
+
import * as Binding from "alchemy/Binding";
|
|
3
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
4
|
+
import type * as Effect from "effect/Effect";
|
|
5
|
+
import type * as Redacted from "effect/Redacted";
|
|
6
|
+
import type { SecretKey } from "./SecretKey.ts";
|
|
7
|
+
|
|
8
|
+
export interface DecryptRequest {
|
|
9
|
+
/** Ciphertext produced by {@link Encrypt}. */
|
|
10
|
+
ciphertext: Uint8Array | ArrayLike<number>;
|
|
11
|
+
/** Optional AEAD associated data. Must match encryption. */
|
|
12
|
+
associatedData?: Uint8Array | ArrayLike<number>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DecryptResult {
|
|
16
|
+
/** Plaintext, wrapped so it never logs. Unwrap with `Redacted.value`. */
|
|
17
|
+
plaintext: Redacted.Redacted<Uint8Array>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Decrypt with a Fly {@link SecretKey}. The App and key name are fixed
|
|
22
|
+
* by `Decrypt(key)`.
|
|
23
|
+
*
|
|
24
|
+
*
|
|
25
|
+
* ### Decrypt a payload
|
|
26
|
+
* Provide {@link DecryptHttp}. Plaintext comes back `Redacted`. Unwrap
|
|
27
|
+
* with `Redacted.value` only where you need the raw bytes.
|
|
28
|
+
*
|
|
29
|
+
* **Example:** Decrypt
|
|
30
|
+
* ```typescript
|
|
31
|
+
* import * as Redacted from "effect/Redacted";
|
|
32
|
+
*
|
|
33
|
+
* const decrypt = yield* Fly.Decrypt(Box);
|
|
34
|
+
* const { plaintext } = yield* decrypt({ ciphertext });
|
|
35
|
+
* const bytes = Redacted.value(plaintext);
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* ### Associated data
|
|
39
|
+
* `associatedData` must match the bytes passed to {@link Encrypt}.
|
|
40
|
+
*
|
|
41
|
+
* **Example:** AEAD
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const { plaintext } = yield* decrypt({
|
|
44
|
+
* ciphertext,
|
|
45
|
+
* associatedData: nonce,
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @binding
|
|
50
|
+
* @product Secret Key
|
|
51
|
+
*/
|
|
52
|
+
export interface Decrypt extends Binding.Service<
|
|
53
|
+
Decrypt,
|
|
54
|
+
"Fly.Decrypt",
|
|
55
|
+
(
|
|
56
|
+
key: SecretKey,
|
|
57
|
+
) => Effect.Effect<
|
|
58
|
+
(request: DecryptRequest) => Effect.Effect<DecryptResult, DecryptSecretKeyError, RuntimeContext>
|
|
59
|
+
>
|
|
60
|
+
> {}
|
|
61
|
+
|
|
62
|
+
export const Decrypt = Binding.Service<Decrypt>("Fly.Decrypt");
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as machines from "@distilled.cloud/fly-io/machines";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as FetchHttpClient from "effect/http/FetchHttpClient";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import * as Redacted from "effect/Redacted";
|
|
6
|
+
import { CredentialsFromAmbientOrEnv } from "./Credentials.ts";
|
|
7
|
+
import { Decrypt, type DecryptRequest } from "./Decrypt.ts";
|
|
8
|
+
import { unwrapSecretValue } from "./SecretHttp.ts";
|
|
9
|
+
import { base64ToBytes, bytesToBase64, makeHttpSecretKeyBinding } from "./SecretKeyHttp.ts";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* HTTP implementation of {@link Decrypt}. Provide it on the
|
|
13
|
+
* {@link Service} or Action Effect.
|
|
14
|
+
*
|
|
15
|
+
*
|
|
16
|
+
* ### Provide the layer
|
|
17
|
+
* **Example:** On a Service
|
|
18
|
+
* ```typescript
|
|
19
|
+
* Effect.gen(function* () {
|
|
20
|
+
* const decrypt = yield* Fly.Decrypt(Box);
|
|
21
|
+
* // ...
|
|
22
|
+
* }).pipe(Effect.provide(Fly.DecryptHttp))
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @layer
|
|
26
|
+
* @product Secret Key
|
|
27
|
+
* @provides Fly.Decrypt
|
|
28
|
+
*/
|
|
29
|
+
export const DecryptHttp = Layer.effect(
|
|
30
|
+
Decrypt,
|
|
31
|
+
Effect.suspend(() =>
|
|
32
|
+
makeHttpSecretKeyBinding({
|
|
33
|
+
makeClient: (auth, appName, secretName) =>
|
|
34
|
+
Effect.fn("Fly.Decrypt")(function* (request: DecryptRequest) {
|
|
35
|
+
const res = yield* auth.authorize(
|
|
36
|
+
machines.decryptSecretKey({
|
|
37
|
+
app_name: yield* appName,
|
|
38
|
+
secret_name: yield* secretName,
|
|
39
|
+
ciphertext: bytesToBase64(request.ciphertext),
|
|
40
|
+
associated_data:
|
|
41
|
+
request.associatedData === undefined
|
|
42
|
+
? undefined
|
|
43
|
+
: bytesToBase64(request.associatedData),
|
|
44
|
+
}),
|
|
45
|
+
);
|
|
46
|
+
return {
|
|
47
|
+
plaintext: Redacted.make(base64ToBytes(unwrapSecretValue(res.plaintext ?? ""))),
|
|
48
|
+
};
|
|
49
|
+
}),
|
|
50
|
+
}),
|
|
51
|
+
),
|
|
52
|
+
).pipe(Layer.provide(FetchHttpClient.layer), Layer.provide(CredentialsFromAmbientOrEnv));
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type * as S3 from "@distilled.cloud/aws/s3";
|
|
2
|
+
import * as Binding from "alchemy/Binding";
|
|
3
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
4
|
+
import type * as Effect from "effect/Effect";
|
|
5
|
+
import type { Bucket } from "./Bucket.ts";
|
|
6
|
+
import type { TigrisCredentialsMissing } from "./Errors.ts";
|
|
7
|
+
|
|
8
|
+
export interface DeleteObjectRequest extends Omit<S3.DeleteObjectRequest, "Bucket"> {}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Runtime binding for Tigris `DeleteObject` over the S3 API.
|
|
12
|
+
*
|
|
13
|
+
* Bind this operation to a {@link Bucket} in Service init. Provide
|
|
14
|
+
* {@link DeleteObjectHttp}.
|
|
15
|
+
*
|
|
16
|
+
*
|
|
17
|
+
* ### Deleting Objects
|
|
18
|
+
* **Example:** Delete an Object
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const deleteObject = yield* Fly.DeleteObject(Data);
|
|
21
|
+
* yield* deleteObject({ Key: "hello.txt" });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @binding
|
|
25
|
+
* @product Bucket
|
|
26
|
+
*/
|
|
27
|
+
export interface DeleteObject extends Binding.Service<
|
|
28
|
+
DeleteObject,
|
|
29
|
+
"Fly.DeleteObject",
|
|
30
|
+
(
|
|
31
|
+
bucket: Bucket,
|
|
32
|
+
) => Effect.Effect<
|
|
33
|
+
(
|
|
34
|
+
request: DeleteObjectRequest,
|
|
35
|
+
) => Effect.Effect<
|
|
36
|
+
S3.DeleteObjectOutput,
|
|
37
|
+
S3.DeleteObjectError | TigrisCredentialsMissing,
|
|
38
|
+
RuntimeContext
|
|
39
|
+
>
|
|
40
|
+
>
|
|
41
|
+
> {}
|
|
42
|
+
|
|
43
|
+
export const DeleteObject = Binding.Service<DeleteObject>("Fly.DeleteObject");
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as S3 from "@distilled.cloud/aws/s3";
|
|
2
|
+
import * as Layer from "effect/Layer";
|
|
3
|
+
import { makeTigrisS3Binding } from "./BucketBinding.ts";
|
|
4
|
+
import { DeleteObject } from "./DeleteObject.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* HTTP implementation of {@link DeleteObject}. Calls distilled S3
|
|
8
|
+
* `deleteObject` against the Tigris endpoint with the bucket's credentials.
|
|
9
|
+
*
|
|
10
|
+
* @layer
|
|
11
|
+
* @product Bucket
|
|
12
|
+
* @provides Fly.DeleteObject
|
|
13
|
+
*/
|
|
14
|
+
export const DeleteObjectHttp = Layer.effect(
|
|
15
|
+
DeleteObject,
|
|
16
|
+
makeTigrisS3Binding({
|
|
17
|
+
tag: "Fly.DeleteObject",
|
|
18
|
+
operation: S3.deleteObject,
|
|
19
|
+
}),
|
|
20
|
+
);
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { FlyMachineConfig, FlyStopConfigSignal } from "@distilled.cloud/fly-io/machines";
|
|
2
|
+
import * as Data from "effect/Data";
|
|
3
|
+
import * as Duration from "effect/Duration";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import { pinsFromConfig } from "./DeploymentImages.ts";
|
|
6
|
+
import type { MachineServiceCheck } from "./Machine.ts";
|
|
7
|
+
|
|
8
|
+
/** Replacement/readiness policy shared by Machines, Services, and websites; not an App-wide deployment lock. */
|
|
9
|
+
export interface MachineDeploy {
|
|
10
|
+
/** Sequential in-place updates, or a checked replacement set. @default "rolling" */
|
|
11
|
+
strategy: "rolling" | "bluegreen";
|
|
12
|
+
/** Readiness deadline after startup, positive and at most 300 seconds. A deadline-only change does not replace Machines. @default "60 seconds" */
|
|
13
|
+
healthTimeout?: Duration.Input;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Process shutdown policy. Retirement uses the predecessor's own policy; raw images and external website servers own signal handling and drain. */
|
|
17
|
+
export interface MachineShutdown {
|
|
18
|
+
/** Signal sent before termination. Managed Services support SIGTERM and SIGINT. @default "SIGTERM" */
|
|
19
|
+
signal?: Exclude<FlyStopConfigSignal, "SIGKILL">;
|
|
20
|
+
/** Grace period, greater than zero and at most 300 seconds. @default "30 seconds" */
|
|
21
|
+
timeout?: Duration.Input;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Named readiness check for a worker without public proxy ports. */
|
|
25
|
+
export interface MachineCheck extends MachineServiceCheck {
|
|
26
|
+
/** Port inside the Machine to check. */
|
|
27
|
+
port: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class InvalidDeployment extends Data.TaggedError("Fly.InvalidDeployment")<{
|
|
31
|
+
message: string;
|
|
32
|
+
}> {}
|
|
33
|
+
|
|
34
|
+
export interface DeploymentPolicy {
|
|
35
|
+
bluegreen: boolean;
|
|
36
|
+
healthTimeoutMs: number;
|
|
37
|
+
shutdown:
|
|
38
|
+
| { signal: Exclude<FlyStopConfigSignal, "SIGKILL">; timeout: string; timeoutMs: number }
|
|
39
|
+
| undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const duration = (value: Duration.Input, name: string, maximum: number) =>
|
|
43
|
+
Effect.try({
|
|
44
|
+
try: () => {
|
|
45
|
+
const milliseconds = Duration.toMillis(value);
|
|
46
|
+
if (!Number.isSafeInteger(milliseconds) || milliseconds <= 0 || milliseconds > maximum) {
|
|
47
|
+
throw new Error("invalid duration");
|
|
48
|
+
}
|
|
49
|
+
return milliseconds;
|
|
50
|
+
},
|
|
51
|
+
catch: () =>
|
|
52
|
+
new InvalidDeployment({
|
|
53
|
+
message: `${name} must be a finite positive duration no greater than ${maximum / 1000} seconds.`,
|
|
54
|
+
}),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
export const deploymentPolicy = Effect.fn(function* (
|
|
58
|
+
deploy: MachineDeploy | undefined,
|
|
59
|
+
shutdown: MachineShutdown | undefined,
|
|
60
|
+
managed = false,
|
|
61
|
+
) {
|
|
62
|
+
const bluegreen = deploy?.strategy === "bluegreen";
|
|
63
|
+
const healthTimeoutMs = yield* duration(
|
|
64
|
+
deploy?.healthTimeout ?? "60 seconds",
|
|
65
|
+
"deploy.healthTimeout",
|
|
66
|
+
300_000,
|
|
67
|
+
);
|
|
68
|
+
const enabled = bluegreen || shutdown !== undefined;
|
|
69
|
+
const signal = shutdown?.signal ?? "SIGTERM";
|
|
70
|
+
if (
|
|
71
|
+
enabled &&
|
|
72
|
+
!["SIGHUP", "SIGINT", "SIGQUIT", "SIGUSR1", "SIGUSR2", "SIGTERM"].includes(signal)
|
|
73
|
+
) {
|
|
74
|
+
return yield* new InvalidDeployment({
|
|
75
|
+
message: "shutdown.signal must be a supported graceful Fly signal, not SIGKILL.",
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (managed && enabled && signal !== "SIGTERM" && signal !== "SIGINT") {
|
|
79
|
+
return yield* new InvalidDeployment({
|
|
80
|
+
message: "Managed Fly Services support SIGTERM and SIGINT shutdown signals.",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
const timeoutMs = enabled
|
|
84
|
+
? yield* duration(shutdown?.timeout ?? "30 seconds", "shutdown.timeout", 300_000)
|
|
85
|
+
: undefined;
|
|
86
|
+
return {
|
|
87
|
+
bluegreen,
|
|
88
|
+
healthTimeoutMs,
|
|
89
|
+
shutdown:
|
|
90
|
+
timeoutMs === undefined ? undefined : { signal, timeout: `${timeoutMs}ms`, timeoutMs },
|
|
91
|
+
} satisfies DeploymentPolicy;
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
export const validateDeployment = (
|
|
95
|
+
policy: DeploymentPolicy,
|
|
96
|
+
config: FlyMachineConfig,
|
|
97
|
+
mounted: boolean,
|
|
98
|
+
skipLaunch = false,
|
|
99
|
+
) => {
|
|
100
|
+
if (!policy.bluegreen) return Effect.void;
|
|
101
|
+
let message: string | undefined;
|
|
102
|
+
if (mounted)
|
|
103
|
+
message = "Blue/green deployments cannot attach volumes, including MountVolume bindings.";
|
|
104
|
+
else if (config.containers !== undefined && pinsFromConfig(config) === undefined)
|
|
105
|
+
message =
|
|
106
|
+
"Blue/green multi-container Machines require unique names and immutable repository@sha256 image references for every container.";
|
|
107
|
+
else if (skipLaunch || config.auto_destroy || config.restart?.policy === "no")
|
|
108
|
+
message = "Blue/green deployments require a persistent, launched Machine.";
|
|
109
|
+
else if (
|
|
110
|
+
(config.services ?? []).some(
|
|
111
|
+
(service) => (service.ports?.length ?? 0) > 0 && !service.checks?.length,
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
message = "Every published service needs a service health check for blue/green deployment.";
|
|
115
|
+
else if (
|
|
116
|
+
!(config.services ?? []).some((service) => service.checks?.length) &&
|
|
117
|
+
!Object.keys(config.checks ?? {}).length
|
|
118
|
+
)
|
|
119
|
+
message = "Blue/green deployments require readiness checks.";
|
|
120
|
+
return message ? Effect.fail(new InvalidDeployment({ message })) : Effect.void;
|
|
121
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { FlyMachineConfig } from "@distilled.cloud/fly-io/machines";
|
|
2
|
+
import * as Option from "effect/Option";
|
|
3
|
+
import * as Schema from "effect/Schema";
|
|
4
|
+
import { alchemyMetadataKeys as keys } from "./Metadata.ts";
|
|
5
|
+
|
|
6
|
+
const ImageSet = Schema.Array(Schema.Struct({ name: Schema.String, image: Schema.String }));
|
|
7
|
+
export type ContainerImagePin = { name: string; image: string };
|
|
8
|
+
|
|
9
|
+
/** Blue/green needs immutable image references that survive a crash. */
|
|
10
|
+
export const isImmutableImage = (image: string): boolean =>
|
|
11
|
+
/^[a-zA-Z0-9][a-zA-Z0-9._:/-]*@sha256:[a-fA-F0-9]{64}$/.test(image);
|
|
12
|
+
|
|
13
|
+
const canonical = (pins: readonly ContainerImagePin[]): ContainerImagePin[] =>
|
|
14
|
+
[...pins].sort((a, b) => a.name.localeCompare(b.name));
|
|
15
|
+
|
|
16
|
+
const valid = (pins: readonly ContainerImagePin[]): boolean =>
|
|
17
|
+
pins.length > 0 &&
|
|
18
|
+
new Set(pins.map(({ name }) => name)).size === pins.length &&
|
|
19
|
+
pins.every(({ name, image }) => name.trim().length > 0 && isImmutableImage(image));
|
|
20
|
+
|
|
21
|
+
export const pinsFromConfig = (
|
|
22
|
+
config: FlyMachineConfig | undefined,
|
|
23
|
+
): ContainerImagePin[] | undefined => {
|
|
24
|
+
const containers = config?.containers;
|
|
25
|
+
if (!containers?.length) return undefined;
|
|
26
|
+
const pins = containers.map(({ name, image }) => ({
|
|
27
|
+
name: name ?? "",
|
|
28
|
+
image: image ?? "",
|
|
29
|
+
}));
|
|
30
|
+
return valid(pins) ? canonical(pins) : undefined;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const encodeImageSet = (pins: readonly ContainerImagePin[]): string | undefined =>
|
|
34
|
+
valid(pins) ? JSON.stringify(canonical(pins)) : undefined;
|
|
35
|
+
|
|
36
|
+
export const decodeImageSet = (raw: string | undefined): ContainerImagePin[] | undefined => {
|
|
37
|
+
if (raw === undefined) return undefined;
|
|
38
|
+
const decoded = Schema.decodeUnknownOption(Schema.fromJsonString(ImageSet))(raw);
|
|
39
|
+
if (!Option.isSome(decoded)) return undefined;
|
|
40
|
+
const pins = decoded.value;
|
|
41
|
+
return valid(pins) ? canonical(pins) : undefined;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const sameImageSet = (
|
|
45
|
+
left: readonly ContainerImagePin[] | undefined,
|
|
46
|
+
right: readonly ContainerImagePin[] | undefined,
|
|
47
|
+
): boolean => {
|
|
48
|
+
const a = left === undefined ? undefined : encodeImageSet(left);
|
|
49
|
+
const b = right === undefined ? undefined : encodeImageSet(right);
|
|
50
|
+
return a !== undefined && b !== undefined && a === b;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** Protocol-2 metadata and the authoritative readback config must describe exactly the same set. */
|
|
54
|
+
export const validObservedImageSet = (machine: { config?: FlyMachineConfig }): boolean => {
|
|
55
|
+
const metadata = machine.config?.metadata;
|
|
56
|
+
if (metadata?.[keys.protocol] !== "2" || metadata[keys.image] !== undefined) return false;
|
|
57
|
+
return sameImageSet(
|
|
58
|
+
decodeImageSet(metadata[keys.containerImageSet]),
|
|
59
|
+
pinsFromConfig(machine.config),
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/** Keep all named pins when changing service or idle policy on a candidate. */
|
|
64
|
+
export const applyImageSet = (
|
|
65
|
+
config: FlyMachineConfig,
|
|
66
|
+
pins: readonly ContainerImagePin[],
|
|
67
|
+
): FlyMachineConfig | undefined => {
|
|
68
|
+
if (!valid(pins) || !config.containers) return undefined;
|
|
69
|
+
const byName = new Map(pins.map((pin) => [pin.name, pin.image]));
|
|
70
|
+
if (
|
|
71
|
+
config.containers.length !== byName.size ||
|
|
72
|
+
new Set(config.containers.map(({ name }) => name)).size !== config.containers.length ||
|
|
73
|
+
config.containers.some(({ name }) => name === undefined || !byName.has(name))
|
|
74
|
+
)
|
|
75
|
+
return undefined;
|
|
76
|
+
return {
|
|
77
|
+
...config,
|
|
78
|
+
image: undefined,
|
|
79
|
+
containers: config.containers.map((container) => ({
|
|
80
|
+
...container,
|
|
81
|
+
image: byName.get(container.name!),
|
|
82
|
+
})),
|
|
83
|
+
};
|
|
84
|
+
};
|