1import * as Layer from "effect/Layer";
2import * as FetchHttpClient from "effect/http/FetchHttpClient";
3import { CredentialsStoreLive } from "../Auth/Credentials.ts";
4import { ProfileStoreLive } from "../Auth/Profile.ts";
5import * as Command from "../Command/index.ts";
6import * as Provider from "../Provider.ts";
7import { Random, RandomProvider } from "../Random.ts";
8import { App, AppProvider } from "./App.ts";
9import { FlyAuth } from "./AuthProvider.ts";
10import { Bucket, BucketProvider } from "./Bucket.ts";
11import { DeleteObjectHttp } from "./DeleteObjectHttp.ts";
12import { GetObjectHttp } from "./GetObjectHttp.ts";
13import { HeadObjectHttp } from "./HeadObjectHttp.ts";
14import { ListObjectsV2Http } from "./ListObjectsV2Http.ts";
15import { PutObjectHttp } from "./PutObjectHttp.ts";
16import { ReadRedisHttp } from "./ReadRedisHttp.ts";
17import { ReadWriteRedisHttp } from "./ReadWriteRedisHttp.ts";
18import { WriteRedisHttp } from "./WriteRedisHttp.ts";
19import { Certificate, CertificateProvider } from "./Certificate.ts";
20import { CheckpointHttp } from "./CheckpointHttp.ts";
21import * as Credentials from "./Credentials.ts";
22import { fromCredentials } from "./Environment.ts";
23import { IpAssignment, IpAssignmentProvider } from "./IpAssignment.ts";
24import { Machine, MachineProvider } from "./Machine.ts";
25import { ConnectPostgresHttp } from "./ConnectPostgresHttp.ts";
26import { Postgres, PostgresProvider } from "./Postgres.ts";
27import { Redis, RedisProvider } from "./Redis.ts";
28import { DecryptHttp } from "./DecryptHttp.ts";
29import { EncryptHttp } from "./EncryptHttp.ts";
30import { ExecHttp } from "./ExecHttp.ts";
31import { GetSecretHttp } from "./GetSecretHttp.ts";
32import { ListSecretsHttp } from "./ListSecretsHttp.ts";
33import { MountVolumeLive } from "./MountVolume.ts";
34import { Secret, SecretProvider } from "./Secret.ts";
35import { SecretKey, SecretKeyProvider } from "./SecretKey.ts";
36import { Service, ServiceProvider } from "./Service.ts";
37import {
38 AssetDeployment,
39 AssetDeploymentProvider,
40} from "./Website/AssetDeployment.ts";
41import {
42 Server as WebsiteServer,
43 ServerProvider as WebsiteServerProvider,
44} from "../Website/Server.ts";
45import { SignHttp } from "./SignHttp.ts";
46import { Sprite, SpriteProvider } from "./Sprite.ts";
47import { VerifyHttp } from "./VerifyHttp.ts";
48import { VolumeSnapshot, VolumeSnapshotProvider } from "./VolumeSnapshot.ts";
49import { WriteCertificatesHttp } from "./WriteCertificatesHttp.ts";
50import { WriteSecretHttp } from "./WriteSecretHttp.ts";
51
52export class Providers extends Provider.ProviderCollection<Providers>()(
53 "Fly",
54) {}
55
56export type ProviderRequirements = Layer.Services<ReturnType<typeof providers>>;
57
58/**
59 * Build a layer that registers Fly resource providers, the Fly
60 * `AuthProvider`, the resolved `Credentials`, and an `HttpClient`. Include
61 * this from your stack alongside other cloud `providers()` layers.
62 *
63 * Resource providers are inserted into {@link Provider.collection} as they
64 * land. The collection starts empty so App / Machine / Service agents can
65 * make a single minimal insertion.
66 *
67 * @example
68 * ```typescript
69 * import * as Alchemy from "alchemy";
70 * import * as Fly from "alchemy/Fly";
71 * import * as Effect from "effect/Effect";
72 *
73 * export default Alchemy.Stack(
74 * "MyStack",
75 * {
76 * providers: Fly.providers(),
77 * state: Alchemy.localState(),
78 * },
79 * Effect.gen(function* () {
80 * return {};
81 * }),
82 * );
83 * ```
84 */
85export const providers = () =>
86 Layer.effect(
87 Providers,
88 Provider.collection([
89 App,
90 AssetDeployment,
91 Bucket,
92 Certificate,
93 IpAssignment,
94 Machine,
95 Postgres,
96 Random,
97 Redis,
98 Secret,
99 SecretKey,
100 Service,
101 Sprite,
102 VolumeSnapshot,
103 WebsiteServer,
104 ]),
105 ).pipe(
106 Layer.provide(
107 Layer.mergeAll(
108 AppProvider(),
109 AssetDeploymentProvider(),
110 BucketProvider(),
111 CertificateProvider(),
112 IpAssignmentProvider(),
113 MachineProvider(),
114 PostgresProvider(),
115 RandomProvider(),
116 RedisProvider(),
117 SecretProvider(),
118 SecretKeyProvider(),
119 ServiceProvider(),
120 SpriteProvider(),
121 VolumeSnapshotProvider(),
122 WebsiteServerProvider(),
123 ),
124 ),
125 // The binding layers are mutually independent — they all draw on the
126 // Credentials/HttpClient layers below. Merge them into one group so
127 // `.pipe` stays under its 20-argument overload ceiling.
128 Layer.provideMerge(
129 Layer.mergeAll(
130 MountVolumeLive,
131 ConnectPostgresHttp,
132 PutObjectHttp,
133 GetObjectHttp,
134 DeleteObjectHttp,
135 HeadObjectHttp,
136 ListObjectsV2Http,
137 ReadRedisHttp,
138 WriteRedisHttp,
139 ReadWriteRedisHttp,
140 CheckpointHttp,
141 ExecHttp,
142 GetSecretHttp,
143 ListSecretsHttp,
144 WriteSecretHttp,
145 WriteCertificatesHttp,
146 EncryptHttp,
147 DecryptHttp,
148 SignHttp,
149 VerifyHttp,
150 ),
151 ),
152 Layer.provideMerge(fromCredentials()),
153 Layer.provideMerge(Credentials.fromAuthProvider()),
154 Layer.provideMerge(FlyAuth),
155 Layer.provideMerge(ProfileStoreLive),
156 Layer.provideMerge(CredentialsStoreLive),
157 Layer.provideMerge(FetchHttpClient.layer),
158 Layer.provideMerge(Command.providers()),
159 Layer.orDie,
160 );