1import * as Effect from "effect/Effect";
2import * as Binding from "../../Binding.ts";
3import { isBindingHost } from "../Lambda/Function.ts";
4
5/**
6 * Shared scaffolding for Amazon DevOps Guru HTTP bindings.
7 *
8 * NOT exported from `index.ts` — every `{Op}Http.ts` in this service is a
9 * thin `Layer.effect(Cap, makeDevOpsGuruAccountHttpBinding({ … }))` over the
10 * builder below. Everything except the operation and the IAM action is
11 * boilerplate.
12 *
13 * All DevOps Guru actions are account-level: the service does not support
14 * resource-level IAM permissions (insights, anomalies, and health summaries
15 * are account/region-scoped API objects, not ARN-addressable resources), so
16 * the deploy-time half always grants the action on `*`.
17 */
18
19/**
20 * Build the impl Effect for an account-level DevOps Guru operation. The
21 * runtime callable passes the caller's request through unchanged; the
22 * deploy-time half grants `actions` on `*`.
23 */
24export const makeDevOpsGuruAccountHttpBinding = <I, A, E, R>(options: {
25 /** Fully-qualified binding tag, e.g. `AWS.DevOpsGuru.ListInsights`. */
26 tag: string;
27 /** The distilled operation, invoked with the caller's request as-is. */
28 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
29 /** IAM actions granted on `*`. */
30 actions: readonly string[];
31}) =>
32 Effect.gen(function* () {
33 const op = yield* options.operation;
34
35 return Effect.fn(function* () {
36 if (!globalThis.__ALCHEMY_RUNTIME__) {
37 const host = yield* Binding.Host;
38 if (isBindingHost(host)) {
39 yield* host.bind`Allow(${host}, ${options.tag}())`({
40 policyStatements: [
41 {
42 Effect: "Allow",
43 Action: [...options.actions],
44 Resource: ["*"],
45 },
46 ],
47 });
48 }
49 }
50 return Effect.fn(options.tag)(function* (request?: I) {
51 return yield* op((request ?? {}) as I);
52 });
53 });
54 });