1import * as Effect from "effect/Effect";
2import * as Binding from "../../Binding.ts";
3import { isBindingHost } from "../Lambda/Function.ts";
4
5/**
6 * Shared HTTP scaffolding for the Lake Formation runtime bindings.
7 *
8 * NOT exported from `index.ts` — every `{Op}Http.ts` in this service is a
9 * thin `Layer.effect(Cap, makeLakeFormationHttpBinding({ … }))` over the
10 * builder below. Everything except the operation and the IAM action list is
11 * boilerplate.
12 *
13 * Per the `lakeformation` service authorization reference, Lake Formation
14 * IAM actions support no resource types (authorization beyond IAM is
15 * enforced by Lake Formation's own permission grants — see
16 * `AWS.LakeFormation.Permissions`), so every binding grants its actions on
17 * `Resource: ["*"]`.
18 */
19export const makeLakeFormationHttpBinding = <
20 I extends object,
21 A,
22 E,
23 R,
24>(options: {
25 /**
26 * Short capability name used in the binding sid and runtime span, e.g.
27 * `"GetDataLakePrincipal"`.
28 */
29 capability: string;
30 /** IAM actions granted on `Resource: ["*"]`. */
31 iamActions: readonly string[];
32 /** The distilled operation implementing the capability. */
33 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
34}) =>
35 Effect.gen(function* () {
36 const op = yield* options.operation;
37
38 return Effect.fn(function* () {
39 if (!globalThis.__ALCHEMY_RUNTIME__) {
40 const host = yield* Binding.Host;
41 if (isBindingHost(host)) {
42 yield* host.bind`Allow(${host}, AWS.LakeFormation.${options.capability}())`(
43 {
44 policyStatements: [
45 {
46 Effect: "Allow",
47 Action: [...options.iamActions],
48 Resource: ["*"],
49 },
50 ],
51 },
52 );
53 }
54 }
55 return Effect.fn(`AWS.LakeFormation.${options.capability}`)(function* (
56 request?: I,
57 ) {
58 return yield* op((request ?? {}) as I);
59 });
60 });
61 });