1import * as Effect from "effect/Effect";
2import * as Binding from "../../Binding.ts";
3import { isBindingHost } from "../Lambda/Function.ts";
4import { withRoute53DomainsRegion } from "./internal.ts";
5
6/**
7 * Shared HTTP scaffolding for the Route 53 Domains runtime bindings.
8 *
9 * NOT exported from `index.ts` — every `{Op}Http.ts` in this service is a
10 * thin `Layer.effect(Cap, makeRoute53DomainsHttpBinding({ … }))` over the
11 * builder below. Everything except the operation and the IAM action is
12 * boilerplate.
13 *
14 * Route 53 Domains is a global registration API with no resource-level IAM:
15 * every action authorizes account-wide, so the builder always grants on
16 * `Resource: ["*"]` and the capability takes no arguments. The API is only
17 * served from `us-east-1`, so the captured client is pinned to that region
18 * regardless of where the calling function runs.
19 */
20export const makeRoute53DomainsHttpBinding = <
21 I extends object,
22 A,
23 E,
24 R,
25>(options: {
26 /**
27 * Short capability name used in the binding sid and runtime span, e.g.
28 * `"CheckDomainAvailability"`.
29 */
30 capability: string;
31 /** IAM actions granted on `Resource: ["*"]`. */
32 iamActions: readonly string[];
33 /** The distilled operation implementing the capability. */
34 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
35}) =>
36 Effect.gen(function* () {
37 // Capture the client with the region pinned to us-east-1 — the Route 53
38 // Domains API is not served from any other region.
39 const op = yield* withRoute53DomainsRegion(options.operation);
40
41 return Effect.fn(function* () {
42 if (!globalThis.__ALCHEMY_RUNTIME__) {
43 const host = yield* Binding.Host;
44 if (isBindingHost(host)) {
45 yield* host.bind`Allow(${host}, AWS.Route53Domains.${options.capability}())`(
46 {
47 policyStatements: [
48 {
49 Effect: "Allow",
50 Action: [...options.iamActions],
51 // route53domains has no resource-level IAM
52 Resource: ["*"],
53 },
54 ],
55 },
56 );
57 }
58 }
59 return Effect.fn(`AWS.Route53Domains.${options.capability}`)(function* (
60 request: I,
61 ) {
62 // The region must also be pinned at the call site: the yield-time
63 // snapshot is only a fallback — the calling fiber's ambient Region
64 // (the host Function's own region) wins over it.
65 return yield* withRoute53DomainsRegion(op(request));
66 });
67 });
68 });