1import type * as Effect from "effect/Effect";
2import * as Binding from "../../Binding.ts";
3import type { RuntimeContext } from "../../RuntimeContext.ts";
4import { connectEnvPrefix as makeConnectEnvPrefix } from "../Connection/internal.ts";
5import type { ServerlessCluster } from "./ServerlessCluster.ts";
6
7/**
8 * Connection descriptor for an MSK {@link ServerlessCluster}. Alchemy does
9 * not bundle a Kafka client — pass these settings to the Kafka client of
10 * your choice (`kafkajs` + `aws-msk-iam-sasl-signer-js`, `@confluentinc/kafka-javascript`, ...),
11 * which speaks the Kafka wire protocol against the cluster's SASL/IAM
12 * bootstrap endpoint.
13 */
14export interface ClusterConnectionInfo {
15 /**
16 * Comma-separated SASL/IAM bootstrap broker string
17 * (`boot-….kafka-serverless.….amazonaws.com:9098`).
18 */
19 bootstrapServers: string;
20 /** Bootstrap brokers as individual `host:port` entries (kafkajs `brokers`). */
21 brokers: string[];
22 /** ARN of the cluster (MSK IAM SASL signers take the cluster's region). */
23 clusterArn: string;
24 /**
25 * SASL mechanism the endpoint requires — always IAM (`AWS_MSK_IAM` over
26 * TLS) for MSK Serverless.
27 */
28 authentication: "iam";
29}
30
31/**
32 * Environment variable prefix under which the connect bindings publish the
33 * cluster endpoint on the host Function, derived from the cluster's logical
34 * ID. A cluster with logical ID `Events` yields `MSK_EVENTS` and the
35 * variables `MSK_EVENTS_BROKERS` and `MSK_EVENTS_ARN`.
36 */
37export const connectEnvPrefix = (logicalId: string): string =>
38 makeConnectEnvPrefix("MSK", logicalId);
39
40/**
41 * Read-only (consumer) runtime access to an MSK {@link ServerlessCluster}'s
42 * data plane.
43 *
44 * Grants the MSK IAM-auth actions a Kafka consumer needs
45 * (`kafka-cluster:Connect` on the cluster, `kafka-cluster:ReadData` +
46 * `kafka-cluster:DescribeTopic` on the cluster's topics, and
47 * `kafka-cluster:DescribeGroup` + `kafka-cluster:AlterGroup` on its consumer
48 * groups), publishes the SASL/IAM bootstrap endpoint as environment
49 * variables on the host Function, and resolves a typed
50 * {@link ClusterConnectionInfo} at runtime.
51 *
52 * The Kafka data plane is VPC-only — the host Function must be attached to
53 * the cluster's VPC and allowed ingress on port 9098 by the cluster's
54 * security groups. Provide the implementation with
55 * `Effect.provide(AWS.Kafka.ConnectReadHttp)`.
56 * ### Connecting to a Cluster
57 * **Example:** Resolve Consumer Connection Info inside a Function
58 * ```typescript
59 * const connect = yield* Kafka.ConnectRead(cluster);
60 * // inside a handler:
61 * const { brokers, authentication } = yield* connect;
62 * ```
63 *
64 * @binding
65 */
66export interface ConnectRead extends Binding.Service<
67 ConnectRead,
68 "AWS.Kafka.ConnectRead",
69 (
70 cluster: ServerlessCluster,
71 ) => Effect.Effect<
72 Effect.Effect<ClusterConnectionInfo, never, RuntimeContext>
73 >
74> {}
75export const ConnectRead = Binding.Service<ConnectRead>(
76 "AWS.Kafka.ConnectRead",
77);
78
79/**
80 * Write-only (producer) runtime access to an MSK {@link ServerlessCluster}'s
81 * data plane.
82 *
83 * Grants the MSK IAM-auth actions a Kafka producer needs
84 * (`kafka-cluster:Connect` + `kafka-cluster:WriteDataIdempotently` on the
85 * cluster, `kafka-cluster:WriteData` + `kafka-cluster:DescribeTopic` on the
86 * cluster's topics, and the transactional-id actions for transactional
87 * producers), publishes the SASL/IAM bootstrap endpoint as environment
88 * variables on the host Function, and resolves a typed
89 * {@link ClusterConnectionInfo} at runtime.
90 *
91 * The Kafka data plane is VPC-only — the host Function must be attached to
92 * the cluster's VPC and allowed ingress on port 9098 by the cluster's
93 * security groups. Provide the implementation with
94 * `Effect.provide(AWS.Kafka.ConnectWriteHttp)`.
95 * ### Connecting to a Cluster
96 * **Example:** Resolve Producer Connection Info inside a Function
97 * ```typescript
98 * const connect = yield* Kafka.ConnectWrite(cluster);
99 * // inside a handler:
100 * const { bootstrapServers } = yield* connect;
101 * ```
102 *
103 * @binding
104 */
105export interface ConnectWrite extends Binding.Service<
106 ConnectWrite,
107 "AWS.Kafka.ConnectWrite",
108 (
109 cluster: ServerlessCluster,
110 ) => Effect.Effect<
111 Effect.Effect<ClusterConnectionInfo, never, RuntimeContext>
112 >
113> {}
114export const ConnectWrite = Binding.Service<ConnectWrite>(
115 "AWS.Kafka.ConnectWrite",
116);
117
118/**
119 * Full read-write runtime access to an MSK {@link ServerlessCluster}'s data
120 * plane.
121 *
122 * Grants both the consumer- and producer-side MSK IAM-auth actions on the
123 * cluster, its topics, its consumer groups, and its transactional ids,
124 * publishes the SASL/IAM bootstrap endpoint as environment variables on the
125 * host Function, and resolves a typed {@link ClusterConnectionInfo} at
126 * runtime.
127 *
128 * The Kafka data plane is VPC-only — the host Function must be attached to
129 * the cluster's VPC and allowed ingress on port 9098 by the cluster's
130 * security groups. Provide the implementation with
131 * `Effect.provide(AWS.Kafka.ConnectReadWriteHttp)`.
132 * ### Connecting to a Cluster
133 * **Example:** Resolve Connection Info inside a Function
134 * ```typescript
135 * const connect = yield* Kafka.ConnectReadWrite(cluster);
136 * // inside a handler:
137 * const { bootstrapServers, brokers, clusterArn } = yield* connect;
138 * ```
139 *
140 * @binding
141 */
142export interface ConnectReadWrite extends Binding.Service<
143 ConnectReadWrite,
144 "AWS.Kafka.ConnectReadWrite",
145 (
146 cluster: ServerlessCluster,
147 ) => Effect.Effect<
148 Effect.Effect<ClusterConnectionInfo, never, RuntimeContext>
149 >
150> {}
151export const ConnectReadWrite = Binding.Service<ConnectReadWrite>(
152 "AWS.Kafka.ConnectReadWrite",
153);