1import * as Effect from "effect/Effect";
2import * as Binding from "../../Binding.ts";
3import { isBindingHost } from "../Lambda/Function.ts";
4import type { PolicyStatement } from "../IAM/Policy.ts";
5
6/**
7 * Shared HTTP scaffolding for the AWS Account Management runtime bindings.
8 *
9 * Account Management is an account-singleton global service: every runtime
10 * operation reads settings of the calling account (account information,
11 * primary/alternate contacts, Region opt statuses), so every binding is
12 * account-level and grants its action(s) on `Resource: ["*"]` (the account
13 * ARN is the caller's own account, fixed by the credentials rather than
14 * chosen per resource).
15 *
16 * NOT exported from `index.ts` — every thin `{Op}Http.ts` in this service is
17 * a `Layer.effect(Cap, makeAccountHttpBinding({ … }))` over the builder
18 * below. Everything except the operation and the IAM action list is
19 * boilerplate.
20 */
21export const makeAccountHttpBinding = <I, A, E, R>(options: {
22 /**
23 * Short capability name used in the binding sid and runtime span, e.g.
24 * `"GetContactInformation"`.
25 */
26 capability: string;
27 /**
28 * IAM actions granted on `Resource: ["*"]` (Account Management operations
29 * target the calling account itself).
30 */
31 iamActions: readonly string[];
32 /**
33 * The distilled operation implementing the capability.
34 */
35 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
36}) =>
37 Effect.gen(function* () {
38 const op = yield* options.operation;
39
40 return Effect.fn(function* () {
41 if (!globalThis.__ALCHEMY_RUNTIME__) {
42 const host = yield* Binding.Host;
43 if (isBindingHost(host)) {
44 const policyStatements: PolicyStatement[] = [
45 {
46 Effect: "Allow",
47 Action: [...options.iamActions],
48 // Account Management operations act on the calling account
49 // itself (identified by the credentials, not a per-resource
50 // ARN chosen at deploy time).
51 Resource: ["*"],
52 },
53 ];
54 yield* host.bind`Allow(${host}, AWS.Account.${options.capability}())`(
55 {
56 policyStatements,
57 },
58 );
59 }
60 }
61 return Effect.fn(`AWS.Account.${options.capability}`)(function* (
62 request?: I,
63 ) {
64 return yield* op((request ?? {}) as I);
65 });
66 });
67 });