1import type * as Effect from "effect/Effect";
2import type * as Stream from "effect/Stream";
3import {
4 consumeBusEvents,
5 type EventRecord,
6 type EventRouteProps,
7} from "../EventBridge/EventSource.ts";
8
9/**
10 * The `detail` payload Amazon Transcribe delivers to EventBridge when a
11 * batch transcription job finishes (`Transcribe Job State Change`, statuses
12 * `COMPLETED` and `FAILED` only — Transcribe does not emit intermediate
13 * states).
14 */
15export interface TranscriptionJobEventDetail {
16 /** The transcription job's name. */
17 TranscriptionJobName?: string;
18 /** The terminal status: `COMPLETED` or `FAILED`. */
19 TranscriptionJobStatus?: string;
20 /** Why the job failed — only present on `FAILED` events. */
21 FailureReason?: string;
22 /** Additional event fields (the schema grows over time). */
23 [key: string]: unknown;
24}
25
26/** A Transcribe job EventBridge event delivered to the handler. */
27export type TranscriptionJobEvent = EventRecord<TranscriptionJobEventDetail>;
28
29/**
30 * The `detail` payload for `Call Analytics Job State Change` events.
31 */
32export interface CallAnalyticsJobEventDetail {
33 /** The Call Analytics job's name. */
34 JobName?: string;
35 /** The terminal status: `COMPLETED` or `FAILED`. */
36 JobStatus?: string;
37 /** Why the job failed — only present on `FAILED` events. */
38 FailureReason?: string;
39 /** Additional event fields (the schema grows over time). */
40 [key: string]: unknown;
41}
42
43/** A Call Analytics job EventBridge event delivered to the handler. */
44export type CallAnalyticsJobEvent = EventRecord<CallAnalyticsJobEventDetail>;
45
46/**
47 * The `detail` payload for `Medical Scribe Job State Change` events.
48 */
49export interface MedicalScribeJobEventDetail {
50 /** The Medical Scribe job's name. */
51 MedicalScribeJobName?: string;
52 /** The terminal status: `COMPLETED` or `FAILED`. */
53 MedicalScribeJobStatus?: string;
54 /** Why the job failed — only present on `FAILED` events. */
55 FailureReason?: string;
56 /** Additional event fields (the schema grows over time). */
57 [key: string]: unknown;
58}
59
60/** A Medical Scribe job EventBridge event delivered to the handler. */
61export type MedicalScribeJobEvent = EventRecord<MedicalScribeJobEventDetail>;
62
63/**
64 * The `detail` payload for `Vocabulary State Change` events (custom
65 * vocabulary processing finished).
66 */
67export interface VocabularyEventDetail {
68 /** The custom vocabulary's name. */
69 VocabularyName?: string;
70 /** The terminal state: `READY` or `FAILED`. */
71 VocabularyState?: string;
72 /** Why processing failed — only present on `FAILED` events. */
73 FailureReason?: string;
74 /** Additional event fields (the schema grows over time). */
75 [key: string]: unknown;
76}
77
78/** A vocabulary EventBridge event delivered to the handler. */
79export type VocabularyEvent = EventRecord<VocabularyEventDetail>;
80
81/**
82 * The `detail` payload for `Language Model State Change` events (custom
83 * language model training finished).
84 */
85export interface LanguageModelEventDetail {
86 /** The custom language model's name. */
87 ModelName?: string;
88 /** The terminal status: `COMPLETED` or `FAILED`. */
89 ModelStatus?: string;
90 /** Why training failed — only present on `FAILED` events. */
91 FailureReason?: string;
92 /** Additional event fields (the schema grows over time). */
93 [key: string]: unknown;
94}
95
96/** A language model EventBridge event delivered to the handler. */
97export type LanguageModelEvent = EventRecord<LanguageModelEventDetail>;
98
99export interface TranscriptionJobEventSourceProps extends EventRouteProps {
100 /**
101 * Logical id for the backing EventBridge rule.
102 * @default "TranscribeJobEvents"
103 */
104 id?: string;
105 /**
106 * Only deliver events with these `detail.TranscriptionJobStatus` values
107 * (e.g. `["COMPLETED"]`).
108 * @default all statuses
109 */
110 statuses?: readonly string[];
111}
112
113/**
114 * Event source connecting Amazon Transcribe batch job completions to the
115 * hosting compute. Transcribe publishes a `Transcribe Job State Change`
116 * event (source `aws.transcribe`) to the account's default EventBridge bus
117 * when a batch transcription job reaches `COMPLETED` or `FAILED`; this
118 * subscribes the host Function to those events so it can chain
119 * post-transcription processing without polling {@link GetTranscriptionJob}.
120 *
121 * Transcribe publishes to EventBridge automatically — no additional
122 * resource is created besides the EventBridge rule targeting the host.
123 * Provide the host-specific implementation layer (e.g.
124 * `AWS.Lambda.EventSource`) on the Function effect.
125 *
126 * ### Consuming Job Events
127 * **Example:** React To Finished Transcriptions
128 * ```typescript
129 * import * as AWS from "alchemy/AWS";
130 *
131 * export default TranscriptReactor.make(
132 * { main: import.meta.url },
133 * Effect.gen(function* () {
134 * yield* AWS.Transcribe.consumeTranscriptionJobEvents(
135 * { statuses: ["COMPLETED", "FAILED"] },
136 * (events) =>
137 * Stream.runForEach(events, (event) =>
138 * event.detail.TranscriptionJobStatus === "FAILED"
139 * ? Effect.log(`job ${event.detail.TranscriptionJobName} failed: ${event.detail.FailureReason}`)
140 * : Effect.log(`job ${event.detail.TranscriptionJobName} complete`),
141 * ),
142 * );
143 * return {};
144 * }).pipe(Effect.provide(AWS.Lambda.EventSource)),
145 * );
146 * ```
147 */
148export const consumeTranscriptionJobEvents = <StreamReq = never, Req = never>(
149 props: TranscriptionJobEventSourceProps,
150 process: (
151 events: Stream.Stream<TranscriptionJobEvent, never, StreamReq>,
152 ) => Effect.Effect<void, never, Req>,
153) =>
154 consumeBusEvents(
155 props.id ?? "TranscribeJobEvents",
156 {
157 source: ["aws.transcribe"],
158 "detail-type": ["Transcribe Job State Change"],
159 ...(props.statuses
160 ? { detail: { TranscriptionJobStatus: [...props.statuses] } }
161 : {}),
162 },
163 { description: props.description, state: props.state },
164 process,
165 );
166
167export interface CallAnalyticsJobEventSourceProps extends EventRouteProps {
168 /**
169 * Logical id for the backing EventBridge rule.
170 * @default "TranscribeCallAnalyticsJobEvents"
171 */
172 id?: string;
173 /**
174 * Only deliver events with these `detail.JobStatus` values.
175 * @default all statuses
176 */
177 statuses?: readonly string[];
178}
179
180/**
181 * Event source for Amazon Transcribe `Call Analytics Job State Change`
182 * events (source `aws.transcribe`) — fires when a Call Analytics job
183 * reaches `COMPLETED` or `FAILED`.
184 *
185 * ### Consuming Job Events
186 * **Example:** React To Finished Call Analytics Jobs
187 * ```typescript
188 * yield* AWS.Transcribe.consumeCallAnalyticsJobEvents(
189 * { statuses: ["COMPLETED"] },
190 * (events) =>
191 * Stream.runForEach(events, (event) =>
192 * Effect.log(`call ${event.detail.JobName} analyzed`),
193 * ),
194 * );
195 * ```
196 */
197export const consumeCallAnalyticsJobEvents = <StreamReq = never, Req = never>(
198 props: CallAnalyticsJobEventSourceProps,
199 process: (
200 events: Stream.Stream<CallAnalyticsJobEvent, never, StreamReq>,
201 ) => Effect.Effect<void, never, Req>,
202) =>
203 consumeBusEvents(
204 props.id ?? "TranscribeCallAnalyticsJobEvents",
205 {
206 source: ["aws.transcribe"],
207 "detail-type": ["Call Analytics Job State Change"],
208 ...(props.statuses ? { detail: { JobStatus: [...props.statuses] } } : {}),
209 },
210 { description: props.description, state: props.state },
211 process,
212 );
213
214export interface MedicalScribeJobEventSourceProps extends EventRouteProps {
215 /**
216 * Logical id for the backing EventBridge rule.
217 * @default "TranscribeMedicalScribeJobEvents"
218 */
219 id?: string;
220 /**
221 * Only deliver events with these `detail.MedicalScribeJobStatus` values.
222 * @default all statuses
223 */
224 statuses?: readonly string[];
225}
226
227/**
228 * Event source for AWS HealthScribe `Medical Scribe Job State Change`
229 * events (source `aws.transcribe`) — fires when a Medical Scribe job
230 * reaches `COMPLETED` or `FAILED`.
231 *
232 * ### Consuming Job Events
233 * **Example:** React To Finished Medical Scribe Jobs
234 * ```typescript
235 * yield* AWS.Transcribe.consumeMedicalScribeJobEvents(
236 * { statuses: ["COMPLETED"] },
237 * (events) =>
238 * Stream.runForEach(events, (event) =>
239 * Effect.log(`visit ${event.detail.MedicalScribeJobName} summarized`),
240 * ),
241 * );
242 * ```
243 */
244export const consumeMedicalScribeJobEvents = <StreamReq = never, Req = never>(
245 props: MedicalScribeJobEventSourceProps,
246 process: (
247 events: Stream.Stream<MedicalScribeJobEvent, never, StreamReq>,
248 ) => Effect.Effect<void, never, Req>,
249) =>
250 consumeBusEvents(
251 props.id ?? "TranscribeMedicalScribeJobEvents",
252 {
253 source: ["aws.transcribe"],
254 "detail-type": ["Medical Scribe Job State Change"],
255 ...(props.statuses
256 ? { detail: { MedicalScribeJobStatus: [...props.statuses] } }
257 : {}),
258 },
259 { description: props.description, state: props.state },
260 process,
261 );
262
263export interface VocabularyEventSourceProps extends EventRouteProps {
264 /**
265 * Logical id for the backing EventBridge rule.
266 * @default "TranscribeVocabularyEvents"
267 */
268 id?: string;
269 /**
270 * Only deliver events with these `detail.VocabularyState` values
271 * (e.g. `["READY"]`).
272 * @default all states
273 */
274 states?: readonly string[];
275}
276
277/**
278 * Event source for Amazon Transcribe `Vocabulary State Change` events
279 * (source `aws.transcribe`) — fires when custom vocabulary processing
280 * reaches `READY` or `FAILED`, so runtime-created vocabularies (e.g.
281 * per-tenant via {@link CreateVocabulary}) can be used the moment they are
282 * ready.
283 *
284 * ### Consuming Job Events
285 * **Example:** React To Ready Vocabularies
286 * ```typescript
287 * yield* AWS.Transcribe.consumeVocabularyEvents(
288 * { states: ["READY"] },
289 * (events) =>
290 * Stream.runForEach(events, (event) =>
291 * Effect.log(`vocabulary ${event.detail.VocabularyName} ready`),
292 * ),
293 * );
294 * ```
295 */
296export const consumeVocabularyEvents = <StreamReq = never, Req = never>(
297 props: VocabularyEventSourceProps,
298 process: (
299 events: Stream.Stream<VocabularyEvent, never, StreamReq>,
300 ) => Effect.Effect<void, never, Req>,
301) =>
302 consumeBusEvents(
303 props.id ?? "TranscribeVocabularyEvents",
304 {
305 source: ["aws.transcribe"],
306 "detail-type": ["Vocabulary State Change"],
307 ...(props.states
308 ? { detail: { VocabularyState: [...props.states] } }
309 : {}),
310 },
311 { description: props.description, state: props.state },
312 process,
313 );
314
315export interface LanguageModelEventSourceProps extends EventRouteProps {
316 /**
317 * Logical id for the backing EventBridge rule.
318 * @default "TranscribeLanguageModelEvents"
319 */
320 id?: string;
321 /**
322 * Only deliver events with these `detail.ModelStatus` values.
323 * @default all statuses
324 */
325 statuses?: readonly string[];
326}
327
328/**
329 * Event source for Amazon Transcribe `Language Model State Change` events
330 * (source `aws.transcribe`) — fires when custom language model training
331 * (started with {@link CreateLanguageModel}) reaches `COMPLETED` or
332 * `FAILED`.
333 *
334 * ### Consuming Job Events
335 * **Example:** React To Trained Language Models
336 * ```typescript
337 * yield* AWS.Transcribe.consumeLanguageModelEvents(
338 * { statuses: ["COMPLETED"] },
339 * (events) =>
340 * Stream.runForEach(events, (event) =>
341 * Effect.log(`model ${event.detail.ModelName} trained`),
342 * ),
343 * );
344 * ```
345 */
346export const consumeLanguageModelEvents = <StreamReq = never, Req = never>(
347 props: LanguageModelEventSourceProps,
348 process: (
349 events: Stream.Stream<LanguageModelEvent, never, StreamReq>,
350 ) => Effect.Effect<void, never, Req>,
351) =>
352 consumeBusEvents(
353 props.id ?? "TranscribeLanguageModelEvents",
354 {
355 source: ["aws.transcribe"],
356 "detail-type": ["Language Model State Change"],
357 ...(props.statuses
358 ? { detail: { ModelStatus: [...props.statuses] } }
359 : {}),
360 },
361 { description: props.description, state: props.state },
362 process,
363 );