1import type { Config } from "@distilled.cloud/hetzner";
2import { Credentials } from "@distilled.cloud/hetzner";
3import * as Context from "effect/Context";
4import * as Effect from "effect/Effect";
5import * as Layer from "effect/Layer";
6
7/**
8 * Fully-resolved Hetzner Cloud environment for a stack.
9 *
10 * A Hetzner Cloud token is issued per project — the token IS the project
11 * scope, so this service only carries `{ token, apiBaseUrl }`. Resolve
12 * it inside lifecycle operations with `HetznerEnvironment.current`.
13 */
14export type HetznerEnvironmentShape = Config;
15
16export class HetznerEnvironment extends Context.Service<
17 HetznerEnvironment,
18 Effect.Effect<HetznerEnvironmentShape>
19>()("Hetzner::Environment") {
20 static current = HetznerEnvironment.use((env) => env);
21 readonly kind = "Environment" as const;
22}
23
24/**
25 * Build a `HetznerEnvironment` layer from the distilled `Credentials`
26 * service. Provide this after `Credentials.fromAuthProvider()`.
27 */
28export const fromCredentials = () =>
29 Layer.effect(
30 HetznerEnvironment,
31 Effect.gen(function* () {
32 return yield* Credentials;
33 }),
34 );