1import * as Effect from "effect/Effect";
2import * as Binding from "../../Binding.ts";
3import { isBindingHost } from "../Lambda/Function.ts";
4import type { CertificateAuthority } from "./CertificateAuthority.ts";
5
6/**
7 * Options for {@link makeACMPCAHttpBinding}.
8 *
9 * @internal shared HTTP scaffolding for the ACM PCA capability bindings —
10 * not exported from the service index.
11 */
12export interface ACMPCAHttpBindingOptions<
13 Req extends { CertificateAuthorityArn: string },
14 A,
15 E,
16 R,
17> {
18 /**
19 * The ACM PCA action name, e.g. `"IssueCertificate"`. Used verbatim for
20 * the IAM action (`acm-pca:{action}`), the bind label, and the tracing
21 * span name.
22 */
23 action: string;
24 /**
25 * The distilled ACM PCA operation. Every ACM PCA data-plane operation is
26 * keyed by `CertificateAuthorityArn`, which the binding injects from the
27 * bound {@link CertificateAuthority}.
28 */
29 operation: Effect.Effect<(request: Req) => Effect.Effect<A, E>, never, R>;
30}
31
32/**
33 * Build the implementation Effect for an ACM PCA HTTP capability binding.
34 *
35 * Every ACM PCA capability has the same shape — resolve the CA's ARN,
36 * register an IAM policy statement for `acm-pca:{action}` scoped to that
37 * CA at deploy time, and return a runtime callable that injects
38 * `CertificateAuthorityArn` into the operation's request. Only the
39 * operation and the action name differ, so each `{Op}Http.ts` is a thin
40 * `Layer.effect(Cap, makeACMPCAHttpBinding({ ... }))`.
41 *
42 * @internal
43 */
44export const makeACMPCAHttpBinding = <
45 Req extends { CertificateAuthorityArn: string },
46 A,
47 E,
48 R,
49>(
50 options: ACMPCAHttpBindingOptions<Req, A, E, R>,
51) =>
52 Effect.gen(function* () {
53 const operation = yield* options.operation;
54
55 return Effect.fn(function* (certificateAuthority: CertificateAuthority) {
56 const Arn = yield* certificateAuthority.certificateAuthorityArn;
57 if (!globalThis.__ALCHEMY_RUNTIME__) {
58 const host = yield* Binding.Host;
59 if (isBindingHost(host)) {
60 yield* host.bind`Allow(${host}, AWS.ACMPCA.${options.action}(${certificateAuthority}))`(
61 {
62 policyStatements: [
63 {
64 Effect: "Allow",
65 Action: [`acm-pca:${options.action}`],
66 Resource: [certificateAuthority.certificateAuthorityArn],
67 },
68 ],
69 },
70 );
71 }
72 }
73 return Effect.fn(
74 `AWS.ACMPCA.${options.action}(${certificateAuthority.LogicalId})`,
75 )(function* (
76 request: Omit<Req, "CertificateAuthorityArn"> = {} as Omit<
77 Req,
78 "CertificateAuthorityArn"
79 >,
80 ) {
81 return yield* operation({
82 ...request,
83 CertificateAuthorityArn: yield* Arn,
84 } as Req);
85 });
86 });
87 });