1import type * as eventbridge from "@distilled.cloud/aws/eventbridge";
2import type * as Effect from "effect/Effect";
3import type * as Sink from "effect/Sink";
4import * as Binding from "../../Binding.ts";
5import type { BatchRetryExhaustedError } from "../internal/BatchedSink.ts";
6import type { EventBus } from "./EventBus.ts";
7
8/**
9 * A raw `PutEventsRequestEntry` minus `EventBusName`, which the sink derives
10 * from the bus it is bound to. Callers stay in control of `Source`,
11 * `DetailType`, `Detail`, `Time`, `Resources`, and `TraceHeader` — no
12 * auto-marshalling.
13 */
14export interface BusSinkEntry extends Omit<
15 eventbridge.PutEventsRequestEntry,
16 "EventBusName"
17> {}
18
19export type BusSinkError =
20 | eventbridge.PutEventsError
21 | BatchRetryExhaustedError<BusSinkEntry>;
22
23/**
24 * A batching sink over EventBridge `PutEvents` (10 entries / 256 KiB per
25 * call). Per-entry failures with transient error codes (`ThrottlingException`,
26 * `InternalFailure`) are re-submitted on a bounded schedule; any other
27 * per-entry `ErrorCode` (e.g. `MalformedDetail`) is permanent — those entries
28 * are dropped and surfaced via a logged warning. Exhausting retries fails the
29 * sink with a typed `BatchRetryExhaustedError` carrying the stranded entries.
30 *
31 * Omit the bus argument to publish to the account's default event bus.
32 *
33 * ### Streaming Events
34 * **Example:** Run a Stream of Entries into the Bus
35 * ```typescript
36 * // init — bind the sink (provide AWS.EventBridge.BusSinkHttp on the Function)
37 * const sink = yield* AWS.EventBridge.BusSink(bus);
38 *
39 * return {
40 * fetch: Effect.gen(function* () {
41 * // runtime — publish a stream of raw PutEvents entries
42 * const entries: AWS.EventBridge.BusSinkEntry[] = markers.map((marker) => ({
43 * Source: "my.app",
44 * DetailType: "MarkerSeen",
45 * Detail: JSON.stringify({ marker }),
46 * }));
47 * yield* Stream.fromIterable(entries).pipe(Stream.run(sink));
48 * return HttpServerResponse.json({ ok: true });
49 * }),
50 * };
51 * ```
52 *
53 * @binding
54 */
55export interface BusSink extends Binding.Service<
56 BusSink,
57 "AWS.EventBridge.BusSink",
58 (
59 bus?: EventBus,
60 ) => Effect.Effect<
61 Sink.Sink<void, BusSinkEntry, readonly BusSinkEntry[], BusSinkError>
62 >
63> {}
64
65export const BusSink = Binding.Service<BusSink>("AWS.EventBridge.BusSink");