@alchemy.run/fly 0.0.0 → 2.0.0-beta.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +338 -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 +55 -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 +20 -0
- package/lib/PostgresMigrations.d.ts.map +1 -0
- package/lib/PostgresMigrations.js +58 -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 +611 -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 +11 -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 +1017 -0
- package/lib/Service.d.ts.map +1 -0
- package/lib/Service.js +1430 -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 +471 -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 +89 -0
- package/lib/Website/Astro.d.ts.map +1 -0
- package/lib/Website/Astro.js +54 -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 +212 -0
- package/lib/Website/FrameworkSite.d.ts.map +1 -0
- package/lib/Website/FrameworkSite.js +205 -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 +162 -0
- package/lib/Website/StaticSite.d.ts.map +1 -0
- package/lib/Website/StaticSite.js +180 -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 +112 -0
- package/lib/Website/Vite.d.ts.map +1 -0
- package/lib/Website/Vite.js +100 -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 +460 -0
- package/lib/bluegreen.js.map +1 -0
- package/lib/hosted.d.ts +171 -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 +158 -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 +514 -0
- package/src/AuthProvider.ts +68 -0
- package/src/BindService.ts +303 -0
- package/src/Bootstrap.ts +66 -0
- package/src/Bucket.ts +918 -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 +75 -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 +1270 -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 +93 -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 +823 -0
- package/src/RedisBinding.ts +64 -0
- package/src/RedisHttp.ts +14 -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 +1968 -0
- package/src/Sign.ts +46 -0
- package/src/SignHttp.ts +44 -0
- package/src/Sprite.ts +673 -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 +292 -0
- package/src/Website/Astro.ts +92 -0
- package/src/Website/Foldkit.ts +54 -0
- package/src/Website/FrameworkSite.ts +449 -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 +295 -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 +121 -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 +711 -0
- package/src/globals.d.ts +2 -0
- package/src/hosted.ts +667 -0
- package/src/index.ts +64 -0
- package/src/internal/RemoteBuilder.ts +242 -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
package/src/Sprite.ts
ADDED
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
import type { SpriteResponse as FlySprite } from "@distilled.cloud/fly-io/sprites";
|
|
2
|
+
import * as sprites from "@distilled.cloud/fly-io/sprites";
|
|
3
|
+
import { Unowned } from "alchemy/AdoptPolicy";
|
|
4
|
+
import * as Bundle from "alchemy/Bundle/Bundle";
|
|
5
|
+
import { isResolved } from "alchemy/Diff";
|
|
6
|
+
import { Platform, type Main, type PlatformProps } from "alchemy/Platform";
|
|
7
|
+
import * as Provider from "alchemy/Provider";
|
|
8
|
+
import type { Resource, ResourceBinding } from "alchemy/Resource";
|
|
9
|
+
import type { ServerHost } from "alchemy/Runtime/Process";
|
|
10
|
+
import { Stack } from "alchemy/Stack";
|
|
11
|
+
import { createInternalTags } from "alchemy/Tags";
|
|
12
|
+
import * as Data from "effect/Data";
|
|
13
|
+
import * as Duration from "effect/Duration";
|
|
14
|
+
import * as Effect from "effect/Effect";
|
|
15
|
+
import * as Redacted from "effect/Redacted";
|
|
16
|
+
import * as Schedule from "effect/Schedule";
|
|
17
|
+
import * as Stream from "effect/Stream";
|
|
18
|
+
import {
|
|
19
|
+
createFlyHostRuntimeContext,
|
|
20
|
+
createSpriteHostedSupport,
|
|
21
|
+
DEFAULT_PORT,
|
|
22
|
+
type FlyHostRuntimeContext,
|
|
23
|
+
type HostedProgramProps,
|
|
24
|
+
} from "./hosted.ts";
|
|
25
|
+
import {
|
|
26
|
+
createFlyResourceName,
|
|
27
|
+
matchesAlchemyPhysicalName,
|
|
28
|
+
sanitizeFlyAppName,
|
|
29
|
+
} from "./Metadata.ts";
|
|
30
|
+
import type { Providers } from "./Providers.ts";
|
|
31
|
+
|
|
32
|
+
const DEFAULT_URL_AUTH: UrlAuth = "public";
|
|
33
|
+
const APP_DIR = "/home/sprite/alchemy";
|
|
34
|
+
const BUN_BIN = "/home/sprite/.bun/bin/bun";
|
|
35
|
+
const SERVICE_NAME = "alchemy";
|
|
36
|
+
const OWNER_LABEL = "alchemy.type=Fly.Sprite";
|
|
37
|
+
|
|
38
|
+
const backoff = Schedule.min([
|
|
39
|
+
Schedule.exponential(Duration.millis(500), 1.5),
|
|
40
|
+
Schedule.spaced(Duration.seconds(5)),
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
export type UrlAuth = "public" | "sprite";
|
|
44
|
+
|
|
45
|
+
export type SpriteStatus = "cold" | "warm" | "running";
|
|
46
|
+
|
|
47
|
+
export interface SpriteProps extends PlatformProps {
|
|
48
|
+
/**
|
|
49
|
+
* Module entrypoint bundled with rolldown and written onto the Sprite.
|
|
50
|
+
* Typically `import.meta.url`. A content-hash change updates in place.
|
|
51
|
+
*/
|
|
52
|
+
main: string;
|
|
53
|
+
/**
|
|
54
|
+
* Sprite name. Unique per organization. If omitted, a unique name is
|
|
55
|
+
* generated from the stack, stage and logical ID. Changing it replaces
|
|
56
|
+
* the Sprite.
|
|
57
|
+
*/
|
|
58
|
+
name?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Who can hit {@link Sprite} `url`. `public` is open. `sprite` requires
|
|
61
|
+
* Sprites auth.
|
|
62
|
+
*
|
|
63
|
+
* @default "public"
|
|
64
|
+
*/
|
|
65
|
+
urlAuth?: UrlAuth;
|
|
66
|
+
/**
|
|
67
|
+
* Port the hosted HTTP server listens on. Written to `PORT` and used
|
|
68
|
+
* as the Sprite service `http_port`.
|
|
69
|
+
*
|
|
70
|
+
* @default 3000
|
|
71
|
+
*/
|
|
72
|
+
port?: number;
|
|
73
|
+
/**
|
|
74
|
+
* Named export to load from `main`.
|
|
75
|
+
*
|
|
76
|
+
* @default "default"
|
|
77
|
+
*/
|
|
78
|
+
handler?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Additional environment variables for the hosted process. Merged
|
|
81
|
+
* after binding-injected `env`.
|
|
82
|
+
*/
|
|
83
|
+
env?: Record<string, any>;
|
|
84
|
+
/**
|
|
85
|
+
* Bundler configuration for `main`: rolldown `input`/`output`
|
|
86
|
+
* overrides plus pure-annotation options (`pure`).
|
|
87
|
+
*/
|
|
88
|
+
build?: Bundle.BundleConfig;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Binding contract accepted by {@link Sprite} for injected env.
|
|
93
|
+
*/
|
|
94
|
+
export interface SpriteBinding {
|
|
95
|
+
env?: Record<string, any>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export type Sprite = Resource<
|
|
99
|
+
"Fly.Sprite",
|
|
100
|
+
SpriteProps,
|
|
101
|
+
{
|
|
102
|
+
/** Fly Sprite id. */
|
|
103
|
+
spriteId: string;
|
|
104
|
+
/** Physical Sprite name (unique per org). */
|
|
105
|
+
name: string;
|
|
106
|
+
/**
|
|
107
|
+
* Public Sprite URL (`https://{name}-….sprites.app`).
|
|
108
|
+
*/
|
|
109
|
+
url: string;
|
|
110
|
+
/** Observed runtime status. Hibernates to `cold` when idle. */
|
|
111
|
+
status: SpriteStatus;
|
|
112
|
+
/** Observed URL auth setting. */
|
|
113
|
+
urlAuth: UrlAuth;
|
|
114
|
+
/** Organization slug, if the API returned one. */
|
|
115
|
+
orgSlug: string | undefined;
|
|
116
|
+
/** Content hash of the bundled program. */
|
|
117
|
+
code: {
|
|
118
|
+
hash: string;
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
SpriteBinding,
|
|
122
|
+
Providers
|
|
123
|
+
>;
|
|
124
|
+
|
|
125
|
+
export const isSprite = (value: unknown): value is Sprite =>
|
|
126
|
+
typeof value === "object" && value !== null && (value as { Type?: string }).Type === "Fly.Sprite";
|
|
127
|
+
|
|
128
|
+
export type SpriteServices = ServerHost;
|
|
129
|
+
|
|
130
|
+
export type SpriteShape = Main<SpriteServices>;
|
|
131
|
+
|
|
132
|
+
export type SpriteRuntimeContext = FlyHostRuntimeContext;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* A Sprite is an Effect program running in a Fly.io Sprite. Sprites
|
|
136
|
+
* are org-scoped Linux sandboxes. They hibernate when idle and wake
|
|
137
|
+
* on demand. There is no parent {@link App}. Unlike a {@link Service},
|
|
138
|
+
* Alchemy does not build a Docker image.
|
|
139
|
+
*
|
|
140
|
+
* @see https://sprites.dev/api/sprites
|
|
141
|
+
*
|
|
142
|
+
* ### Declare a Sprite
|
|
143
|
+
* A Sprite is a class. Props describe the sandbox. The Effect is the
|
|
144
|
+
* program that runs on it. There is no parent App.
|
|
145
|
+
*
|
|
146
|
+
* `main: import.meta.url` is the bundle entrypoint. Alchemy bundles
|
|
147
|
+
* this file with Rolldown, writes it onto the Sprite, and runs it as
|
|
148
|
+
* a Sprite service on {@link port}. Auth is `FLY_API_TOKEN`.
|
|
149
|
+
*
|
|
150
|
+
* **Example:** Class + main
|
|
151
|
+
* ```typescript
|
|
152
|
+
* export default class Box extends Fly.Sprite<Box>()(
|
|
153
|
+
* "Box",
|
|
154
|
+
* { main: import.meta.url },
|
|
155
|
+
* Effect.gen(function* () {
|
|
156
|
+
* return {};
|
|
157
|
+
* }),
|
|
158
|
+
* ) {}
|
|
159
|
+
* ```
|
|
160
|
+
*
|
|
161
|
+
* ### Serve HTTP with fetch
|
|
162
|
+
* Return `fetch` from the init Effect to boot an HTTP server. The
|
|
163
|
+
* Sprite URL proxies to {@link port}.
|
|
164
|
+
*
|
|
165
|
+
* **Example:** Hello
|
|
166
|
+
* ```typescript
|
|
167
|
+
* export default class Box extends Fly.Sprite<Box>()(
|
|
168
|
+
* "Box",
|
|
169
|
+
* { main: import.meta.url },
|
|
170
|
+
* Effect.gen(function* () {
|
|
171
|
+
* return {
|
|
172
|
+
* fetch: Effect.succeed(HttpServerResponse.text("hello")),
|
|
173
|
+
* };
|
|
174
|
+
* }),
|
|
175
|
+
* ) {}
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* ### The public URL
|
|
179
|
+
* Yield the Sprite in the Stack. `box.url` is
|
|
180
|
+
* `https://{name}-….sprites.app`.
|
|
181
|
+
*
|
|
182
|
+
* **Example:** Stack output
|
|
183
|
+
* ```typescript
|
|
184
|
+
* export default Alchemy.Stack(
|
|
185
|
+
* "MyApp",
|
|
186
|
+
* { providers: Fly.providers(), state: Alchemy.localState() },
|
|
187
|
+
* Effect.gen(function* () {
|
|
188
|
+
* const box = yield* Box;
|
|
189
|
+
* return { url: box.url };
|
|
190
|
+
* }),
|
|
191
|
+
* );
|
|
192
|
+
* ```
|
|
193
|
+
*
|
|
194
|
+
* ### URL auth
|
|
195
|
+
* `urlAuth` is `public` or `sprite`. Default is `public` so `url`
|
|
196
|
+
* answers without a Sprites token.
|
|
197
|
+
*
|
|
198
|
+
* **Example:** Sprite-auth URL
|
|
199
|
+
* ```typescript
|
|
200
|
+
* export default class Box extends Fly.Sprite<Box>()(
|
|
201
|
+
* "Box",
|
|
202
|
+
* { main: import.meta.url, urlAuth: "sprite" },
|
|
203
|
+
* Effect.gen(function* () {
|
|
204
|
+
* return {
|
|
205
|
+
* fetch: Effect.succeed(HttpServerResponse.text("hello")),
|
|
206
|
+
* };
|
|
207
|
+
* }),
|
|
208
|
+
* ) {}
|
|
209
|
+
* ```
|
|
210
|
+
*
|
|
211
|
+
* :::note[Default is public]
|
|
212
|
+
* Fly's API default is `sprite`. Alchemy defaults to `public` so a
|
|
213
|
+
* `fetch` handler is reachable.
|
|
214
|
+
* :::
|
|
215
|
+
*
|
|
216
|
+
* ### Config
|
|
217
|
+
* Yield `Config` in init. Alchemy reads the value from the env of
|
|
218
|
+
* whoever deploys and writes it onto the Sprite. Do not pass
|
|
219
|
+
* `env: { ... }` on a Sprite.
|
|
220
|
+
*
|
|
221
|
+
* Yield `FileSystem.FileSystem` in init, never inside `fetch`.
|
|
222
|
+
*
|
|
223
|
+
* **Example:** Config.Redacted
|
|
224
|
+
* ```typescript
|
|
225
|
+
* import * as Config from "effect/Config";
|
|
226
|
+
* import * as FileSystem from "effect/FileSystem";
|
|
227
|
+
* import * as Redacted from "effect/Redacted";
|
|
228
|
+
*
|
|
229
|
+
* export default class Box extends Fly.Sprite<Box>()(
|
|
230
|
+
* "Box",
|
|
231
|
+
* { main: import.meta.url },
|
|
232
|
+
* Effect.gen(function* () {
|
|
233
|
+
* const apiKey = yield* Config.Redacted("API_KEY");
|
|
234
|
+
* const fs = yield* FileSystem.FileSystem;
|
|
235
|
+
* yield* fs.makeDirectory("/tmp", { recursive: true });
|
|
236
|
+
*
|
|
237
|
+
* return {
|
|
238
|
+
* fetch: Effect.gen(function* () {
|
|
239
|
+
* const token = Redacted.value(apiKey);
|
|
240
|
+
* return HttpServerResponse.text("ok");
|
|
241
|
+
* }),
|
|
242
|
+
* };
|
|
243
|
+
* }),
|
|
244
|
+
* ) {}
|
|
245
|
+
* ```
|
|
246
|
+
*
|
|
247
|
+
* ### Exec
|
|
248
|
+
* {@link Exec} runs a command on the Sprite. Provide {@link ExecHttp}.
|
|
249
|
+
*
|
|
250
|
+
* **Example:** ls
|
|
251
|
+
* ```typescript
|
|
252
|
+
* const exec = yield* Fly.Exec(Box);
|
|
253
|
+
* const result = yield* exec({ cmd: ["ls", "-la"] });
|
|
254
|
+
* ```
|
|
255
|
+
*
|
|
256
|
+
* ### Checkpoint
|
|
257
|
+
* {@link Checkpoint} snapshots and restores the Sprite disk. Provide
|
|
258
|
+
* {@link CheckpointHttp}.
|
|
259
|
+
*
|
|
260
|
+
* **Example:** Create and restore
|
|
261
|
+
* ```typescript
|
|
262
|
+
* const checkpoint = yield* Fly.Checkpoint(Box);
|
|
263
|
+
* yield* checkpoint.create({ comment: "before" });
|
|
264
|
+
* yield* checkpoint.restore("v1");
|
|
265
|
+
* ```
|
|
266
|
+
*
|
|
267
|
+
* :::caution[Restore is destructive]
|
|
268
|
+
* The disk rewinds. Later writes are gone.
|
|
269
|
+
* :::
|
|
270
|
+
*
|
|
271
|
+
* ### A stable name
|
|
272
|
+
* Omit `name` and Alchemy generates one from the stack, stage, and
|
|
273
|
+
* logical ID.
|
|
274
|
+
*
|
|
275
|
+
* **Example:** Explicit name
|
|
276
|
+
* ```typescript
|
|
277
|
+
* export default class Box extends Fly.Sprite<Box>()(
|
|
278
|
+
* "Box",
|
|
279
|
+
* { main: import.meta.url, name: "box" },
|
|
280
|
+
* Effect.gen(function* () {
|
|
281
|
+
* return {
|
|
282
|
+
* fetch: Effect.succeed(HttpServerResponse.text("hello")),
|
|
283
|
+
* };
|
|
284
|
+
* }),
|
|
285
|
+
* ) {}
|
|
286
|
+
* ```
|
|
287
|
+
*
|
|
288
|
+
* :::caution[Changing `name` replaces the Sprite]
|
|
289
|
+
* Fly cannot rename a Sprite. Alchemy creates the new name, then
|
|
290
|
+
* deletes the old one.
|
|
291
|
+
* :::
|
|
292
|
+
*
|
|
293
|
+
* ### Named export
|
|
294
|
+
* `handler` is the named export to load from `main`. Default is
|
|
295
|
+
* `"default"`.
|
|
296
|
+
*
|
|
297
|
+
* **Example:** Custom handler
|
|
298
|
+
* ```typescript
|
|
299
|
+
* export default class Box extends Fly.Sprite<Box>()(
|
|
300
|
+
* "Box",
|
|
301
|
+
* { main: import.meta.url, handler: "box" },
|
|
302
|
+
* Effect.gen(function* () {
|
|
303
|
+
* return {
|
|
304
|
+
* fetch: Effect.succeed(HttpServerResponse.text("hello")),
|
|
305
|
+
* };
|
|
306
|
+
* }),
|
|
307
|
+
* ) {}
|
|
308
|
+
* ```
|
|
309
|
+
*
|
|
310
|
+
* @resource
|
|
311
|
+
* @product Sprite
|
|
312
|
+
*/
|
|
313
|
+
export const Sprite: Platform<Sprite, SpriteServices, SpriteShape, SpriteRuntimeContext> = Platform(
|
|
314
|
+
"Fly.Sprite",
|
|
315
|
+
{
|
|
316
|
+
createRuntimeContext: createFlyHostRuntimeContext("Fly.Sprite"),
|
|
317
|
+
},
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
export class SpriteNotCreated extends Data.TaggedError("Fly.SpriteNotCreated")<{
|
|
321
|
+
resourceName: string;
|
|
322
|
+
}> {}
|
|
323
|
+
|
|
324
|
+
export class SpriteExecFailed extends Data.TaggedError("Fly.SpriteExecFailed")<{
|
|
325
|
+
resourceName: string;
|
|
326
|
+
cmd: string;
|
|
327
|
+
exitCode: number | undefined;
|
|
328
|
+
stderr: string | undefined;
|
|
329
|
+
}> {}
|
|
330
|
+
|
|
331
|
+
class SpritePending extends Data.TaggedError("Fly.SpritePending")<{
|
|
332
|
+
resourceName: string;
|
|
333
|
+
}> {}
|
|
334
|
+
|
|
335
|
+
const toStatus = (status: string | undefined): SpriteStatus =>
|
|
336
|
+
status === "warm" || status === "running" || status === "cold" ? status : "cold";
|
|
337
|
+
|
|
338
|
+
const toUrlAuth = (auth: string | undefined): UrlAuth => (auth === "sprite" ? "sprite" : "public");
|
|
339
|
+
|
|
340
|
+
const toAttrs = (sprite: FlySprite, name: string, codeHash: string): Sprite["Attributes"] => ({
|
|
341
|
+
spriteId: sprite.id ?? name,
|
|
342
|
+
name: sprite.name ?? name,
|
|
343
|
+
url: sprite.url ?? `https://${name}.sprites.app`,
|
|
344
|
+
status: toStatus(sprite.status),
|
|
345
|
+
urlAuth: toUrlAuth(sprite.url_settings?.auth),
|
|
346
|
+
orgSlug: sprite.organization,
|
|
347
|
+
code: { hash: codeHash },
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
const isOwnedSprite = (sprite: FlySprite): boolean => {
|
|
351
|
+
const labels = sprite.labels ?? [];
|
|
352
|
+
if (labels.includes(OWNER_LABEL)) return true;
|
|
353
|
+
if (labels.some((label) => label.startsWith("alchemy.type="))) return true;
|
|
354
|
+
return matchesAlchemyPhysicalName(sprite.name);
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
const resolveSpriteName = (id: string, name: string | undefined, existing?: string) =>
|
|
358
|
+
Effect.gen(function* () {
|
|
359
|
+
if (name !== undefined) return sanitizeFlyAppName(name);
|
|
360
|
+
if (existing !== undefined) return existing;
|
|
361
|
+
return yield* createFlyResourceName(id);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
const ownershipLabels = (id: string) =>
|
|
365
|
+
Effect.gen(function* () {
|
|
366
|
+
const tags = yield* createInternalTags(id);
|
|
367
|
+
return [...Object.entries(tags).map(([key, value]) => `${key}=${value}`), OWNER_LABEL];
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
const getByName = (name: string) =>
|
|
371
|
+
sprites.getSprite({ name }).pipe(Effect.catchTag("NotFound", () => Effect.undefined));
|
|
372
|
+
|
|
373
|
+
const waitForSprite = (name: string) =>
|
|
374
|
+
getByName(name).pipe(
|
|
375
|
+
Effect.flatMap((found) =>
|
|
376
|
+
found !== undefined
|
|
377
|
+
? Effect.succeed(found)
|
|
378
|
+
: Effect.fail(new SpritePending({ resourceName: name })),
|
|
379
|
+
),
|
|
380
|
+
Effect.retry({
|
|
381
|
+
while: (e) => e._tag === "Fly.SpritePending",
|
|
382
|
+
times: 8,
|
|
383
|
+
schedule: backoff,
|
|
384
|
+
}),
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
const isTransient = (e: { readonly _tag: string }) =>
|
|
388
|
+
e._tag === "NotFound" ||
|
|
389
|
+
e._tag === "TooManyRequests" ||
|
|
390
|
+
e._tag === "ServiceUnavailable" ||
|
|
391
|
+
e._tag === "BadGateway" ||
|
|
392
|
+
e._tag === "GatewayTimeout";
|
|
393
|
+
|
|
394
|
+
const retryTransient = <A, E extends { readonly _tag: string }, R>(
|
|
395
|
+
effect: Effect.Effect<A, E, R>,
|
|
396
|
+
) =>
|
|
397
|
+
effect.pipe(
|
|
398
|
+
Effect.retry({
|
|
399
|
+
while: isTransient,
|
|
400
|
+
times: 8,
|
|
401
|
+
schedule: backoff,
|
|
402
|
+
}),
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
const toEnv = (env: Record<string, any> | undefined): Record<string, string> =>
|
|
406
|
+
Object.fromEntries(
|
|
407
|
+
Object.entries(env ?? {}).flatMap(([key, value]) => {
|
|
408
|
+
if (value === undefined || value === null) return [];
|
|
409
|
+
const raw = Redacted.isRedacted(value) ? Redacted.value(value) : value;
|
|
410
|
+
return [[key, String(raw)]];
|
|
411
|
+
}),
|
|
412
|
+
);
|
|
413
|
+
|
|
414
|
+
const collectBindingEnv = (bindings: readonly ResourceBinding<SpriteBinding>[]) => {
|
|
415
|
+
const active = bindings.filter(
|
|
416
|
+
(binding: ResourceBinding<SpriteBinding> & { action?: string }) => binding.action !== "delete",
|
|
417
|
+
);
|
|
418
|
+
return active
|
|
419
|
+
.map((binding) => binding?.data?.env)
|
|
420
|
+
.reduce<Record<string, any>>((acc, value) => ({ ...acc, ...value }), {});
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const desiredEnv = (
|
|
424
|
+
props: SpriteProps,
|
|
425
|
+
bindingEnv: Record<string, any>,
|
|
426
|
+
alchemyEnv: Record<string, string>,
|
|
427
|
+
port: number,
|
|
428
|
+
): Record<string, string> => ({
|
|
429
|
+
...toEnv(bindingEnv),
|
|
430
|
+
...alchemyEnv,
|
|
431
|
+
PORT: String(port),
|
|
432
|
+
...toEnv(props.env),
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
const renderEnvFile = (env: Record<string, string>) =>
|
|
436
|
+
`${Object.entries(env)
|
|
437
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
438
|
+
.map(([key, value]) => `${key}=${JSON.stringify(value)}`)
|
|
439
|
+
.join("\n")}\n`;
|
|
440
|
+
|
|
441
|
+
const writeRemoteFile = (input: { name: string; path: string; body: Uint8Array }) =>
|
|
442
|
+
retryTransient(
|
|
443
|
+
sprites.writeFile({
|
|
444
|
+
name: input.name,
|
|
445
|
+
path: input.path,
|
|
446
|
+
workingDir: "/",
|
|
447
|
+
mkdir: true,
|
|
448
|
+
body: input.body,
|
|
449
|
+
}),
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
const runExec = (input: { name: string; cmd: string[]; env?: string[] }) =>
|
|
453
|
+
Effect.gen(function* () {
|
|
454
|
+
const result = yield* retryTransient(
|
|
455
|
+
sprites.execCommand({
|
|
456
|
+
name: input.name,
|
|
457
|
+
cmd: input.cmd,
|
|
458
|
+
env: input.env,
|
|
459
|
+
}),
|
|
460
|
+
);
|
|
461
|
+
if ((result.exit_code ?? 0) !== 0) {
|
|
462
|
+
return yield* new SpriteExecFailed({
|
|
463
|
+
resourceName: input.name,
|
|
464
|
+
cmd: input.cmd.join(" "),
|
|
465
|
+
exitCode: result.exit_code,
|
|
466
|
+
stderr: result.stderr,
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
return result;
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
const ensureBun = (name: string) =>
|
|
473
|
+
runExec({
|
|
474
|
+
name,
|
|
475
|
+
cmd: [
|
|
476
|
+
"bash",
|
|
477
|
+
"-lc",
|
|
478
|
+
[
|
|
479
|
+
"set -euo pipefail",
|
|
480
|
+
"export HOME=/home/sprite",
|
|
481
|
+
"export BUN_INSTALL=/home/sprite/.bun",
|
|
482
|
+
'export PATH="$BUN_INSTALL/bin:$PATH"',
|
|
483
|
+
'if [ ! -x "$BUN_INSTALL/bin/bun" ]; then',
|
|
484
|
+
" curl -fsSL https://bun.sh/install | bash",
|
|
485
|
+
"fi",
|
|
486
|
+
`test -x ${BUN_BIN}`,
|
|
487
|
+
].join("\n"),
|
|
488
|
+
],
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
const putAlchemyService = (input: { name: string; port: number }) =>
|
|
492
|
+
retryTransient(
|
|
493
|
+
sprites.putService({
|
|
494
|
+
name: input.name,
|
|
495
|
+
service_name: SERVICE_NAME,
|
|
496
|
+
cmd: "bash",
|
|
497
|
+
args: [
|
|
498
|
+
"-lc",
|
|
499
|
+
`set -a; [ -f ${APP_DIR}/env ] && . ${APP_DIR}/env; set +a; exec ${BUN_BIN} --no-install ${APP_DIR}/index.mjs`,
|
|
500
|
+
],
|
|
501
|
+
dir: APP_DIR,
|
|
502
|
+
http_port: input.port,
|
|
503
|
+
}),
|
|
504
|
+
).pipe(Effect.catchTag("NotFound", () => Effect.void));
|
|
505
|
+
|
|
506
|
+
const deployProgram = Effect.fn(function* (input: {
|
|
507
|
+
name: string;
|
|
508
|
+
files: ReadonlyArray<{ path: string; content: Uint8Array }>;
|
|
509
|
+
env: Record<string, string>;
|
|
510
|
+
port: number;
|
|
511
|
+
session?: { note: (message: string) => Effect.Effect<void> };
|
|
512
|
+
}) {
|
|
513
|
+
const note = input.session?.note ?? ((_message: string) => Effect.void);
|
|
514
|
+
yield* note(`Writing ${input.name} program onto the Sprite...`);
|
|
515
|
+
for (const file of input.files) {
|
|
516
|
+
const rel = file.path.replace(/^\/+/, "");
|
|
517
|
+
yield* writeRemoteFile({
|
|
518
|
+
name: input.name,
|
|
519
|
+
path: `${APP_DIR}/${rel}`,
|
|
520
|
+
body: file.content,
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
yield* writeRemoteFile({
|
|
524
|
+
name: input.name,
|
|
525
|
+
path: `${APP_DIR}/env`,
|
|
526
|
+
body: new TextEncoder().encode(renderEnvFile(input.env)),
|
|
527
|
+
});
|
|
528
|
+
yield* note(`Installing bun on ${input.name}...`);
|
|
529
|
+
yield* ensureBun(input.name);
|
|
530
|
+
yield* note(`Starting ${input.name} service...`);
|
|
531
|
+
yield* putAlchemyService({ name: input.name, port: input.port });
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
export const SpriteProvider = () =>
|
|
535
|
+
Provider.effect(
|
|
536
|
+
Sprite,
|
|
537
|
+
Effect.gen(function* () {
|
|
538
|
+
const stack = yield* Stack;
|
|
539
|
+
const virtualEntryPlugin = yield* Bundle.virtualEntryPlugin;
|
|
540
|
+
const hosted = createSpriteHostedSupport({
|
|
541
|
+
stackName: stack.name,
|
|
542
|
+
stage: stack.stage,
|
|
543
|
+
virtualEntryPlugin,
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
return Sprite.Provider.of({
|
|
547
|
+
stables: ["spriteId", "name"],
|
|
548
|
+
|
|
549
|
+
diff: Effect.fn(function* ({ news, output }) {
|
|
550
|
+
if (news === undefined || output === undefined) return undefined;
|
|
551
|
+
if (isResolved(news)) {
|
|
552
|
+
const desiredName =
|
|
553
|
+
news.name !== undefined ? sanitizeFlyAppName(news.name) : output.name;
|
|
554
|
+
if (desiredName !== output.name) {
|
|
555
|
+
return { action: "replace" as const };
|
|
556
|
+
}
|
|
557
|
+
const desiredAuth = news.urlAuth ?? DEFAULT_URL_AUTH;
|
|
558
|
+
if (desiredAuth !== output.urlAuth) {
|
|
559
|
+
return { action: "update" as const };
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
// The code hash depends only on statically-known props — never
|
|
563
|
+
// gate it on the WHOLE props being resolved: an unresolved
|
|
564
|
+
// reference elsewhere in props would make code-only changes
|
|
565
|
+
// silently noop (see the same pattern in Service.ts). By diff
|
|
566
|
+
// time the effect-config form has been evaluated, so the object
|
|
567
|
+
// view is safe to read.
|
|
568
|
+
const statics = news as Partial<Pick<SpriteProps, "main" | "port">>;
|
|
569
|
+
if (isResolved({ main: statics.main, port: statics.port })) {
|
|
570
|
+
const hash = yield* hosted.hash(news as HostedProgramProps);
|
|
571
|
+
if (hash !== output.code.hash) {
|
|
572
|
+
return { action: "update" as const };
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
return undefined;
|
|
576
|
+
}),
|
|
577
|
+
|
|
578
|
+
read: Effect.fn(function* ({ id, olds, output }) {
|
|
579
|
+
const name = yield* resolveSpriteName(id, olds?.name, output?.name);
|
|
580
|
+
const found = yield* (
|
|
581
|
+
output?.name !== undefined ? getByName(output.name) : Effect.undefined
|
|
582
|
+
).pipe(
|
|
583
|
+
Effect.flatMap((existing) =>
|
|
584
|
+
existing !== undefined ? Effect.succeed(existing) : getByName(name),
|
|
585
|
+
),
|
|
586
|
+
Effect.catchTag("SpritesNotEnabled", () => Effect.undefined),
|
|
587
|
+
);
|
|
588
|
+
if (found === undefined) return undefined;
|
|
589
|
+
const attrs = toAttrs(found, name, output?.code.hash ?? "");
|
|
590
|
+
if (output !== undefined) return attrs;
|
|
591
|
+
return isOwnedSprite(found) ? attrs : Unowned(attrs);
|
|
592
|
+
}),
|
|
593
|
+
|
|
594
|
+
list: Effect.fn(function* () {
|
|
595
|
+
const items = yield* sprites.listSprites.items({ max_results: 50 }).pipe(
|
|
596
|
+
Stream.runCollect,
|
|
597
|
+
Effect.map((chunk) => Array.from(chunk)),
|
|
598
|
+
Effect.catchTag("SpritesNotEnabled", () => Effect.succeed([])),
|
|
599
|
+
);
|
|
600
|
+
return items
|
|
601
|
+
.filter(isOwnedSprite)
|
|
602
|
+
.map((sprite) => toAttrs(sprite, sprite.name ?? "", ""));
|
|
603
|
+
}),
|
|
604
|
+
|
|
605
|
+
reconcile: Effect.fn(function* ({ id, news, output, bindings, session }) {
|
|
606
|
+
const props = news;
|
|
607
|
+
const name = yield* resolveSpriteName(id, props.name, output?.name);
|
|
608
|
+
const urlAuth = props.urlAuth ?? DEFAULT_URL_AUTH;
|
|
609
|
+
const port = props.port ?? DEFAULT_PORT;
|
|
610
|
+
const labels = yield* ownershipLabels(id);
|
|
611
|
+
const boundEnv = collectBindingEnv(bindings ?? []);
|
|
612
|
+
const env = desiredEnv(props, boundEnv, hosted.alchemyEnv, port);
|
|
613
|
+
|
|
614
|
+
let current = output?.name !== undefined ? yield* getByName(output.name) : undefined;
|
|
615
|
+
if (current === undefined && output?.name !== name) {
|
|
616
|
+
current = yield* getByName(name);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
if (current === undefined) {
|
|
620
|
+
yield* sprites
|
|
621
|
+
.createSprite({
|
|
622
|
+
name,
|
|
623
|
+
url_settings: { auth: urlAuth },
|
|
624
|
+
labels,
|
|
625
|
+
})
|
|
626
|
+
.pipe(Effect.catchTag("Conflict", () => Effect.void));
|
|
627
|
+
current = yield* waitForSprite(name).pipe(
|
|
628
|
+
Effect.catchTag("Fly.SpritePending", () => getByName(name)),
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (current === undefined) {
|
|
633
|
+
return yield* new SpriteNotCreated({ resourceName: name });
|
|
634
|
+
}
|
|
635
|
+
// Narrowed once so the `NotFound` fallbacks below keep the
|
|
636
|
+
// non-optional type instead of widening back to `| undefined`.
|
|
637
|
+
let sprite = current;
|
|
638
|
+
|
|
639
|
+
const observedAuth = toUrlAuth(sprite.url_settings?.auth);
|
|
640
|
+
if (observedAuth !== urlAuth) {
|
|
641
|
+
sprite = yield* sprites
|
|
642
|
+
.updateSprite({
|
|
643
|
+
name,
|
|
644
|
+
url_settings: { auth: urlAuth },
|
|
645
|
+
})
|
|
646
|
+
.pipe(Effect.catchTag("NotFound", () => Effect.succeed(sprite)));
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
const codeHash = yield* hosted.hash(props);
|
|
650
|
+
if (codeHash !== output?.code.hash) {
|
|
651
|
+
const bundled = yield* hosted.bundleProgram(props);
|
|
652
|
+
yield* deployProgram({
|
|
653
|
+
name,
|
|
654
|
+
files: bundled.files,
|
|
655
|
+
env,
|
|
656
|
+
port,
|
|
657
|
+
session,
|
|
658
|
+
});
|
|
659
|
+
sprite = (yield* getByName(name)) ?? sprite;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
return toAttrs(sprite, name, codeHash);
|
|
663
|
+
}),
|
|
664
|
+
|
|
665
|
+
delete: Effect.fn(function* ({ output }) {
|
|
666
|
+
if (output.name.length === 0) return;
|
|
667
|
+
yield* sprites
|
|
668
|
+
.deleteSprite({ name: output.name })
|
|
669
|
+
.pipe(Effect.catchTag(["NotFound", "SpritesNotEnabled"], () => Effect.void));
|
|
670
|
+
}),
|
|
671
|
+
});
|
|
672
|
+
}),
|
|
673
|
+
);
|