1import * as Effect from "effect/Effect";
2import * as Binding from "../../Binding.ts";
3import { isBindingHost } from "../Lambda/Function.ts";
4import type { Detector } from "./Detector.ts";
5import type { EventType } from "./EventType.ts";
6import type { List } from "./List.ts";
7
8/**
9 * Shared scaffolding for Amazon Fraud Detector HTTP bindings.
10 *
11 * NOT exported from `index.ts` — every thin `{Op}Http.ts` in this service is
12 * a `Layer.effect(Cap, make…HttpBinding({ … }))` over one of the two builders
13 * below. Everything except the operation and the IAM action list is
14 * boilerplate.
15 */
16
17/**
18 * Build the impl Effect for a Fraud Detector operation scoped to a
19 * {@link Detector}: the deploy-time half grants `actions` on the bound
20 * detector's ARN, and the runtime half injects the detector's `detectorId`
21 * into every request.
22 */
23export const makeFraudDetectorDetectorHttpBinding = <
24 I extends { detectorId: string },
25 A,
26 E,
27 R,
28>(options: {
29 /** Fully-qualified binding tag, e.g. `AWS.FraudDetector.GetEventPrediction`. */
30 tag: string;
31 /** The distilled operation. */
32 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
33 /** IAM actions granted on the detector ARN. */
34 actions: readonly string[];
35}) =>
36 Effect.gen(function* () {
37 const op = yield* options.operation;
38
39 return Effect.fn(function* (detector: Detector) {
40 // Output yields a DEFERRED effect — resolve again per invocation below.
41 const DetectorId = yield* detector.detectorId;
42 if (!globalThis.__ALCHEMY_RUNTIME__) {
43 const host = yield* Binding.Host;
44 if (isBindingHost(host)) {
45 yield* host.bind`Allow(${host}, ${options.tag}(${detector}))`({
46 policyStatements: [
47 {
48 Effect: "Allow",
49 Action: [...options.actions],
50 Resource: [detector.arn],
51 },
52 ],
53 });
54 }
55 }
56 return Effect.fn(`${options.tag}(${detector.LogicalId})`)(function* (
57 request: Omit<I, "detectorId">,
58 ) {
59 const detectorId = yield* DetectorId;
60 return yield* op({ ...request, detectorId } as I);
61 });
62 });
63 });
64
65/**
66 * Build the impl Effect for a Fraud Detector event data-plane operation
67 * scoped to an {@link EventType} (`SendEvent`, `GetEvent`, `DeleteEvent`,
68 * `UpdateEventLabel`): the deploy-time half grants `actions` on the bound
69 * event type's ARN, and the runtime half injects the event type's
70 * `eventTypeName` into every request.
71 */
72/**
73 * Build the impl Effect for a Fraud Detector list data-plane operation scoped
74 * to a {@link List} (`GetListElements`, `UpdateList`): the deploy-time half
75 * grants `actions` on the bound list's ARN, and the runtime half injects the
76 * list's `name` into every request.
77 */
78export const makeFraudDetectorListHttpBinding = <
79 I extends { name: string },
80 A,
81 E,
82 R,
83>(options: {
84 /** Fully-qualified binding tag, e.g. `AWS.FraudDetector.GetListElements`. */
85 tag: string;
86 /** The distilled operation. */
87 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
88 /** IAM actions granted on the list ARN. */
89 actions: readonly string[];
90}) =>
91 Effect.gen(function* () {
92 const op = yield* options.operation;
93
94 return Effect.fn(function* (list: List) {
95 // Output yields a DEFERRED effect — resolve again per invocation below.
96 const ListName = yield* list.name;
97 if (!globalThis.__ALCHEMY_RUNTIME__) {
98 const host = yield* Binding.Host;
99 if (isBindingHost(host)) {
100 yield* host.bind`Allow(${host}, ${options.tag}(${list}))`({
101 policyStatements: [
102 {
103 Effect: "Allow",
104 Action: [...options.actions],
105 Resource: [list.arn],
106 },
107 ],
108 });
109 }
110 }
111 return Effect.fn(`${options.tag}(${list.LogicalId})`)(function* (
112 request: Omit<I, "name">,
113 ) {
114 const name = yield* ListName;
115 return yield* op({ ...request, name } as unknown as I);
116 });
117 });
118 });
119
120export const makeFraudDetectorEventTypeHttpBinding = <
121 I extends { eventTypeName: string },
122 A,
123 E,
124 R,
125>(options: {
126 /** Fully-qualified binding tag, e.g. `AWS.FraudDetector.SendEvent`. */
127 tag: string;
128 /** The distilled operation. */
129 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
130 /** IAM actions granted on the event type ARN. */
131 actions: readonly string[];
132}) =>
133 Effect.gen(function* () {
134 const op = yield* options.operation;
135
136 return Effect.fn(function* (eventType: EventType) {
137 // Output yields a DEFERRED effect — resolve again per invocation below.
138 const EventTypeName = yield* eventType.name;
139 if (!globalThis.__ALCHEMY_RUNTIME__) {
140 const host = yield* Binding.Host;
141 if (isBindingHost(host)) {
142 yield* host.bind`Allow(${host}, ${options.tag}(${eventType}))`({
143 policyStatements: [
144 {
145 Effect: "Allow",
146 Action: [...options.actions],
147 Resource: [eventType.arn],
148 },
149 ],
150 });
151 }
152 }
153 return Effect.fn(`${options.tag}(${eventType.LogicalId})`)(function* (
154 request: Omit<I, "eventTypeName">,
155 ) {
156 const eventTypeName = yield* EventTypeName;
157 return yield* op({ ...request, eventTypeName } as unknown as I);
158 });
159 });
160 });