@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,548 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CertificateCheckResponse,
|
|
3
|
+
CertificateDetail,
|
|
4
|
+
CertificateSummary,
|
|
5
|
+
CertificateValidation as FlyCertificateValidation,
|
|
6
|
+
DNSRequirements,
|
|
7
|
+
} from "@distilled.cloud/fly-io/machines";
|
|
8
|
+
import * as machines from "@distilled.cloud/fly-io/machines";
|
|
9
|
+
import { isResolved } from "alchemy/Diff";
|
|
10
|
+
import * as Provider from "alchemy/Provider";
|
|
11
|
+
import { Resource } from "alchemy/Resource";
|
|
12
|
+
import * as Data from "effect/Data";
|
|
13
|
+
import * as Effect from "effect/Effect";
|
|
14
|
+
import * as Redacted from "effect/Redacted";
|
|
15
|
+
import * as Schedule from "effect/Schedule";
|
|
16
|
+
import { listOwnedApps } from "./App.ts";
|
|
17
|
+
import type { App } from "./App.ts";
|
|
18
|
+
import type { Providers } from "./Providers.ts";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A resource-valued prop: the resource itself, or an Effect that produces
|
|
22
|
+
* it (so `yield* App(...)` and `App(...)` both type-check).
|
|
23
|
+
*/
|
|
24
|
+
type Ref<T> = T | Effect.Effect<T, never, Providers>;
|
|
25
|
+
|
|
26
|
+
export type CertificateKind = "acme" | "custom";
|
|
27
|
+
|
|
28
|
+
export type CertificateSource = "custom" | "fly";
|
|
29
|
+
|
|
30
|
+
export type CertificateDnsRequirements = {
|
|
31
|
+
a?: string[];
|
|
32
|
+
aaaa?: string[];
|
|
33
|
+
acmeChallenge?: { name?: string; target?: string };
|
|
34
|
+
cname?: string;
|
|
35
|
+
ownership?: { appValue?: string; name?: string; orgValue?: string };
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export type CertificateValidationState = {
|
|
39
|
+
alpnConfigured?: boolean;
|
|
40
|
+
dnsConfigured?: boolean;
|
|
41
|
+
httpConfigured?: boolean;
|
|
42
|
+
ownershipTxtConfigured?: boolean;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export interface CertificateProps {
|
|
46
|
+
/**
|
|
47
|
+
* Parent Fly App. Accepts a `Fly.App` resource or an Effect that
|
|
48
|
+
* produces one. Changing the App replaces the Certificate.
|
|
49
|
+
*/
|
|
50
|
+
app: Ref<App>;
|
|
51
|
+
/**
|
|
52
|
+
* Hostname this Certificate covers. Identity of the resource.
|
|
53
|
+
* Changing it replaces the Certificate.
|
|
54
|
+
*/
|
|
55
|
+
hostname: string;
|
|
56
|
+
/**
|
|
57
|
+
* How the Certificate is issued. `"acme"` requests a Let's Encrypt
|
|
58
|
+
* certificate (`createAppAcmeCertificate`). `"custom"` uploads a PEM
|
|
59
|
+
* (`createAppCustomCertificate`). Changing kind replaces.
|
|
60
|
+
*
|
|
61
|
+
* @default "acme"
|
|
62
|
+
*/
|
|
63
|
+
kind?: CertificateKind;
|
|
64
|
+
/**
|
|
65
|
+
* PEM-encoded certificate chain. Required when `kind` is `"custom"`.
|
|
66
|
+
* Updating it re-uploads in place (custom create upsert, or
|
|
67
|
+
* delete+create if the API conflicts).
|
|
68
|
+
*/
|
|
69
|
+
fullchain?: string;
|
|
70
|
+
/**
|
|
71
|
+
* PEM-encoded private key. Required when `kind` is `"custom"`. Wrap
|
|
72
|
+
* with `Redacted.make` to keep it out of logs. Never stored in
|
|
73
|
+
* attributes.
|
|
74
|
+
*/
|
|
75
|
+
privateKey?: Redacted.Redacted<string> | string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type Certificate = Resource<
|
|
79
|
+
"Fly.Certificate",
|
|
80
|
+
CertificateProps,
|
|
81
|
+
{
|
|
82
|
+
/** Physical Fly App name the Certificate is attached to. */
|
|
83
|
+
appName: string;
|
|
84
|
+
/** Hostname this Certificate covers. Identity of the resource. */
|
|
85
|
+
hostname: string;
|
|
86
|
+
/** Observed status (`active`, `pending_validation`, …). */
|
|
87
|
+
status: string | undefined;
|
|
88
|
+
/** Whether DNS/ownership validation has completed. */
|
|
89
|
+
configured: boolean | undefined;
|
|
90
|
+
/** Whether ACME issuance has been requested for this hostname. */
|
|
91
|
+
acmeRequested: boolean | undefined;
|
|
92
|
+
/** DNS records Fly expects for validation. */
|
|
93
|
+
dnsRequirements: CertificateDnsRequirements | undefined;
|
|
94
|
+
/** Per-challenge validation flags. */
|
|
95
|
+
validation: CertificateValidationState | undefined;
|
|
96
|
+
/** Observed source: `"custom"` for uploaded PEMs, `"fly"` for ACME. */
|
|
97
|
+
source: CertificateSource;
|
|
98
|
+
},
|
|
99
|
+
never,
|
|
100
|
+
Providers
|
|
101
|
+
>;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* A Fly.Certificate covers a hostname on an {@link App}. Default
|
|
105
|
+
* `kind` is `"acme"` (Let's Encrypt). `"custom"` uploads a PEM.
|
|
106
|
+
*
|
|
107
|
+
* IPs and certificates attach to the App. A {@link Service} publishes
|
|
108
|
+
* ports. Fly's proxy terminates TLS on 443 once the certificate is
|
|
109
|
+
* `configured`.
|
|
110
|
+
*
|
|
111
|
+
* @see https://fly.io/docs/machines/api/certificates-resource/
|
|
112
|
+
*
|
|
113
|
+
* ### ACME certificates
|
|
114
|
+
* Request Let's Encrypt for a hostname. The Service does not change.
|
|
115
|
+
* Yield the certificate in the Stack. Point DNS at the App.
|
|
116
|
+
*
|
|
117
|
+
* **Example:** Let's Encrypt
|
|
118
|
+
* ```typescript
|
|
119
|
+
* export const Www = Fly.Certificate("Www", {
|
|
120
|
+
* app: Site,
|
|
121
|
+
* hostname: "www.example.com",
|
|
122
|
+
* });
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* :::caution[Changing `hostname` replaces the Certificate]
|
|
126
|
+
* Hostname is the identity. The old hostname is deleted, then the new
|
|
127
|
+
* one is created.
|
|
128
|
+
* :::
|
|
129
|
+
*
|
|
130
|
+
* :::caution[Changing `app` or `kind` replaces the Certificate]
|
|
131
|
+
* The certificate is created on the new App or with the new issuer.
|
|
132
|
+
* :::
|
|
133
|
+
*
|
|
134
|
+
* ### DNS
|
|
135
|
+
* Point an A record at a `shared_v4` {@link IpAssignment} and an AAAA
|
|
136
|
+
* at `v6`. Plus whatever `dnsRequirements` lists for the ACME
|
|
137
|
+
* challenge. Alchemy re-checks via `checkAppCertificate` while
|
|
138
|
+
* `configured` is false.
|
|
139
|
+
*
|
|
140
|
+
* Observed attrs include `status`, `configured`, `acmeRequested`,
|
|
141
|
+
* `dnsRequirements`, and `validation`.
|
|
142
|
+
*
|
|
143
|
+
* **Example:** Yield next to a Service
|
|
144
|
+
* ```typescript
|
|
145
|
+
* export default Alchemy.Stack(
|
|
146
|
+
* "MyApp",
|
|
147
|
+
* { providers: Fly.providers(), state: Alchemy.localState() },
|
|
148
|
+
* Effect.gen(function* () {
|
|
149
|
+
* const api = yield* Api;
|
|
150
|
+
* const ip = yield* PublicIp;
|
|
151
|
+
* const v6 = yield* V6;
|
|
152
|
+
* const www = yield* Www;
|
|
153
|
+
* return {
|
|
154
|
+
* url: api.url,
|
|
155
|
+
* ip: ip.ip,
|
|
156
|
+
* v6: v6.ip,
|
|
157
|
+
* dns: www.dnsRequirements,
|
|
158
|
+
* };
|
|
159
|
+
* }),
|
|
160
|
+
* );
|
|
161
|
+
* ```
|
|
162
|
+
*
|
|
163
|
+
* ### Custom certificates
|
|
164
|
+
* `"custom"` uploads `fullchain` and `privateKey`. Wrap the key with
|
|
165
|
+
* `Redacted.make` so it never logs. Never stored in attributes.
|
|
166
|
+
* Updating the PEM re-uploads in place.
|
|
167
|
+
*
|
|
168
|
+
* **Example:** Upload a PEM
|
|
169
|
+
* ```typescript
|
|
170
|
+
* export const Www = Fly.Certificate("Www", {
|
|
171
|
+
* app: Site,
|
|
172
|
+
* hostname: "www.example.com",
|
|
173
|
+
* kind: "custom",
|
|
174
|
+
* fullchain: pem,
|
|
175
|
+
* privateKey: Redacted.make(key),
|
|
176
|
+
* });
|
|
177
|
+
* ```
|
|
178
|
+
*
|
|
179
|
+
* @resource
|
|
180
|
+
* @product Certificate
|
|
181
|
+
*/
|
|
182
|
+
export const Certificate = Resource<Certificate>("Fly.Certificate");
|
|
183
|
+
|
|
184
|
+
export class CertificateNotCreated extends Data.TaggedError("Fly.CertificateNotCreated")<{
|
|
185
|
+
appName: string;
|
|
186
|
+
hostname: string;
|
|
187
|
+
}> {}
|
|
188
|
+
|
|
189
|
+
export class CertificateAppMissing extends Data.TaggedError("Fly.CertificateAppMissing")<{
|
|
190
|
+
hostname: string;
|
|
191
|
+
}> {}
|
|
192
|
+
|
|
193
|
+
export class CertificateMaterialRequired extends Data.TaggedError(
|
|
194
|
+
"Fly.CertificateMaterialRequired",
|
|
195
|
+
)<{
|
|
196
|
+
hostname: string;
|
|
197
|
+
}> {}
|
|
198
|
+
|
|
199
|
+
type ObservedCert = CertificateDetail | CertificateCheckResponse;
|
|
200
|
+
|
|
201
|
+
const appNameOf = (value: unknown): string | undefined => {
|
|
202
|
+
if (value === null || typeof value !== "object") return undefined;
|
|
203
|
+
const rec = value as { appName?: unknown; name?: unknown };
|
|
204
|
+
if (typeof rec.appName === "string" && rec.appName.length > 0) {
|
|
205
|
+
return rec.appName;
|
|
206
|
+
}
|
|
207
|
+
if (typeof rec.name === "string" && rec.name.length > 0) {
|
|
208
|
+
return rec.name;
|
|
209
|
+
}
|
|
210
|
+
return undefined;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const unwrapSecret = (
|
|
214
|
+
value: Redacted.Redacted<string> | string | undefined,
|
|
215
|
+
): string | undefined => {
|
|
216
|
+
if (value === undefined) return undefined;
|
|
217
|
+
return Redacted.isRedacted(value) ? Redacted.value(value) : value;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const normalizePem = (pem: string | undefined): string => (pem ?? "").replace(/\r\n/g, "\n").trim();
|
|
221
|
+
|
|
222
|
+
const desiredKind = (props: Pick<CertificateProps, "kind">): CertificateKind =>
|
|
223
|
+
props.kind ?? "acme";
|
|
224
|
+
|
|
225
|
+
const kindOf = (source: CertificateSource): CertificateKind =>
|
|
226
|
+
source === "custom" ? "custom" : "acme";
|
|
227
|
+
|
|
228
|
+
const sourceOf = (detail: ObservedCert): CertificateSource => {
|
|
229
|
+
const entries = detail.certificates ?? [];
|
|
230
|
+
if (entries.some((entry) => entry.source === "custom")) return "custom";
|
|
231
|
+
if (entries.some((entry) => entry.source === "fly")) return "fly";
|
|
232
|
+
return detail.acme_requested === true ? "fly" : "custom";
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const sourceFromSummary = (summary: CertificateSummary): CertificateSource =>
|
|
236
|
+
summary.has_custom_certificate === true ? "custom" : "fly";
|
|
237
|
+
|
|
238
|
+
const toDnsRequirements = (
|
|
239
|
+
req: DNSRequirements | undefined,
|
|
240
|
+
): CertificateDnsRequirements | undefined => {
|
|
241
|
+
if (req === undefined) return undefined;
|
|
242
|
+
return {
|
|
243
|
+
a: req.a,
|
|
244
|
+
aaaa: req.aaaa,
|
|
245
|
+
acmeChallenge:
|
|
246
|
+
req.acme_challenge === undefined
|
|
247
|
+
? undefined
|
|
248
|
+
: {
|
|
249
|
+
name: req.acme_challenge.name,
|
|
250
|
+
target: req.acme_challenge.target,
|
|
251
|
+
},
|
|
252
|
+
cname: req.cname,
|
|
253
|
+
ownership:
|
|
254
|
+
req.ownership === undefined
|
|
255
|
+
? undefined
|
|
256
|
+
: {
|
|
257
|
+
appValue: req.ownership.app_value,
|
|
258
|
+
name: req.ownership.name,
|
|
259
|
+
orgValue: req.ownership.org_value,
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
const toValidation = (
|
|
265
|
+
validation: FlyCertificateValidation | undefined,
|
|
266
|
+
): CertificateValidationState | undefined => {
|
|
267
|
+
if (validation === undefined) return undefined;
|
|
268
|
+
return {
|
|
269
|
+
alpnConfigured: validation.alpn_configured,
|
|
270
|
+
dnsConfigured: validation.dns_configured,
|
|
271
|
+
httpConfigured: validation.http_configured,
|
|
272
|
+
ownershipTxtConfigured: validation.ownership_txt_configured,
|
|
273
|
+
};
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const toAttrs = (
|
|
277
|
+
appName: string,
|
|
278
|
+
detail: ObservedCert,
|
|
279
|
+
fallbackHostname?: string,
|
|
280
|
+
): Certificate["Attributes"] => ({
|
|
281
|
+
appName,
|
|
282
|
+
hostname: detail.hostname ?? fallbackHostname ?? "",
|
|
283
|
+
status: detail.status,
|
|
284
|
+
configured: detail.configured,
|
|
285
|
+
acmeRequested: detail.acme_requested,
|
|
286
|
+
dnsRequirements: toDnsRequirements(detail.dns_requirements),
|
|
287
|
+
validation: toValidation(detail.validation),
|
|
288
|
+
source: sourceOf(detail),
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const toAttrsFromSummary = (
|
|
292
|
+
appName: string,
|
|
293
|
+
summary: CertificateSummary,
|
|
294
|
+
): Certificate["Attributes"] | undefined => {
|
|
295
|
+
const hostname = summary.hostname;
|
|
296
|
+
if (hostname === undefined || hostname.length === 0) return undefined;
|
|
297
|
+
return {
|
|
298
|
+
appName,
|
|
299
|
+
hostname,
|
|
300
|
+
status: summary.status,
|
|
301
|
+
configured: summary.configured,
|
|
302
|
+
acmeRequested: summary.acme_requested,
|
|
303
|
+
dnsRequirements: undefined,
|
|
304
|
+
validation: {
|
|
305
|
+
alpnConfigured: summary.acme_alpn_configured,
|
|
306
|
+
dnsConfigured: summary.acme_dns_configured,
|
|
307
|
+
httpConfigured: summary.acme_http_configured,
|
|
308
|
+
ownershipTxtConfigured: summary.ownership_txt_configured,
|
|
309
|
+
},
|
|
310
|
+
source: sourceFromSummary(summary),
|
|
311
|
+
};
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const getByHostname = (appName: string, hostname: string) =>
|
|
315
|
+
machines
|
|
316
|
+
.getAppCertificate({ app_name: appName, hostname })
|
|
317
|
+
.pipe(Effect.catchTag("NotFound", () => Effect.succeed(undefined)));
|
|
318
|
+
|
|
319
|
+
const listAppCertificates = (appName: string) =>
|
|
320
|
+
Effect.gen(function* () {
|
|
321
|
+
const all: CertificateSummary[] = [];
|
|
322
|
+
let cursor: string | undefined;
|
|
323
|
+
for (let i = 0; i < 8; i++) {
|
|
324
|
+
const page = yield* machines
|
|
325
|
+
.listAppCertificates({
|
|
326
|
+
app_name: appName,
|
|
327
|
+
cursor,
|
|
328
|
+
limit: 100,
|
|
329
|
+
})
|
|
330
|
+
.pipe(
|
|
331
|
+
Effect.catchTag(["NotFound", "Forbidden"], () =>
|
|
332
|
+
Effect.succeed({
|
|
333
|
+
certificates: [] as CertificateSummary[],
|
|
334
|
+
next_cursor: undefined,
|
|
335
|
+
}),
|
|
336
|
+
),
|
|
337
|
+
);
|
|
338
|
+
all.push(...(page.certificates ?? []));
|
|
339
|
+
if (page.next_cursor === undefined || page.next_cursor.length === 0) {
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
cursor = page.next_cursor;
|
|
343
|
+
}
|
|
344
|
+
return all;
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
const waitUntilGone = (appName: string, hostname: string) =>
|
|
348
|
+
getByHostname(appName, hostname).pipe(
|
|
349
|
+
Effect.map((found) => found === undefined),
|
|
350
|
+
Effect.repeat({
|
|
351
|
+
schedule: Schedule.spaced("1 second"),
|
|
352
|
+
until: (gone) => gone,
|
|
353
|
+
times: 8,
|
|
354
|
+
}),
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
const requireCustomMaterial = (
|
|
358
|
+
hostname: string,
|
|
359
|
+
fullchain: string | undefined,
|
|
360
|
+
privateKey: string | undefined,
|
|
361
|
+
) =>
|
|
362
|
+
fullchain === undefined ||
|
|
363
|
+
fullchain.length === 0 ||
|
|
364
|
+
privateKey === undefined ||
|
|
365
|
+
privateKey.length === 0
|
|
366
|
+
? new CertificateMaterialRequired({ hostname })
|
|
367
|
+
: undefined;
|
|
368
|
+
|
|
369
|
+
const createAcme = (appName: string, hostname: string) =>
|
|
370
|
+
machines
|
|
371
|
+
.createAppAcmeCertificate({
|
|
372
|
+
app_name: appName,
|
|
373
|
+
hostname,
|
|
374
|
+
})
|
|
375
|
+
.pipe(Effect.catchTag("Conflict", () => Effect.succeed(undefined)));
|
|
376
|
+
|
|
377
|
+
const createCustom = (appName: string, hostname: string, fullchain: string, privateKey: string) =>
|
|
378
|
+
machines
|
|
379
|
+
.createAppCustomCertificate({
|
|
380
|
+
app_name: appName,
|
|
381
|
+
hostname,
|
|
382
|
+
fullchain,
|
|
383
|
+
private_key: privateKey,
|
|
384
|
+
})
|
|
385
|
+
.pipe(Effect.catchTag("Conflict", () => Effect.succeed(undefined)));
|
|
386
|
+
|
|
387
|
+
const replaceCustom = (appName: string, hostname: string, fullchain: string, privateKey: string) =>
|
|
388
|
+
Effect.gen(function* () {
|
|
389
|
+
yield* machines
|
|
390
|
+
.deleteAppCustomCertificate({
|
|
391
|
+
app_name: appName,
|
|
392
|
+
hostname,
|
|
393
|
+
})
|
|
394
|
+
.pipe(Effect.catchTag("NotFound", () => Effect.void));
|
|
395
|
+
yield* machines.createAppCustomCertificate({
|
|
396
|
+
app_name: appName,
|
|
397
|
+
hostname,
|
|
398
|
+
fullchain,
|
|
399
|
+
private_key: privateKey,
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
export const CertificateProvider = () =>
|
|
404
|
+
Provider.succeed(Certificate, {
|
|
405
|
+
stables: ["appName", "hostname", "source"],
|
|
406
|
+
nuke: { dependsOn: ["Fly.App"] },
|
|
407
|
+
|
|
408
|
+
diff: Effect.fn(function* ({ news, output }) {
|
|
409
|
+
if (news === undefined || !isResolved(news)) return undefined;
|
|
410
|
+
if (output === undefined) return undefined;
|
|
411
|
+
const appName = appNameOf(news.app);
|
|
412
|
+
const appChanged = appName !== undefined && appName !== output.appName;
|
|
413
|
+
const hostnameChanged = news.hostname !== output.hostname;
|
|
414
|
+
const nextKind = desiredKind(news);
|
|
415
|
+
const kindChanged = nextKind !== kindOf(output.source);
|
|
416
|
+
if (appChanged || hostnameChanged || kindChanged) {
|
|
417
|
+
return {
|
|
418
|
+
action: "replace" as const,
|
|
419
|
+
// Same hostname cannot exist twice — delete the old kind first.
|
|
420
|
+
deleteFirst: !hostnameChanged && !appChanged,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
return undefined;
|
|
424
|
+
}),
|
|
425
|
+
|
|
426
|
+
read: Effect.fn(function* ({ olds, output }) {
|
|
427
|
+
const appName = output?.appName ?? appNameOf(olds?.app);
|
|
428
|
+
const hostname = output?.hostname ?? olds?.hostname;
|
|
429
|
+
if (appName === undefined || hostname === undefined) return undefined;
|
|
430
|
+
const found = yield* getByHostname(appName, hostname);
|
|
431
|
+
if (found === undefined) return undefined;
|
|
432
|
+
return toAttrs(appName, found, hostname);
|
|
433
|
+
}),
|
|
434
|
+
|
|
435
|
+
list: Effect.fn(function* () {
|
|
436
|
+
const apps = yield* listOwnedApps();
|
|
437
|
+
const rows = yield* Effect.forEach(
|
|
438
|
+
apps,
|
|
439
|
+
(app) =>
|
|
440
|
+
listAppCertificates(app.appName).pipe(
|
|
441
|
+
Effect.map((certs) =>
|
|
442
|
+
certs.flatMap((item) => {
|
|
443
|
+
const attrs = toAttrsFromSummary(app.appName, item);
|
|
444
|
+
return attrs === undefined ? [] : [attrs];
|
|
445
|
+
}),
|
|
446
|
+
),
|
|
447
|
+
),
|
|
448
|
+
{ concurrency: 8 },
|
|
449
|
+
);
|
|
450
|
+
return rows.flat();
|
|
451
|
+
}),
|
|
452
|
+
|
|
453
|
+
reconcile: Effect.fn(function* ({ news, olds, output }) {
|
|
454
|
+
const props = news ?? ({} as CertificateProps);
|
|
455
|
+
const appName = appNameOf(props.app) ?? output?.appName;
|
|
456
|
+
const hostname = props.hostname ?? output?.hostname;
|
|
457
|
+
if (appName === undefined) {
|
|
458
|
+
return yield* new CertificateAppMissing({
|
|
459
|
+
hostname: hostname ?? "",
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
if (hostname === undefined || hostname.length === 0) {
|
|
463
|
+
return yield* new CertificateNotCreated({
|
|
464
|
+
appName,
|
|
465
|
+
hostname: "",
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const kind = desiredKind(props);
|
|
470
|
+
|
|
471
|
+
// Observe by cached identity, then by desired hostname.
|
|
472
|
+
let current =
|
|
473
|
+
output?.hostname !== undefined
|
|
474
|
+
? yield* getByHostname(
|
|
475
|
+
output.appName.length > 0 ? output.appName : appName,
|
|
476
|
+
output.hostname,
|
|
477
|
+
)
|
|
478
|
+
: undefined;
|
|
479
|
+
if (current === undefined && (output?.hostname !== hostname || output?.appName !== appName)) {
|
|
480
|
+
current = yield* getByHostname(appName, hostname);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
let createdThisPass = false;
|
|
484
|
+
if (current === undefined) {
|
|
485
|
+
if (kind === "custom") {
|
|
486
|
+
const fullchain = props.fullchain;
|
|
487
|
+
const privateKey = unwrapSecret(props.privateKey);
|
|
488
|
+
const missing = requireCustomMaterial(hostname, fullchain, privateKey);
|
|
489
|
+
if (missing !== undefined) return yield* missing;
|
|
490
|
+
const created = yield* createCustom(appName, hostname, fullchain!, privateKey!);
|
|
491
|
+
current = created ?? (yield* getByHostname(appName, hostname));
|
|
492
|
+
} else {
|
|
493
|
+
const created = yield* createAcme(appName, hostname);
|
|
494
|
+
current = created ?? (yield* getByHostname(appName, hostname));
|
|
495
|
+
}
|
|
496
|
+
createdThisPass = true;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (current === undefined) {
|
|
500
|
+
return yield* new CertificateNotCreated({ appName, hostname });
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (kind === "custom") {
|
|
504
|
+
const fullchain = props.fullchain;
|
|
505
|
+
const privateKey = unwrapSecret(props.privateKey);
|
|
506
|
+
const missing = requireCustomMaterial(hostname, fullchain, privateKey);
|
|
507
|
+
if (missing !== undefined) return yield* missing;
|
|
508
|
+
const previousChain = olds?.fullchain;
|
|
509
|
+
const previousKey = unwrapSecret(olds?.privateKey);
|
|
510
|
+
const materialChanged =
|
|
511
|
+
olds === undefined ||
|
|
512
|
+
normalizePem(fullchain) !== normalizePem(previousChain) ||
|
|
513
|
+
normalizePem(privateKey) !== normalizePem(previousKey);
|
|
514
|
+
if (!createdThisPass && materialChanged) {
|
|
515
|
+
const upserted = yield* createCustom(appName, hostname, fullchain!, privateKey!);
|
|
516
|
+
if (upserted === undefined) {
|
|
517
|
+
yield* replaceCustom(appName, hostname, fullchain!, privateKey!);
|
|
518
|
+
}
|
|
519
|
+
current = upserted ?? (yield* getByHostname(appName, hostname)) ?? current;
|
|
520
|
+
}
|
|
521
|
+
} else if (current.configured !== true) {
|
|
522
|
+
const checked = yield* machines
|
|
523
|
+
.checkAppCertificate({
|
|
524
|
+
app_name: appName,
|
|
525
|
+
hostname,
|
|
526
|
+
})
|
|
527
|
+
.pipe(Effect.catchTag(["NotFound", "BadRequest"], () => Effect.succeed(undefined)));
|
|
528
|
+
if (checked !== undefined) {
|
|
529
|
+
current = checked;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return toAttrs(appName, current, hostname);
|
|
534
|
+
}),
|
|
535
|
+
|
|
536
|
+
delete: Effect.fn(function* ({ output }) {
|
|
537
|
+
const appName = output.appName;
|
|
538
|
+
const hostname = output.hostname;
|
|
539
|
+
if (appName.length === 0 || hostname.length === 0) return;
|
|
540
|
+
yield* machines
|
|
541
|
+
.deleteAppCertificate({
|
|
542
|
+
app_name: appName,
|
|
543
|
+
hostname,
|
|
544
|
+
})
|
|
545
|
+
.pipe(Effect.catchTag("NotFound", () => Effect.void));
|
|
546
|
+
yield* waitUntilGone(appName, hostname);
|
|
547
|
+
}),
|
|
548
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CheckpointInfo as FlyCheckpoint,
|
|
3
|
+
CreateCheckpointError,
|
|
4
|
+
GetCheckpointError,
|
|
5
|
+
ListCheckpointsError,
|
|
6
|
+
RestoreCheckpointError,
|
|
7
|
+
StreamEvent,
|
|
8
|
+
} from "@distilled.cloud/fly-io/sprites";
|
|
9
|
+
import * as Binding from "alchemy/Binding";
|
|
10
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
11
|
+
import type * as Effect from "effect/Effect";
|
|
12
|
+
import type { Sprite } from "./Sprite.ts";
|
|
13
|
+
|
|
14
|
+
export interface CheckpointClient {
|
|
15
|
+
/**
|
|
16
|
+
* Create a checkpoint of the Sprite filesystem. Returns NDJSON
|
|
17
|
+
* progress events. The checkpoint id is in a `complete` event.
|
|
18
|
+
*/
|
|
19
|
+
create: (options?: {
|
|
20
|
+
comment?: string;
|
|
21
|
+
}) => Effect.Effect<ReadonlyArray<StreamEvent>, CreateCheckpointError, RuntimeContext>;
|
|
22
|
+
/** List checkpoints on the Sprite. */
|
|
23
|
+
list: () => Effect.Effect<ReadonlyArray<FlyCheckpoint>, ListCheckpointsError, RuntimeContext>;
|
|
24
|
+
/** Get one checkpoint by id (`v1`, `v2`, …). */
|
|
25
|
+
get: (checkpointId: string) => Effect.Effect<FlyCheckpoint, GetCheckpointError, RuntimeContext>;
|
|
26
|
+
/**
|
|
27
|
+
* Restore the Sprite filesystem to a checkpoint. Destructive.
|
|
28
|
+
* Returns NDJSON progress events.
|
|
29
|
+
*/
|
|
30
|
+
restore: (
|
|
31
|
+
checkpointId: string,
|
|
32
|
+
) => Effect.Effect<ReadonlyArray<StreamEvent>, RestoreCheckpointError, RuntimeContext>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Checkpoint and restore a {@link Sprite} filesystem.
|
|
37
|
+
*
|
|
38
|
+
*
|
|
39
|
+
* ### Create a checkpoint
|
|
40
|
+
* Bind the client in init. Provide {@link CheckpointHttp}.
|
|
41
|
+
*
|
|
42
|
+
* **Example:** Create
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const checkpoint = yield* Fly.Checkpoint(Box);
|
|
45
|
+
* yield* checkpoint.create({ comment: "before deploy" });
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* ### Restore
|
|
49
|
+
* Restore rewinds the filesystem. Running processes stop.
|
|
50
|
+
*
|
|
51
|
+
* **Example:** Restore v1
|
|
52
|
+
* ```typescript
|
|
53
|
+
* yield* checkpoint.restore("v1");
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* :::caution[Restore is destructive]
|
|
57
|
+
* The Sprite disk goes back to that checkpoint. Later writes are gone.
|
|
58
|
+
* :::
|
|
59
|
+
*
|
|
60
|
+
* @binding
|
|
61
|
+
* @product Sprite
|
|
62
|
+
*/
|
|
63
|
+
export interface Checkpoint extends Binding.Service<
|
|
64
|
+
Checkpoint,
|
|
65
|
+
"Fly.Checkpoint",
|
|
66
|
+
(sprite: Sprite) => Effect.Effect<CheckpointClient>
|
|
67
|
+
> {}
|
|
68
|
+
|
|
69
|
+
export const Checkpoint = Binding.Service<Checkpoint>("Fly.Checkpoint");
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as sprites from "@distilled.cloud/fly-io/sprites";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as FetchHttpClient from "effect/http/FetchHttpClient";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import { Checkpoint, type CheckpointClient } from "./Checkpoint.ts";
|
|
6
|
+
import { CredentialsFromAmbientOrEnv } from "./Credentials.ts";
|
|
7
|
+
import { makeHttpSpriteBinding } from "./SpriteHttp.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* HTTP implementation of {@link Checkpoint}. Provide it on the
|
|
11
|
+
* {@link Sprite}, {@link Service}, or Action Effect.
|
|
12
|
+
*
|
|
13
|
+
*
|
|
14
|
+
* ### Provide the layer
|
|
15
|
+
* **Example:** On a Sprite
|
|
16
|
+
* ```typescript
|
|
17
|
+
* Effect.gen(function* () {
|
|
18
|
+
* const checkpoint = yield* Fly.Checkpoint(Box);
|
|
19
|
+
* // ...
|
|
20
|
+
* }).pipe(Effect.provide(Fly.CheckpointHttp))
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @layer
|
|
24
|
+
* @product Sprite
|
|
25
|
+
* @provides Fly.Checkpoint
|
|
26
|
+
*/
|
|
27
|
+
export const CheckpointHttp = Layer.effect(
|
|
28
|
+
Checkpoint,
|
|
29
|
+
Effect.suspend(() =>
|
|
30
|
+
makeHttpSpriteBinding({
|
|
31
|
+
makeClient: (auth, spriteName): CheckpointClient => ({
|
|
32
|
+
create: Effect.fn("Fly.Checkpoint.create")(function* (options) {
|
|
33
|
+
return yield* auth.authorize(
|
|
34
|
+
sprites.createCheckpoint({
|
|
35
|
+
name: yield* spriteName,
|
|
36
|
+
comment: options?.comment,
|
|
37
|
+
}),
|
|
38
|
+
);
|
|
39
|
+
}),
|
|
40
|
+
list: Effect.fn("Fly.Checkpoint.list")(function* () {
|
|
41
|
+
return yield* auth.authorize(
|
|
42
|
+
sprites.listCheckpoints({
|
|
43
|
+
name: yield* spriteName,
|
|
44
|
+
}),
|
|
45
|
+
);
|
|
46
|
+
}),
|
|
47
|
+
get: Effect.fn("Fly.Checkpoint.get")(function* (checkpointId) {
|
|
48
|
+
return yield* auth.authorize(
|
|
49
|
+
sprites.getCheckpoint({
|
|
50
|
+
name: yield* spriteName,
|
|
51
|
+
checkpoint_id: checkpointId,
|
|
52
|
+
}),
|
|
53
|
+
);
|
|
54
|
+
}),
|
|
55
|
+
restore: Effect.fn("Fly.Checkpoint.restore")(function* (checkpointId) {
|
|
56
|
+
return yield* auth.authorize(
|
|
57
|
+
sprites.restoreCheckpoint({
|
|
58
|
+
name: yield* spriteName,
|
|
59
|
+
checkpoint_id: checkpointId,
|
|
60
|
+
}),
|
|
61
|
+
);
|
|
62
|
+
}),
|
|
63
|
+
}),
|
|
64
|
+
}),
|
|
65
|
+
),
|
|
66
|
+
).pipe(Layer.provide(FetchHttpClient.layer), Layer.provide(CredentialsFromAmbientOrEnv));
|