1import * as Effect from "effect/Effect";
2import * as Binding from "../../Binding.ts";
3import { isBindingHost } from "../Lambda/Function.ts";
4import type { Firewall } from "./Firewall.ts";
5import type { FirewallPolicy } from "./FirewallPolicy.ts";
6import type { RuleGroup } from "./RuleGroup.ts";
7
8/**
9 * Shared scaffolding for AWS Network Firewall HTTP bindings.
10 *
11 * NOT exported from `index.ts` — every `{Op}Http.ts` in this service is a
12 * thin `Layer.effect(Cap, make…HttpBinding({ … }))` over one of the three
13 * builders below. Everything except the operation and the IAM action is
14 * boilerplate:
15 *
16 * - {@link makeNetworkFirewallFirewallHttpBinding} — operations scoped to one
17 * bound {@link Firewall} (`DescribeFirewall`, the flow-operation interface,
18 * the analysis-report interface). The runtime callable injects the
19 * firewall's ARN as the request's `FirewallArn`; the deploy-time half
20 * grants `actions` on the firewall ARN.
21 * - {@link makeNetworkFirewallFirewallPolicyHttpBinding} — operations scoped
22 * to one bound {@link FirewallPolicy}; injects `FirewallPolicyArn`.
23 * - {@link makeNetworkFirewallRuleGroupHttpBinding} — operations scoped to
24 * one bound {@link RuleGroup}; injects `RuleGroupArn`.
25 */
26
27/**
28 * Build the impl Effect for an operation scoped to a single bound
29 * {@link Firewall}. The runtime callable injects the firewall's ARN as the
30 * request's `FirewallArn`; the deploy-time half grants `actions` on the
31 * firewall ARN.
32 */
33export const makeNetworkFirewallFirewallHttpBinding = <
34 I extends { FirewallArn?: string },
35 A,
36 E,
37 R,
38>(options: {
39 /** Fully-qualified binding tag, e.g. `AWS.NetworkFirewall.StartFlowCapture`. */
40 tag: string;
41 /** The distilled operation; `FirewallArn` is injected from the resource. */
42 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
43 /** IAM actions granted on the firewall ARN. */
44 actions: readonly string[];
45}) =>
46 Effect.gen(function* () {
47 const op = yield* options.operation;
48
49 return Effect.fn(function* (firewall: Firewall) {
50 const FirewallArn = yield* firewall.firewallArn;
51 if (!globalThis.__ALCHEMY_RUNTIME__) {
52 const host = yield* Binding.Host;
53 if (isBindingHost(host)) {
54 yield* host.bind`Allow(${host}, ${options.tag}(${firewall}))`({
55 policyStatements: [
56 {
57 Effect: "Allow",
58 Action: [...options.actions],
59 Resource: [firewall.firewallArn],
60 },
61 ],
62 });
63 }
64 }
65 return Effect.fn(`${options.tag}(${firewall.LogicalId})`)(function* (
66 request?: Omit<I, "FirewallArn" | "FirewallName">,
67 ) {
68 return yield* op({
69 ...request,
70 FirewallArn: yield* FirewallArn,
71 } as I);
72 });
73 });
74 });
75
76/**
77 * Build the impl Effect for an operation scoped to a single bound
78 * {@link FirewallPolicy}. The runtime callable injects the policy's ARN as
79 * the request's `FirewallPolicyArn`; the deploy-time half grants `actions`
80 * on the policy ARN.
81 */
82export const makeNetworkFirewallFirewallPolicyHttpBinding = <
83 I extends { FirewallPolicyArn?: string },
84 A,
85 E,
86 R,
87>(options: {
88 /** Fully-qualified binding tag, e.g. `AWS.NetworkFirewall.DescribeFirewallPolicy`. */
89 tag: string;
90 /** The distilled operation; `FirewallPolicyArn` is injected from the resource. */
91 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
92 /** IAM actions granted on the firewall policy ARN. */
93 actions: readonly string[];
94}) =>
95 Effect.gen(function* () {
96 const op = yield* options.operation;
97
98 return Effect.fn(function* (policy: FirewallPolicy) {
99 const FirewallPolicyArn = yield* policy.firewallPolicyArn;
100 if (!globalThis.__ALCHEMY_RUNTIME__) {
101 const host = yield* Binding.Host;
102 if (isBindingHost(host)) {
103 yield* host.bind`Allow(${host}, ${options.tag}(${policy}))`({
104 policyStatements: [
105 {
106 Effect: "Allow",
107 Action: [...options.actions],
108 Resource: [policy.firewallPolicyArn],
109 },
110 ],
111 });
112 }
113 }
114 return Effect.fn(`${options.tag}(${policy.LogicalId})`)(function* (
115 request?: Omit<I, "FirewallPolicyArn" | "FirewallPolicyName">,
116 ) {
117 return yield* op({
118 ...request,
119 FirewallPolicyArn: yield* FirewallPolicyArn,
120 } as I);
121 });
122 });
123 });
124
125/**
126 * Build the impl Effect for an operation scoped to a single bound
127 * {@link RuleGroup}. The runtime callable injects the rule group's ARN as
128 * the request's `RuleGroupArn`; the deploy-time half grants `actions` on the
129 * rule group ARN.
130 */
131export const makeNetworkFirewallRuleGroupHttpBinding = <
132 I extends { RuleGroupArn?: string },
133 A,
134 E,
135 R,
136>(options: {
137 /** Fully-qualified binding tag, e.g. `AWS.NetworkFirewall.DescribeRuleGroup`. */
138 tag: string;
139 /** The distilled operation; `RuleGroupArn` is injected from the resource. */
140 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
141 /** IAM actions granted on the rule group ARN. */
142 actions: readonly string[];
143}) =>
144 Effect.gen(function* () {
145 const op = yield* options.operation;
146
147 return Effect.fn(function* (ruleGroup: RuleGroup) {
148 const RuleGroupArn = yield* ruleGroup.ruleGroupArn;
149 if (!globalThis.__ALCHEMY_RUNTIME__) {
150 const host = yield* Binding.Host;
151 if (isBindingHost(host)) {
152 yield* host.bind`Allow(${host}, ${options.tag}(${ruleGroup}))`({
153 policyStatements: [
154 {
155 Effect: "Allow",
156 Action: [...options.actions],
157 Resource: [ruleGroup.ruleGroupArn],
158 },
159 ],
160 });
161 }
162 }
163 return Effect.fn(`${options.tag}(${ruleGroup.LogicalId})`)(function* (
164 request?: Omit<I, "RuleGroupArn" | "RuleGroupName" | "Type">,
165 ) {
166 return yield* op({
167 ...request,
168 RuleGroupArn: yield* RuleGroupArn,
169 } as I);
170 });
171 });
172 });