1import type {
2 GetRecordError,
3 GetRecordResponse,
4 ListRecordsError,
5 ListRecordsRequest,
6 ListRecordsResponse,
7} from "@distilled.cloud/cloudflare/dns";
8import * as Effect from "effect/Effect";
9import * as Binding from "../../Binding.ts";
10import type { RuntimeContext } from "../../RuntimeContext.ts";
11import type { Zone } from "../Zone/Zone.ts";
12
13/**
14 * Binding that lets a Worker read Cloudflare DNS records at runtime.
15 *
16 * Creates a least-privilege {@link AccountApiToken} with only the `DNS Read`
17 * permission, scoped to the single zone passed to `bind`, and binds its value
18 * into the Worker so runtime code can authenticate.
19 *
20 *
21 * ### Reading DNS records at runtime
22 * **Example:** Read records from inside a Worker
23 * Bind the client in the Worker's Init phase and provide {@link ReadDnsBinding}.
24 * The zone is fixed by `ReadDnsBinding(zone)` — the provisioned token only grants
25 * access to that zone, so calls take no `zoneId`. Pass the {@link Zone}
26 * resource directly (it's an `Effect`), or `yield* Zone` for a resolved value.
27 * ```typescript
28 * import * as Cloudflare from "alchemy/Cloudflare";
29 * import * as Effect from "effect/Effect";
30 * import * as HttpServerResponse from "effect/http/HttpServerResponse";
31 *
32 * const Zone = Cloudflare.Zone.Zone("MyZone", { name: "example.com" });
33 *
34 * export class ReadDnserWorker extends Cloudflare.Worker<ReadDnserWorker>()(
35 * "ReadDnserWorker",
36 * { main: import.meta.url },
37 * Effect.gen(function* () {
38 * // Init phase — bind the read client scoped to the zone.
39 * const dns = yield* Cloudflare.DNS.ReadDns(Zone);
40 *
41 * return {
42 * fetch: Effect.gen(function* () {
43 * const { result } = yield* dns.listDnsRecords({ type: "A" });
44 * const record = yield* dns.getDnsRecord(result[0].id);
45 * return yield* HttpServerResponse.json({ id: record.id });
46 * }),
47 * };
48 * }).pipe(Effect.provide(Cloudflare.DNS.ReadDnsBinding)),
49 * ) {}
50 * ```
51 *
52 * @binding
53 * @product DNS
54 * @category Domains & DNS
55 */
56export interface ReadDns extends Binding.Service<
57 ReadDns,
58 "Cloudflare.DNS.ReadDns",
59 (zone: Zone) => Effect.Effect<ReadDnsClient>
60> {}
61
62export const ReadDns = Binding.Service<ReadDns>("Cloudflare.DNS.ReadDns");
63
64/** List-records request, minus the zone id (bound at `ReadDnsBinding(zone)` time). */
65export type ListRecordsRequestInput = Omit<ListRecordsRequest, "zoneId">;
66
67/**
68 * Read-only DNS record operations. Backed by the `DNS Read` permission group.
69 * The zone is fixed when the client is bound, so no `zoneId` is passed per call.
70 */
71export interface ReadDnsClient {
72 /** Fetch a single DNS record by id. */
73 getDnsRecord(
74 dnsRecordId: string,
75 ): Effect.Effect<GetRecordResponse, GetRecordError, RuntimeContext>;
76 /** List the DNS records in the bound zone. */
77 listDnsRecords(
78 request?: ListRecordsRequestInput,
79 ): Effect.Effect<ListRecordsResponse, ListRecordsError, RuntimeContext>;
80}