1import * as Effect from "effect/Effect";
2import * as Binding from "../../Binding.ts";
3import { isBindingHost } from "../Lambda/Function.ts";
4import type { Domain } from "./Domain.ts";
5
6/**
7 * Shared scaffolding for SimpleDB per-operation bindings.
8 *
9 * INTERNAL — deliberately not exported from the service `index.ts`.
10 *
11 * Every SimpleDB data-plane operation follows the same shape: it targets a
12 * single {@link Domain}, requires the IAM action `sdb:{Operation}` on
13 * `arn:aws:sdb:{region}:{account}:domain/{domainName}`, and (except for
14 * `Select`) injects the domain's physical `DomainName` into the request.
15 * `makeSimpleDbBinding` encodes that once so each `{Op}Http.ts` is a thin
16 * call into it; `registerSimpleDbBinding` is the deploy-time IAM half on its
17 * own for operations (like `Select`) that need a custom runtime client.
18 */
19
20/**
21 * Deploy-time half of a SimpleDB binding: grants `sdb:{operation}` on the
22 * domain's ARN to the host Function. No-op at runtime.
23 */
24export const registerSimpleDbBinding = (operation: string, domain: Domain) =>
25 Effect.gen(function* () {
26 if (!globalThis.__ALCHEMY_RUNTIME__) {
27 const host = yield* Binding.Host;
28 if (isBindingHost(host)) {
29 yield* host.bind`Allow(${host}, AWS.SimpleDB.${operation}(${domain}))`({
30 policyStatements: [
31 {
32 Effect: "Allow",
33 Action: [`sdb:${operation}`],
34 Resource: [domain.domainArn],
35 },
36 ],
37 });
38 }
39 }
40 });
41
42/**
43 * Builds the full binding implementation for a SimpleDB operation whose
44 * request carries a `DomainName` member: registers the IAM grant and returns
45 * a runtime client that closes over the domain's physical name and injects
46 * it into every request.
47 */
48export const makeSimpleDbBinding = <
49 Req extends { DomainName: string },
50 A,
51 E,
52 R,
53>(options: {
54 readonly operation: string;
55 readonly method: Effect.Effect<(input: Req) => Effect.Effect<A, E>, never, R>;
56}) =>
57 Effect.gen(function* () {
58 const call = yield* options.method;
59 return Effect.fn(function* (domain: Domain) {
60 const domainName = yield* domain.domainName;
61 yield* registerSimpleDbBinding(options.operation, domain);
62 return Effect.fn(
63 `AWS.SimpleDB.${options.operation}(${domain.LogicalId})`,
64 )(function* (request?: Omit<Req, "DomainName">) {
65 const name = yield* domainName;
66 return yield* call({ ...request, DomainName: name } as Req);
67 });
68 });
69 });