1import * as Cloudflare from "@/Cloudflare";
2import * as Cause from "effect/Cause";
3import * as Effect from "effect/Effect";
4import { HttpServerRequest } from "effect/http/HttpServerRequest";
5import * as HttpServerResponse from "effect/http/HttpServerResponse";
6import { Zone } from "./zone.ts";
7/**
8 * Effect-native Worker fixture that exercises the {@link Cloudflare.DNS.ReadWriteDns}
9 * binding (full DNS record CRUD).
10 *
11 * Binding `DnsReadWrite` in the Init phase provisions a scoped
12 * {@link Cloudflare.ApiToken.AccountApiToken} (with `DNS Read` + `DNS Write`, limited to
13 * the bound zone) and binds its value plus the zone id into the Worker. The
14 * `/dns` route then drives a self-contained create → get → list → update →
15 * delete scenario against that zone.
16 */
17export default class DnsEffectWorker extends Cloudflare.Worker<DnsEffectWorker>()(
18 "DnsEffectWorker",
19 {
20 main: import.meta.url,
21 },
22 Effect.gen(function* () {
23 const dns = yield* Cloudflare.DNS.ReadWriteDns(Zone);
24
25 return {
26 fetch: Effect.gen(function* () {
27 const request = yield* HttpServerRequest;
28 const url = new URL(request.originalUrl);
29
30 if (url.pathname === "/dns") {
31 const name = url.searchParams.get("name")!;
32
33 return yield* Effect.gen(function* () {
34 // Tests use a deterministic record name — purge any leftover
35 // record from a previously crashed run before creating.
36 const leftovers = yield* dns.listDnsRecords({
37 type: "A",
38 name: { exact: name },
39 });
40 yield* Effect.forEach(
41 (leftovers.result ?? []).filter((r) => r.name === name),
42 (r) => dns.deleteDnsRecord(r.id),
43 );
44
45 const created = yield* dns.createDnsRecord({
46 type: "A",
47 name,
48 content: "192.0.2.1",
49 ttl: 1,
50 });
51 const id = created.id;
52
53 const got = yield* dns.getDnsRecord(id);
54 const list = yield* dns.listDnsRecords({ type: "A" });
55 const updated = yield* dns.updateDnsRecord(id, {
56 type: "A",
57 name,
58 content: "192.0.2.2",
59 ttl: 1,
60 });
61 yield* dns.deleteDnsRecord(id);
62
63 return yield* HttpServerResponse.json({
64 id,
65 getName: got.name,
66 count: list.result?.length,
67 updatedId: updated.id,
68 deleted: true,
69 });
70 }).pipe(
71 Effect.catchCause((cause) =>
72 HttpServerResponse.json(
73 { error: Cause.pretty(cause) },
74 { status: 500 },
75 ),
76 ),
77 );
78 }
79
80 return HttpServerResponse.text("ok");
81 }),
82 };
83 }).pipe(Effect.provide(Cloudflare.DNS.ReadWriteDnsHttp)),
84) {}