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 Service Quotas runtime bindings.
7 *
8 * NOT exported from `index.ts` — every `{Op}Http.ts` in this service is a
9 * thin `Layer.effect(Cap, makeServiceQuotasHttpBinding({ … }))` over the
10 * builder below. Everything except the operation and the IAM action is
11 * boilerplate.
12 *
13 * Service Quotas is a control-plane query service: none of its actions
14 * support resource-level IAM in a way a deploy-time binding could scope
15 * (quota codes are supplied at runtime), so every grant is on
16 * `Resource: ["*"]` and every binding is account-level (takes no resource).
17 */
18export const makeServiceQuotasHttpBinding = <
19 I extends object,
20 A,
21 E,
22 R,
23>(options: {
24 /**
25 * Short capability name used in the binding sid and runtime span, e.g.
26 * `"GetServiceQuota"`.
27 */
28 capability: string;
29 /** IAM actions granted on `Resource: ["*"]`. */
30 iamActions: readonly string[];
31 /** The distilled operation implementing the capability. */
32 operation: Effect.Effect<(input: I) => Effect.Effect<A, E>, never, R>;
33}) =>
34 Effect.gen(function* () {
35 const op = yield* options.operation;
36
37 return Effect.fn(function* () {
38 if (!globalThis.__ALCHEMY_RUNTIME__) {
39 const host = yield* Binding.Host;
40 if (isBindingHost(host)) {
41 yield* host.bind`Allow(${host}, AWS.ServiceQuotas.${options.capability}())`(
42 {
43 policyStatements: [
44 {
45 Effect: "Allow",
46 Action: [...options.iamActions],
47 // Service Quotas actions have no deploy-time scopeable
48 // resource — quota ARNs are only known at runtime.
49 Resource: ["*"],
50 },
51 ],
52 },
53 );
54 }
55 }
56 return Effect.fn(`AWS.ServiceQuotas.${options.capability}`)(function* (
57 request?: I,
58 ) {
59 return yield* op((request ?? {}) as I);
60 });
61 });
62 });