1import * as Effect from "effect/Effect";
2import * as Binding from "../../Binding.ts";
3import { isBindingHost } from "../Lambda/Function.ts";
4
5/**
6 * Shared scaffolding for AWS Rekognition HTTP bindings.
7 *
8 * NOT exported from `index.ts` — every `{Op}Http.ts` in this service is a
9 * thin `Layer.effect(Cap, makeRekognitionHttpBinding({ … }))` over the
10 * builder below. Everything except the operation and the IAM action list is
11 * boilerplate: Rekognition's image/video analysis and collection data-plane
12 * IAM actions are granted on `*` because the resources they touch
13 * (collections, users, jobs) are routinely created at runtime — e.g. a
14 * collection per application tenant — so their identifiers are unknown at
15 * deploy time.
16 */
17export const makeRekognitionHttpBinding = <I, A, E, R>(options: {
18 /** Fully-qualified binding tag, e.g. `AWS.Rekognition.DetectLabels`. */
19 tag: string;
20 /** The distilled operation, invoked with the caller's request as-is. */
21 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
22 /** IAM actions granted on `*`. */
23 actions: readonly string[];
24}) =>
25 Effect.gen(function* () {
26 const op = yield* options.operation;
27
28 return Effect.fn(function* () {
29 if (!globalThis.__ALCHEMY_RUNTIME__) {
30 const host = yield* Binding.Host;
31 if (isBindingHost(host)) {
32 yield* host.bind`Allow(${host}, ${options.tag}())`({
33 policyStatements: [
34 {
35 Effect: "Allow",
36 Action: [...options.actions],
37 Resource: ["*"],
38 },
39 ],
40 });
41 }
42 }
43 return Effect.fn(options.tag)(function* (request?: I) {
44 return yield* op((request ?? {}) as I);
45 });
46 });
47 });