1import * as Effect from "effect/Effect";
2import type * as HttpClient from "effect/http/HttpClient";
3import type { Credentials } from "../Credentials.ts";
4import type { Zone } from "../Zone/Zone.ts";
5import type { DnsAuth } from "./DnsHttp.ts";
6
7/**
8 * Shared scaffolding for the `*Local` DNS services.
9 *
10 * Instead of minting a scoped {@link AccountApiToken} (the `*Http` path), it
11 * captures the ambient current-credentials context available during stack-eval
12 * and builds a {@link DnsAuth} that provides those credentials directly to the
13 * DNS HTTP ops. It then delegates to the same client builders the `*Http`
14 * variant uses. DNS is a zone-management capability with no native Worker
15 * binding, so there is no `*Binding` counterpart.
16 *
17 * NOT exported from `index.ts` — this is internal scaffolding shared by the
18 * three access-level Local layers.
19 */
20export const makeLocalDnsBinding = <Client>(options: {
21 makeClient: (auth: DnsAuth, zoneId: Effect.Effect<string>) => Client;
22}) =>
23 Effect.gen(function* () {
24 // Credentials are ambient during stack-eval (the stack's providers layer).
25 // Capture the full context so DNS HTTP ops can run with the current
26 // credentials — no `host.bind`, no minted token. DNS record ops are
27 // zone-scoped, so no accountId is needed.
28 const context = yield* Effect.context<
29 Credentials | HttpClient.HttpClient
30 >();
31
32 return Effect.fn(function* (zone: Zone) {
33 // Deferred accessor — resolves the zoneId against the tracker at apply
34 // time (in an Action, that's the engine's resolve context).
35 const zoneId = yield* zone.zoneId;
36 const auth: DnsAuth = {
37 authorize: (eff) => eff.pipe(Effect.provideContext(context)),
38 };
39 return options.makeClient(auth, zoneId);
40 });
41 });