| 1 | import * as Effect from "effect/Effect"; |
| 2 | import * as Binding from "../../Binding.ts"; |
| 3 | import { isBindingHost } from "../Lambda/Function.ts"; |
| 4 | import 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 | */ |
| 24 | export 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 | */ |
| 48 | export 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 | }); |